diff options
Diffstat (limited to 'lldb/source/Plugins/Process')
274 files changed, 60707 insertions, 64958 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 ©) : _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> ©) { + 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__ - diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 3cb1cec6983..fae41d004c9 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -16,684 +16,603 @@ #include "lldb/Target/UnixSignals.h" // Project includes -#include "lldb/Breakpoint/Watchpoint.h" +#include "FreeBSDThread.h" +#include "POSIXStopInfo.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/UnwindLLDB.h" +#include "ProcessFreeBSD.h" +#include "ProcessMonitor.h" +#include "ProcessPOSIXLog.h" +#include "RegisterContextPOSIXProcessMonitor_arm.h" +#include "RegisterContextPOSIXProcessMonitor_arm64.h" +#include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" -#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/HostNativeThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" #include "llvm/ADT/SmallString.h" -#include "POSIXStopInfo.h" -#include "FreeBSDThread.h" -#include "ProcessFreeBSD.h" -#include "ProcessPOSIXLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" -#include "RegisterContextPOSIXProcessMonitor_arm64.h" -#include "RegisterContextPOSIXProcessMonitor_mips64.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" -#include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/UnwindLLDB.h" using namespace lldb; using namespace lldb_private; FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), - m_frame_ap (), - m_breakpoint (), - m_thread_name_valid (false), - m_thread_name (), - m_posix_thread(NULL) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); - - // Set the current watchpoints for this thread. - Target &target = GetProcess()->GetTarget(); - const WatchpointList &wp_list = target.GetWatchpointList(); - size_t wp_size = wp_list.GetSize(); - - for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) - { - lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); - if (wp.get() && wp->IsEnabled()) - { - // This watchpoint as been enabled; obviously this "new" thread - // has been created since that watchpoint was enabled. Since - // the POSIXBreakpointProtocol has yet to be initialized, its - // m_watchpoints_initialized member will be FALSE. Attempting to - // read the debug status register to determine if a watchpoint - // has been hit would result in the zeroing of that register. - // Since the active debug registers would have been cloned when - // this thread was created, simply force the m_watchpoints_initized - // member to TRUE and avoid resetting dr6 and dr7. - GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); - } + : Thread(process, tid), m_frame_ap(), m_breakpoint(), + m_thread_name_valid(false), m_thread_name(), m_posix_thread(NULL) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); + + // Set the current watchpoints for this thread. + Target &target = GetProcess()->GetTarget(); + const WatchpointList &wp_list = target.GetWatchpointList(); + size_t wp_size = wp_list.GetSize(); + + for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) { + lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); + if (wp.get() && wp->IsEnabled()) { + // This watchpoint as been enabled; obviously this "new" thread + // has been created since that watchpoint was enabled. Since + // the POSIXBreakpointProtocol has yet to be initialized, its + // m_watchpoints_initialized member will be FALSE. Attempting to + // read the debug status register to determine if a watchpoint + // has been hit would result in the zeroing of that register. + // Since the active debug registers would have been cloned when + // this thread was created, simply force the m_watchpoints_initized + // member to TRUE and avoid resetting dr6 and dr7. + GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); } + } } -FreeBSDThread::~FreeBSDThread() -{ - DestroyThread(); -} +FreeBSDThread::~FreeBSDThread() { DestroyThread(); } -ProcessMonitor & -FreeBSDThread::GetMonitor() -{ - ProcessSP base = GetProcess(); - ProcessFreeBSD &process = static_cast<ProcessFreeBSD&>(*base); - return process.GetMonitor(); +ProcessMonitor &FreeBSDThread::GetMonitor() { + ProcessSP base = GetProcess(); + ProcessFreeBSD &process = static_cast<ProcessFreeBSD &>(*base); + return process.GetMonitor(); } -void -FreeBSDThread::RefreshStateAfterStop() -{ - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do - // the right thing. - //if (StateIsStoppedState(GetState()) - { - const bool force = false; - GetRegisterContext()->InvalidateIfNeeded (force); - } +void FreeBSDThread::RefreshStateAfterStop() { + // Invalidate all registers in our register context. We don't set "force" to + // true because the stop reply packet might have had some register values + // that were expedited and these will already be copied into the register + // context by the time this function gets called. The KDPRegisterContext + // class has been made smart enough to detect when it needs to invalidate + // which registers are valid by putting hooks in the register read and + // register supply functions where they check the process stop ID and do + // the right thing. + // if (StateIsStoppedState(GetState()) + { + const bool force = false; + GetRegisterContext()->InvalidateIfNeeded(force); + } } -const char * -FreeBSDThread::GetInfo() -{ - return NULL; -} +const char *FreeBSDThread::GetInfo() { return NULL; } -void -FreeBSDThread::SetName (const char *name) -{ - m_thread_name_valid = (name && name[0]); - if (m_thread_name_valid) - m_thread_name.assign (name); - else - m_thread_name.clear(); +void FreeBSDThread::SetName(const char *name) { + m_thread_name_valid = (name && name[0]); + if (m_thread_name_valid) + m_thread_name.assign(name); + else + m_thread_name.clear(); } -const char * -FreeBSDThread::GetName () -{ - if (!m_thread_name_valid) - { - llvm::SmallString<32> thread_name; - HostNativeThread::GetName(GetID(), thread_name); - m_thread_name = thread_name.c_str(); - m_thread_name_valid = true; - } +const char *FreeBSDThread::GetName() { + if (!m_thread_name_valid) { + llvm::SmallString<32> thread_name; + HostNativeThread::GetName(GetID(), thread_name); + m_thread_name = thread_name.c_str(); + m_thread_name_valid = true; + } - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); + if (m_thread_name.empty()) + return NULL; + return m_thread_name.c_str(); } -lldb::RegisterContextSP -FreeBSDThread::GetRegisterContext() -{ - if (!m_reg_context_sp) - { - m_posix_thread = NULL; - - RegisterInfoInterface *reg_interface = NULL; - const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); - - assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD); - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - reg_interface = new RegisterContextFreeBSD_arm64(target_arch); - break; - case llvm::Triple::arm: - reg_interface = new RegisterContextFreeBSD_arm(target_arch); - break; - case llvm::Triple::ppc: +lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() { + if (!m_reg_context_sp) { + m_posix_thread = NULL; + + RegisterInfoInterface *reg_interface = NULL; + const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); + + assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD); + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + reg_interface = new RegisterContextFreeBSD_arm64(target_arch); + break; + case llvm::Triple::arm: + reg_interface = new RegisterContextFreeBSD_arm(target_arch); + break; + case llvm::Triple::ppc: #ifndef __powerpc64__ - reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); - break; + reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); + break; #endif - case llvm::Triple::ppc64: - reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); - break; - case llvm::Triple::mips64: - reg_interface = new RegisterContextFreeBSD_mips64(target_arch); - break; - case llvm::Triple::x86: - reg_interface = new RegisterContextFreeBSD_i386(target_arch); - break; - case llvm::Triple::x86_64: - reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); - break; - default: - llvm_unreachable("CPU not supported"); - } + case llvm::Triple::ppc64: + reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); + break; + case llvm::Triple::mips64: + reg_interface = new RegisterContextFreeBSD_mips64(target_arch); + break; + case llvm::Triple::x86: + reg_interface = new RegisterContextFreeBSD_i386(target_arch); + break; + case llvm::Triple::x86_64: + reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); + break; + default: + llvm_unreachable("CPU not supported"); + } - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - { - RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::arm: - { - RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::mips64: - { - RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - { - RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - default: - break; - } + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: { + RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = + new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + break; + } + case llvm::Triple::arm: { + RegisterContextPOSIXProcessMonitor_arm *reg_ctx = + new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + break; + } + case llvm::Triple::mips64: { + RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = + new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, + reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + break; + } + case llvm::Triple::ppc: + case llvm::Triple::ppc64: { + RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = + new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, + reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + break; } - return m_reg_context_sp; + case llvm::Triple::x86: + case llvm::Triple::x86_64: { + RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = + new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, + reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + break; + } + default: + break; + } + } + return m_reg_context_sp; } lldb::RegisterContextSP -FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("FreeBSDThread::%s ()", __FUNCTION__); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else - { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); - } +FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; - return reg_ctx_sp; -} + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf("FreeBSDThread::%s ()", __FUNCTION__); -lldb::addr_t -FreeBSDThread::GetThreadPointer () -{ - ProcessMonitor &monitor = GetMonitor(); - addr_t addr; - if (monitor.ReadThreadPointer (GetID(), addr)) - return addr; - else - return LLDB_INVALID_ADDRESS; -} + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); -bool -FreeBSDThread::CalculateStopInfo() -{ - SetStopInfo (m_stop_info_sp); - return true; -} + if (concrete_frame_idx == 0) + reg_ctx_sp = GetRegisterContext(); + else { + assert(GetUnwinder()); + reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); + } -Unwind * -FreeBSDThread::GetUnwinder() -{ - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - - return m_unwinder_ap.get(); + return reg_ctx_sp; } -void -FreeBSDThread::DidStop() -{ - // Don't set the thread state to stopped unless we really stopped. +lldb::addr_t FreeBSDThread::GetThreadPointer() { + ProcessMonitor &monitor = GetMonitor(); + addr_t addr; + if (monitor.ReadThreadPointer(GetID(), addr)) + return addr; + else + return LLDB_INVALID_ADDRESS; } -void -FreeBSDThread::WillResume(lldb::StateType resume_state) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf("tid %lu resume_state = %s", GetID(), - lldb_private::StateAsCString(resume_state)); - ProcessSP process_sp(GetProcess()); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get()); - int signo = GetResumeSignal(); - bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo); - - switch (resume_state) - { - case eStateSuspended: - case eStateStopped: - process->m_suspend_tids.push_back(GetID()); - break; - case eStateRunning: - process->m_run_tids.push_back(GetID()); - if (signo_valid) - process->m_resume_signo = signo; - break; - case eStateStepping: - process->m_step_tids.push_back(GetID()); - if (signo_valid) - process->m_resume_signo = signo; - break; - default: - break; - } +bool FreeBSDThread::CalculateStopInfo() { + SetStopInfo(m_stop_info_sp); + return true; } -bool -FreeBSDThread::Resume() -{ - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, - StateAsCString(resume_state)); +Unwind *FreeBSDThread::GetUnwinder() { + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); - switch (resume_state) - { - default: - assert(false && "Unexpected state for resume!"); - status = false; - break; - - case lldb::eStateRunning: - SetState(resume_state); - status = monitor.Resume(GetID(), GetResumeSignal()); - break; - - case lldb::eStateStepping: - SetState(resume_state); - status = monitor.SingleStep(GetID(), GetResumeSignal()); - break; - case lldb::eStateStopped: - case lldb::eStateSuspended: - status = true; - break; - } - - return status; + return m_unwinder_ap.get(); } -void -FreeBSDThread::Notify(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, - __FUNCTION__, message.PrintKind(), GetID()); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected message kind!"); - break; - - case ProcessMessage::eExitMessage: - // Nothing to be done. - break; - - case ProcessMessage::eLimboMessage: - LimboNotify(message); - break; - - case ProcessMessage::eSignalMessage: - SignalNotify(message); - break; - - case ProcessMessage::eSignalDeliveredMessage: - SignalDeliveredNotify(message); - break; - - case ProcessMessage::eTraceMessage: - TraceNotify(message); - break; - - case ProcessMessage::eBreakpointMessage: - BreakNotify(message); - break; - - case ProcessMessage::eWatchpointMessage: - WatchNotify(message); - break; +void FreeBSDThread::DidStop() { + // Don't set the thread state to stopped unless we really stopped. +} - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; +void FreeBSDThread::WillResume(lldb::StateType resume_state) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log) + log->Printf("tid %lu resume_state = %s", GetID(), + lldb_private::StateAsCString(resume_state)); + ProcessSP process_sp(GetProcess()); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get()); + int signo = GetResumeSignal(); + bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo); + + switch (resume_state) { + case eStateSuspended: + case eStateStopped: + process->m_suspend_tids.push_back(GetID()); + break; + case eStateRunning: + process->m_run_tids.push_back(GetID()); + if (signo_valid) + process->m_resume_signo = signo; + break; + case eStateStepping: + process->m_step_tids.push_back(GetID()); + if (signo_valid) + process->m_resume_signo = signo; + break; + default: + break; + } +} - case ProcessMessage::eExecMessage: - ExecNotify(message); - break; - } +bool FreeBSDThread::Resume() { + lldb::StateType resume_state = GetResumeState(); + ProcessMonitor &monitor = GetMonitor(); + bool status; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log) + log->Printf("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, + StateAsCString(resume_state)); + + switch (resume_state) { + default: + assert(false && "Unexpected state for resume!"); + status = false; + break; + + case lldb::eStateRunning: + SetState(resume_state); + status = monitor.Resume(GetID(), GetResumeSignal()); + break; + + case lldb::eStateStepping: + SetState(resume_state); + status = monitor.SingleStep(GetID(), GetResumeSignal()); + break; + case lldb::eStateStopped: + case lldb::eStateSuspended: + status = true; + break; + } + + return status; } -bool -FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) -{ - bool wp_set = false; - if (wp) - { - addr_t wp_addr = wp->GetLoadAddress(); - size_t wp_size = wp->GetByteSize(); - bool wp_read = wp->WatchpointRead(); - bool wp_write = wp->WatchpointWrite(); - uint32_t wp_hw_index = wp->GetHardwareIndex(); - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) - wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, - wp_read, wp_write, - wp_hw_index); - } - return wp_set; +void FreeBSDThread::Notify(const ProcessMessage &message) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log) + log->Printf("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, + __FUNCTION__, message.PrintKind(), GetID()); + + switch (message.GetKind()) { + default: + assert(false && "Unexpected message kind!"); + break; + + case ProcessMessage::eExitMessage: + // Nothing to be done. + break; + + case ProcessMessage::eLimboMessage: + LimboNotify(message); + break; + + case ProcessMessage::eSignalMessage: + SignalNotify(message); + break; + + case ProcessMessage::eSignalDeliveredMessage: + SignalDeliveredNotify(message); + break; + + case ProcessMessage::eTraceMessage: + TraceNotify(message); + break; + + case ProcessMessage::eBreakpointMessage: + BreakNotify(message); + break; + + case ProcessMessage::eWatchpointMessage: + WatchNotify(message); + break; + + case ProcessMessage::eCrashMessage: + CrashNotify(message); + break; + + case ProcessMessage::eExecMessage: + ExecNotify(message); + break; + } } -bool -FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) -{ - bool result = false; - if (wp) - { - lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); - if (reg_ctx_sp.get()) - result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); - } - return result; +bool FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) { + bool wp_set = false; + if (wp) { + addr_t wp_addr = wp->GetLoadAddress(); + size_t wp_size = wp->GetByteSize(); + bool wp_read = wp->WatchpointRead(); + bool wp_write = wp->WatchpointWrite(); + uint32_t wp_hw_index = wp->GetHardwareIndex(); + POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) + wp_set = reg_ctx->SetHardwareWatchpointWithIndex( + wp_addr, wp_size, wp_read, wp_write, wp_hw_index); + } + return wp_set; } -uint32_t -FreeBSDThread::NumSupportedHardwareWatchpoints() -{ +bool FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) { + bool result = false; + if (wp) { lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); if (reg_ctx_sp.get()) - return reg_ctx_sp->NumSupportedHardwareWatchpoints(); - return 0; + result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); + } + return result; } -uint32_t -FreeBSDThread::FindVacantWatchpointIndex() -{ - uint32_t hw_index = LLDB_INVALID_INDEX32; - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) - { - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) - { - if (reg_ctx->IsWatchpointVacant(wp_idx)) - { - hw_index = wp_idx; - break; - } - } +uint32_t FreeBSDThread::NumSupportedHardwareWatchpoints() { + lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); + if (reg_ctx_sp.get()) + return reg_ctx_sp->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t FreeBSDThread::FindVacantWatchpointIndex() { + uint32_t hw_index = LLDB_INVALID_INDEX32; + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + uint32_t wp_idx; + POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) { + for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { + if (reg_ctx->IsWatchpointVacant(wp_idx)) { + hw_index = wp_idx; + break; + } } - return hw_index; + } + return hw_index; } -void -FreeBSDThread::BreakNotify(const ProcessMessage &message) -{ - bool status; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - - assert(GetRegisterContext()); - status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); - assert(status && "Breakpoint update failed!"); - - // With our register state restored, resolve the breakpoint object - // corresponding to our current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf ("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); - - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we create a stop reason with should_stop=false. If there is no breakpoint location, then report - // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will - // be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - if (bp_site) - { - lldb::break_id_t bp_id = bp_site->GetID(); - // If we have an operating system plug-in, we might have set a thread specific breakpoint using the - // operating system thread ID, so we can't make any assumptions about the thread ID so we must always - // report the breakpoint regardless of the thread. - if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL) - SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); - else - { - const bool should_stop = false; - SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); - } +void FreeBSDThread::BreakNotify(const ProcessMessage &message) { + bool status; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + + assert(GetRegisterContext()); + status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); + assert(status && "Breakpoint update failed!"); + + // With our register state restored, resolve the breakpoint object + // corresponding to our current PC. + assert(GetRegisterContext()); + lldb::addr_t pc = GetRegisterContext()->GetPC(); + if (log) + log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + lldb::BreakpointSiteSP bp_site( + GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); + + // If the breakpoint is for this thread, then we'll report the hit, but if it + // is for another thread, + // we create a stop reason with should_stop=false. If there is no breakpoint + // location, then report + // an invalid stop reason. We don't need to worry about stepping over the + // breakpoint here, that will + // be taken care of when the thread resumes and notices that there's a + // breakpoint under the pc. + if (bp_site) { + lldb::break_id_t bp_id = bp_site->GetID(); + // If we have an operating system plug-in, we might have set a thread + // specific breakpoint using the + // operating system thread ID, so we can't make any assumptions about the + // thread ID so we must always + // report the breakpoint regardless of the thread. + if (bp_site->ValidForThisThread(this) || + GetProcess()->GetOperatingSystem() != NULL) + SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); + else { + const bool should_stop = false; + SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, + should_stop)); } - else - SetStopInfo(StopInfoSP()); + } else + SetStopInfo(StopInfoSP()); } -void -FreeBSDThread::WatchNotify(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +void FreeBSDThread::WatchNotify(const ProcessMessage &message) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - lldb::addr_t halt_addr = message.GetHWAddress(); - if (log) - log->Printf ("FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" - PRIx64, __FUNCTION__, halt_addr); + lldb::addr_t halt_addr = message.GetHWAddress(); + if (log) + log->Printf( + "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, + __FUNCTION__, halt_addr); - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) - { - uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) - { - if (reg_ctx->IsWatchpointHit(wp_idx)) - { - // Clear the watchpoint hit here - reg_ctx->ClearWatchpointHits(); - break; - } - } + POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) { + uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); + uint32_t wp_idx; + for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { + if (reg_ctx->IsWatchpointHit(wp_idx)) { + // Clear the watchpoint hit here + reg_ctx->ClearWatchpointHits(); + break; + } + } - if (wp_idx == num_hw_wps) - return; + if (wp_idx == num_hw_wps) + return; - Target &target = GetProcess()->GetTarget(); - lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); - const WatchpointList &wp_list = target.GetWatchpointList(); - lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); + Target &target = GetProcess()->GetTarget(); + lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); + const WatchpointList &wp_list = target.GetWatchpointList(); + lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); - assert(wp_sp.get() && "No watchpoint found"); - SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this, - wp_sp->GetID())); - } + assert(wp_sp.get() && "No watchpoint found"); + SetStopInfo( + StopInfo::CreateStopReasonWithWatchpointID(*this, wp_sp->GetID())); + } } -void -FreeBSDThread::TraceNotify(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - - // Try to resolve the breakpoint object corresponding to the current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf ("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); - - // If the current pc is a breakpoint site then set the StopInfo to Breakpoint. - // Otherwise, set the StopInfo to Watchpoint or Trace. - // If we have an operating system plug-in, we might have set a thread specific breakpoint using the - // operating system thread ID, so we can't make any assumptions about the thread ID so we must always - // report the breakpoint regardless of the thread. - if (bp_site && (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)) - SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_site->GetID())); - else - { - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) - { - uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) - { - if (reg_ctx->IsWatchpointHit(wp_idx)) - { - WatchNotify(message); - return; - } - } +void FreeBSDThread::TraceNotify(const ProcessMessage &message) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + + // Try to resolve the breakpoint object corresponding to the current PC. + assert(GetRegisterContext()); + lldb::addr_t pc = GetRegisterContext()->GetPC(); + if (log) + log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + lldb::BreakpointSiteSP bp_site( + GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); + + // If the current pc is a breakpoint site then set the StopInfo to Breakpoint. + // Otherwise, set the StopInfo to Watchpoint or Trace. + // If we have an operating system plug-in, we might have set a thread specific + // breakpoint using the + // operating system thread ID, so we can't make any assumptions about the + // thread ID so we must always + // report the breakpoint regardless of the thread. + if (bp_site && (bp_site->ValidForThisThread(this) || + GetProcess()->GetOperatingSystem() != NULL)) + SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( + *this, bp_site->GetID())); + else { + POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) { + uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); + uint32_t wp_idx; + for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { + if (reg_ctx->IsWatchpointHit(wp_idx)) { + WatchNotify(message); + return; } - SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); + } } + SetStopInfo(StopInfo::CreateStopReasonToTrace(*this)); + } } -void -FreeBSDThread::LimboNotify(const ProcessMessage &message) -{ - SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); +void FreeBSDThread::LimboNotify(const ProcessMessage &message) { + SetStopInfo(lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); } -void -FreeBSDThread::SignalNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +void FreeBSDThread::SignalNotify(const ProcessMessage &message) { + int signo = message.GetSignal(); + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); } -void -FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { + int signo = message.GetSignal(); + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); } -void -FreeBSDThread::CrashNotify(const ProcessMessage &message) -{ - // FIXME: Update stop reason as per bugzilla 14598 - int signo = message.GetSignal(); +void FreeBSDThread::CrashNotify(const ProcessMessage &message) { + // FIXME: Update stop reason as per bugzilla 14598 + int signo = message.GetSignal(); - assert(message.GetKind() == ProcessMessage::eCrashMessage); + assert(message.GetKind() == ProcessMessage::eCrashMessage); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("FreeBSDThread::%s () signo = %i, reason = '%s'", - __FUNCTION__, signo, message.PrintCrashReason()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + if (log) + log->Printf("FreeBSDThread::%s () signo = %i, reason = '%s'", __FUNCTION__, + signo, message.PrintCrashReason()); - SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, - message.GetCrashReason(), - message.GetFaultAddress()))); + SetStopInfo(lldb::StopInfoSP(new POSIXCrashStopInfo( + *this, signo, message.GetCrashReason(), message.GetFaultAddress()))); } -unsigned -FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg = LLDB_INVALID_REGNUM; - ArchSpec arch = HostInfo::GetArchitecture(); - - switch (arch.GetMachine()) - { - default: - llvm_unreachable("CPU type not supported!"); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::mips64: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - reg = reg_ctx->GetRegisterIndexFromOffset(offset); - } - break; - } - return reg; +unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) { + unsigned reg = LLDB_INVALID_REGNUM; + ArchSpec arch = HostInfo::GetArchitecture(); + + switch (arch.GetMachine()) { + default: + llvm_unreachable("CPU type not supported!"); + break; + + case llvm::Triple::aarch64: + case llvm::Triple::arm: + case llvm::Triple::mips64: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::x86: + case llvm::Triple::x86_64: { + POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); + reg = reg_ctx->GetRegisterIndexFromOffset(offset); + } break; + } + return reg; } -void -FreeBSDThread::ExecNotify(const ProcessMessage &message) -{ - SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); +void FreeBSDThread::ExecNotify(const ProcessMessage &message) { + SetStopInfo(StopInfo::CreateStopReasonWithExec(*this)); } -const char * -FreeBSDThread::GetRegisterName(unsigned reg) -{ - const char * name = nullptr; - ArchSpec arch = HostInfo::GetArchitecture(); - - switch (arch.GetMachine()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::mips64: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - name = GetRegisterContext()->GetRegisterName(reg); - break; - } - return name; +const char *FreeBSDThread::GetRegisterName(unsigned reg) { + const char *name = nullptr; + ArchSpec arch = HostInfo::GetArchitecture(); + + switch (arch.GetMachine()) { + default: + assert(false && "CPU type not supported!"); + break; + + case llvm::Triple::aarch64: + case llvm::Triple::arm: + case llvm::Triple::mips64: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + name = GetRegisterContext()->GetRegisterName(reg); + break; + } + return name; } -const char * -FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) -{ - return GetRegisterName(GetRegisterIndexFromOffset(offset)); +const char *FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) { + return GetRegisterName(GetRegisterIndexFromOffset(offset)); } - diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h index 90c11dbefcb..72e84645955 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h +++ b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h @@ -15,8 +15,8 @@ #include <string> // Other libraries and framework includes -#include "lldb/Target/Thread.h" #include "RegisterContextPOSIX.h" +#include "lldb/Target/Thread.h" class ProcessMessage; class ProcessMonitor; @@ -25,118 +25,99 @@ class POSIXBreakpointProtocol; //------------------------------------------------------------------------------ // @class FreeBSDThread // @brief Abstraction of a FreeBSD thread. -class FreeBSDThread - : public lldb_private::Thread -{ +class FreeBSDThread : public lldb_private::Thread { public: + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid); - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~FreeBSDThread(); + virtual ~FreeBSDThread(); - // POSIXThread - void - RefreshStateAfterStop() override; + // POSIXThread + void RefreshStateAfterStop() override; - // This notifies the thread when a private stop occurs. - void - DidStop () override; + // This notifies the thread when a private stop occurs. + void DidStop() override; - const char * - GetInfo() override; + const char *GetInfo() override; - void - SetName (const char *name) override; + void SetName(const char *name) override; - const char * - GetName () override; + const char *GetName() override; - lldb::RegisterContextSP - GetRegisterContext() override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - lldb::addr_t - GetThreadPointer () override; + lldb::addr_t GetThreadPointer() override; - //-------------------------------------------------------------------------- - // These functions provide a mapping from the register offset - // back to the register index or name for use in debugging or log - // output. + //-------------------------------------------------------------------------- + // These functions provide a mapping from the register offset + // back to the register index or name for use in debugging or log + // output. - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - const char * - GetRegisterNameFromOffset(unsigned offset); + const char *GetRegisterNameFromOffset(unsigned offset); - //-------------------------------------------------------------------------- - // These methods form a specialized interface to POSIX threads. - // - bool Resume(); + //-------------------------------------------------------------------------- + // These methods form a specialized interface to POSIX threads. + // + bool Resume(); - void Notify(const ProcessMessage &message); + void Notify(const ProcessMessage &message); - //-------------------------------------------------------------------------- - // These methods provide an interface to watchpoints - // - bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp); + //-------------------------------------------------------------------------- + // These methods provide an interface to watchpoints + // + bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp); - bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp); + bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp); - uint32_t NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); - uint32_t FindVacantWatchpointIndex(); + uint32_t FindVacantWatchpointIndex(); protected: - POSIXBreakpointProtocol * - GetPOSIXBreakpointProtocol () - { - if (!m_reg_context_sp) - m_reg_context_sp = GetRegisterContext(); - return m_posix_thread; - } - - std::unique_ptr<lldb_private::StackFrame> m_frame_ap; - - lldb::BreakpointSiteSP m_breakpoint; - - bool m_thread_name_valid; - std::string m_thread_name; - POSIXBreakpointProtocol *m_posix_thread; - - ProcessMonitor & - GetMonitor(); - - bool - CalculateStopInfo() override; - - void BreakNotify(const ProcessMessage &message); - void WatchNotify(const ProcessMessage &message); - virtual void TraceNotify(const ProcessMessage &message); - void LimboNotify(const ProcessMessage &message); - void SignalNotify(const ProcessMessage &message); - void SignalDeliveredNotify(const ProcessMessage &message); - void CrashNotify(const ProcessMessage &message); - void ExitNotify(const ProcessMessage &message); - void ExecNotify(const ProcessMessage &message); - - lldb_private::Unwind * - GetUnwinder() override; - - //-------------------------------------------------------------------------- - // FreeBSDThread internal API. - - // POSIXThread override - virtual void - WillResume(lldb::StateType resume_state) override; + POSIXBreakpointProtocol *GetPOSIXBreakpointProtocol() { + if (!m_reg_context_sp) + m_reg_context_sp = GetRegisterContext(); + return m_posix_thread; + } + + std::unique_ptr<lldb_private::StackFrame> m_frame_ap; + + lldb::BreakpointSiteSP m_breakpoint; + + bool m_thread_name_valid; + std::string m_thread_name; + POSIXBreakpointProtocol *m_posix_thread; + + ProcessMonitor &GetMonitor(); + + bool CalculateStopInfo() override; + + void BreakNotify(const ProcessMessage &message); + void WatchNotify(const ProcessMessage &message); + virtual void TraceNotify(const ProcessMessage &message); + void LimboNotify(const ProcessMessage &message); + void SignalNotify(const ProcessMessage &message); + void SignalDeliveredNotify(const ProcessMessage &message); + void CrashNotify(const ProcessMessage &message); + void ExitNotify(const ProcessMessage &message); + void ExecNotify(const ProcessMessage &message); + + lldb_private::Unwind *GetUnwinder() override; + + //-------------------------------------------------------------------------- + // FreeBSDThread internal API. + + // POSIXThread override + virtual void WillResume(lldb::StateType resume_state) override; }; #endif // #ifndef liblldb_FreeBSDThread_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp index 409cf8c46b0..dfbd695899f 100644 --- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -12,81 +12,50 @@ using namespace lldb; using namespace lldb_private; - //===----------------------------------------------------------------------===// // POSIXLimboStopInfo -POSIXLimboStopInfo::~POSIXLimboStopInfo() { } +POSIXLimboStopInfo::~POSIXLimboStopInfo() {} -lldb::StopReason -POSIXLimboStopInfo::GetStopReason() const -{ - return lldb::eStopReasonThreadExiting; +lldb::StopReason POSIXLimboStopInfo::GetStopReason() const { + return lldb::eStopReasonThreadExiting; } -const char * -POSIXLimboStopInfo::GetDescription() -{ - return "thread exiting"; -} +const char *POSIXLimboStopInfo::GetDescription() { return "thread exiting"; } -bool -POSIXLimboStopInfo::ShouldStop(Event *event_ptr) -{ - return false; -} +bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; } -bool -POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) -{ - return false; -} +bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; } //===----------------------------------------------------------------------===// // POSIXCrashStopInfo -POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread, - uint32_t status, +POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status) -{ - m_description = ::GetCrashReasonString(reason, fault_addr); + : POSIXStopInfo(thread, status) { + m_description = ::GetCrashReasonString(reason, fault_addr); } -POSIXCrashStopInfo::~POSIXCrashStopInfo() { } +POSIXCrashStopInfo::~POSIXCrashStopInfo() {} -lldb::StopReason -POSIXCrashStopInfo::GetStopReason() const -{ - return lldb::eStopReasonException; +lldb::StopReason POSIXCrashStopInfo::GetStopReason() const { + return lldb::eStopReasonException; } //===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo -POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { } +POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {} -lldb::StopReason -POSIXNewThreadStopInfo::GetStopReason() const -{ - return lldb::eStopReasonNone; +lldb::StopReason POSIXNewThreadStopInfo::GetStopReason() const { + return lldb::eStopReasonNone; } -const char * -POSIXNewThreadStopInfo::GetDescription() -{ - return "thread spawned"; +const char *POSIXNewThreadStopInfo::GetDescription() { + return "thread spawned"; } -bool -POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) -{ - return false; -} +bool POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) { return false; } -bool -POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) -{ - return false; -} +bool POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) { return false; } diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h index ace6c98017b..1ee16dd5f8f 100644 --- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -25,58 +25,42 @@ /// @class POSIXStopInfo /// @brief Simple base class for all POSIX-specific StopInfo objects. /// -class POSIXStopInfo - : public lldb_private::StopInfo -{ +class POSIXStopInfo : public lldb_private::StopInfo { public: - POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) - : StopInfo(thread, status) - { } + POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) + : StopInfo(thread, status) {} }; //===----------------------------------------------------------------------===// /// @class POSIXLimboStopInfo /// @brief Represents the stop state of a process ready to exit. /// -class POSIXLimboStopInfo - : public POSIXStopInfo -{ +class POSIXLimboStopInfo : public POSIXStopInfo { public: - POSIXLimboStopInfo(FreeBSDThread &thread) - : POSIXStopInfo(thread, 0) - { } + POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {} - ~POSIXLimboStopInfo(); + ~POSIXLimboStopInfo(); - lldb::StopReason - GetStopReason() const; + lldb::StopReason GetStopReason() const; - const char * - GetDescription(); + const char *GetDescription(); - bool - ShouldStop(lldb_private::Event *event_ptr); + bool ShouldStop(lldb_private::Event *event_ptr); - bool - ShouldNotify(lldb_private::Event *event_ptr); + bool ShouldNotify(lldb_private::Event *event_ptr); }; - //===----------------------------------------------------------------------===// /// @class POSIXCrashStopInfo /// @brief Represents the stop state of process that is ready to crash. /// -class POSIXCrashStopInfo - : public POSIXStopInfo -{ +class POSIXCrashStopInfo : public POSIXStopInfo { public: - POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, - CrashReason reason, - lldb::addr_t fault_addr); - ~POSIXCrashStopInfo(); + POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, + lldb::addr_t fault_addr); + ~POSIXCrashStopInfo(); - lldb::StopReason - GetStopReason() const; + lldb::StopReason GetStopReason() const; }; //===----------------------------------------------------------------------===// @@ -84,27 +68,19 @@ public: /// @brief Represents the stop state of process when a new thread is spawned. /// -class POSIXNewThreadStopInfo - : public POSIXStopInfo -{ +class POSIXNewThreadStopInfo : public POSIXStopInfo { public: - POSIXNewThreadStopInfo (FreeBSDThread &thread) - : POSIXStopInfo (thread, 0) - { } + POSIXNewThreadStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {} - ~POSIXNewThreadStopInfo(); + ~POSIXNewThreadStopInfo(); - lldb::StopReason - GetStopReason() const; + lldb::StopReason GetStopReason() const; - const char * - GetDescription(); + const char *GetDescription(); - bool - ShouldStop(lldb_private::Event *event_ptr); + bool ShouldStop(lldb_private::Event *event_ptr); - bool - ShouldNotify(lldb_private::Event *event_ptr); + bool ShouldNotify(lldb_private::Event *event_ptr); }; #endif diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 3a72a65da69..82e45a5d5fc 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -1,4 +1,5 @@ -//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===// +//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -21,12 +22,12 @@ #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Target.h" -#include "ProcessFreeBSD.h" -#include "ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "FreeBSDThread.h" #include "Plugins/Process/Utility/FreeBSDSignals.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "ProcessFreeBSD.h" #include "ProcessMonitor.h" -#include "FreeBSDThread.h" +#include "ProcessPOSIXLog.h" // Other libraries and framework includes #include "lldb/Breakpoint/BreakpointLocation.h" @@ -44,18 +45,14 @@ #include "lldb/Host/posix/Fcntl.h" - using namespace lldb; using namespace lldb_private; -namespace -{ - UnixSignalsSP& - GetFreeBSDSignals () - { - static UnixSignalsSP s_freebsd_signals_sp (new FreeBSDSignals ()); - return s_freebsd_signals_sp; - } +namespace { +UnixSignalsSP &GetFreeBSDSignals() { + static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals()); + return s_freebsd_signals_sp; +} } //------------------------------------------------------------------------------ @@ -64,869 +61,756 @@ namespace lldb::ProcessSP ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path) -{ - lldb::ProcessSP process_sp; - if (crash_file_path == NULL) - process_sp.reset(new ProcessFreeBSD (target_sp, listener_sp, GetFreeBSDSignals())); - return process_sp; + const FileSpec *crash_file_path) { + lldb::ProcessSP process_sp; + if (crash_file_path == NULL) + process_sp.reset( + new ProcessFreeBSD(target_sp, listener_sp, GetFreeBSDSignals())); + return process_sp; } -void -ProcessFreeBSD::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - ProcessPOSIXLog::Initialize(GetPluginNameStatic()); - }); +void ProcessFreeBSD::Initialize() { + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + ProcessPOSIXLog::Initialize(GetPluginNameStatic()); + }); } -lldb_private::ConstString -ProcessFreeBSD::GetPluginNameStatic() -{ - static ConstString g_name("freebsd"); - return g_name; +lldb_private::ConstString ProcessFreeBSD::GetPluginNameStatic() { + static ConstString g_name("freebsd"); + return g_name; } -const char * -ProcessFreeBSD::GetPluginDescriptionStatic() -{ - return "Process plugin for FreeBSD"; +const char *ProcessFreeBSD::GetPluginDescriptionStatic() { + return "Process plugin for FreeBSD"; } //------------------------------------------------------------------------------ // ProcessInterface protocol. -lldb_private::ConstString -ProcessFreeBSD::GetPluginName() -{ - return GetPluginNameStatic(); +lldb_private::ConstString ProcessFreeBSD::GetPluginName() { + return GetPluginNameStatic(); } -uint32_t -ProcessFreeBSD::GetPluginVersion() -{ - return 1; -} +uint32_t ProcessFreeBSD::GetPluginVersion() { return 1; } -void -ProcessFreeBSD::Terminate() -{ -} - -Error -ProcessFreeBSD::DoDetach(bool keep_stopped) -{ - Error error; - if (keep_stopped) - { - error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD."); - return error; - } - - error = m_monitor->Detach(GetID()); - - if (error.Success()) - SetPrivateState(eStateDetached); +void ProcessFreeBSD::Terminate() {} +Error ProcessFreeBSD::DoDetach(bool keep_stopped) { + Error error; + if (keep_stopped) { + error.SetErrorString("Detaching with keep_stopped true is not currently " + "supported on FreeBSD."); return error; -} - -Error -ProcessFreeBSD::DoResume() -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - SetPrivateState(eStateRunning); - - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - bool do_step = false; + } + + error = m_monitor->Detach(GetID()); + + if (error.Success()) + SetPrivateState(eStateDetached); + + return error; +} + +Error ProcessFreeBSD::DoResume() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + SetPrivateState(eStateRunning); + + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + bool do_step = false; + + for (tid_collection::const_iterator t_pos = m_run_tids.begin(), + t_end = m_run_tids.end(); + t_pos != t_end; ++t_pos) { + m_monitor->ThreadSuspend(*t_pos, false); + } + for (tid_collection::const_iterator t_pos = m_step_tids.begin(), + t_end = m_step_tids.end(); + t_pos != t_end; ++t_pos) { + m_monitor->ThreadSuspend(*t_pos, false); + do_step = true; + } + for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), + t_end = m_suspend_tids.end(); + t_pos != t_end; ++t_pos) { + m_monitor->ThreadSuspend(*t_pos, true); + // XXX Cannot PT_CONTINUE properly with suspended threads. + do_step = true; + } + + if (log) + log->Printf("process %" PRIu64 " resuming (%s)", GetID(), + do_step ? "step" : "continue"); + if (do_step) + m_monitor->SingleStep(GetID(), m_resume_signo); + else + m_monitor->Resume(GetID(), m_resume_signo); + + return Error(); +} + +bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + if (log) + log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, + GetID()); + + std::vector<lldb::pid_t> tds; + if (!GetMonitor().GetCurrentThreadIDs(tds)) { + return false; + } - for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos) - { - m_monitor->ThreadSuspend(*t_pos, false); - } - for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos) - { - m_monitor->ThreadSuspend(*t_pos, false); - do_step = true; + ThreadList old_thread_list_copy(old_thread_list); + for (size_t i = 0; i < tds.size(); ++i) { + tid_t tid = tds[i]; + ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false)); + if (!thread_sp) { + thread_sp.reset(new FreeBSDThread(*this, tid)); + if (log) + log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid); + } else { + if (log) + log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, + tid); } - for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos) - { - m_monitor->ThreadSuspend(*t_pos, true); - // XXX Cannot PT_CONTINUE properly with suspended threads. - do_step = true; + new_thread_list.AddThread(thread_sp); + } + for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) { + ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); + if (old_thread_sp) { + if (log) + log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__); } + } - if (log) - log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue"); - if (do_step) - m_monitor->SingleStep(GetID(), m_resume_signo); - else - m_monitor->Resume(GetID(), m_resume_signo); - - return Error(); + return true; } -bool -ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log) - log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); - - std::vector<lldb::pid_t> tds; - if (!GetMonitor().GetCurrentThreadIDs(tds)) - { - return false; - } +Error ProcessFreeBSD::WillResume() { + m_resume_signo = 0; + m_suspend_tids.clear(); + m_run_tids.clear(); + m_step_tids.clear(); + return Process::WillResume(); +} - ThreadList old_thread_list_copy(old_thread_list); - for (size_t i = 0; i < tds.size(); ++i) - { - tid_t tid = tds[i]; - ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false)); - if (!thread_sp) - { - thread_sp.reset(new FreeBSDThread(*this, tid)); - if (log) - log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid); - } - else - { - if (log) - log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid); - } - new_thread_list.AddThread(thread_sp); - } - for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) - { - ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); - if (old_thread_sp) - { - if (log) - log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__); - } - } +void ProcessFreeBSD::SendMessage(const ProcessMessage &message) { + std::lock_guard<std::recursive_mutex> guard(m_message_mutex); - return true; -} + switch (message.GetKind()) { + case ProcessMessage::eInvalidMessage: + return; -Error -ProcessFreeBSD::WillResume() -{ - m_resume_signo = 0; - m_suspend_tids.clear(); - m_run_tids.clear(); - m_step_tids.clear(); - return Process::WillResume(); -} + case ProcessMessage::eAttachMessage: + SetPrivateState(eStateStopped); + return; -void -ProcessFreeBSD::SendMessage(const ProcessMessage &message) -{ - std::lock_guard<std::recursive_mutex> guard(m_message_mutex); + case ProcessMessage::eLimboMessage: + case ProcessMessage::eExitMessage: + SetExitStatus(message.GetExitStatus(), NULL); + break; - switch (message.GetKind()) - { - case ProcessMessage::eInvalidMessage: - return; + case ProcessMessage::eSignalMessage: + case ProcessMessage::eSignalDeliveredMessage: + case ProcessMessage::eBreakpointMessage: + case ProcessMessage::eTraceMessage: + case ProcessMessage::eWatchpointMessage: + case ProcessMessage::eCrashMessage: + SetPrivateState(eStateStopped); + break; - case ProcessMessage::eAttachMessage: - SetPrivateState(eStateStopped); - return; + case ProcessMessage::eNewThreadMessage: + llvm_unreachable("eNewThreadMessage unexpected on FreeBSD"); + break; - case ProcessMessage::eLimboMessage: - case ProcessMessage::eExitMessage: - SetExitStatus(message.GetExitStatus(), NULL); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - case ProcessMessage::eBreakpointMessage: - case ProcessMessage::eTraceMessage: - case ProcessMessage::eWatchpointMessage: - case ProcessMessage::eCrashMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eNewThreadMessage: - llvm_unreachable("eNewThreadMessage unexpected on FreeBSD"); - break; - - case ProcessMessage::eExecMessage: - SetPrivateState(eStateStopped); - break; - } + case ProcessMessage::eExecMessage: + SetPrivateState(eStateStopped); + break; + } - m_message_queue.push(message); + m_message_queue.push(message); } //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, UnixSignalsSP &unix_signals_sp) +ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + UnixSignalsSP &unix_signals_sp) : Process(target_sp, listener_sp, unix_signals_sp), - m_byte_order(endian::InlHostByteOrder()), - m_monitor(NULL), - m_module(NULL), - m_message_mutex(), - m_exit_now(false), - m_seen_initial_stop(), - m_resume_signo(0) -{ - // FIXME: Putting this code in the ctor and saving the byte order in a - // member variable is a hack to avoid const qual issues in GetByteOrder. - lldb::ModuleSP module = GetTarget().GetExecutableModule(); - if (module && module->GetObjectFile()) - m_byte_order = module->GetObjectFile()->GetByteOrder(); + m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL), + m_message_mutex(), m_exit_now(false), m_seen_initial_stop(), + m_resume_signo(0) { + // FIXME: Putting this code in the ctor and saving the byte order in a + // member variable is a hack to avoid const qual issues in GetByteOrder. + lldb::ModuleSP module = GetTarget().GetExecutableModule(); + if (module && module->GetObjectFile()) + m_byte_order = module->GetObjectFile()->GetByteOrder(); } -ProcessFreeBSD::~ProcessFreeBSD() -{ - delete m_monitor; -} +ProcessFreeBSD::~ProcessFreeBSD() { delete m_monitor; } //------------------------------------------------------------------------------ // Process protocol. -void -ProcessFreeBSD::Finalize() -{ +void ProcessFreeBSD::Finalize() { Process::Finalize(); if (m_monitor) m_monitor->StopMonitor(); } -bool -ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - // If there is no executable module, we return true since we might be preparing to attach. - return true; +bool ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target_sp->GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + // If there is no executable module, we return true since we might be + // preparing to attach. + return true; } -Error -ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - Error error; - assert(m_monitor == NULL); +Error ProcessFreeBSD::DoAttachToProcessWithID( + lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + Error error; + assert(m_monitor == NULL); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); - m_monitor = new ProcessMonitor(this, pid, error); + m_monitor = new ProcessMonitor(this, pid, error); - if (!error.Success()) - return error; + if (!error.Success()) + return error; - PlatformSP platform_sp (GetTarget().GetPlatform ()); - assert (platform_sp.get()); - if (!platform_sp) - return error; // FIXME: Detatch? - - // Find out what we can about this process - ProcessInstanceInfo process_info; - platform_sp->GetProcessInfo (pid, process_info); - - // Resolve the executable module - ModuleSP exe_module_sp; - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture()); - error = platform_sp->ResolveExecutable(exe_module_spec, - exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return error; + PlatformSP platform_sp(GetTarget().GetPlatform()); + assert(platform_sp.get()); + if (!platform_sp) + return error; // FIXME: Detatch? + + // Find out what we can about this process + ProcessInstanceInfo process_info; + platform_sp->GetProcessInfo(pid, process_info); + + // Resolve the executable module + ModuleSP exe_module_sp; + FileSpecList executable_search_paths( + Target::GetDefaultExecutableSearchPaths()); + ModuleSpec exe_module_spec(process_info.GetExecutableFile(), + GetTarget().GetArchitecture()); + error = platform_sp->ResolveExecutable( + exe_module_spec, exe_module_sp, + executable_search_paths.GetSize() ? &executable_search_paths : NULL); + if (!error.Success()) + return error; - // Fix the target architecture if necessary - const ArchSpec &module_arch = exe_module_sp->GetArchitecture(); - if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch)) - GetTarget().SetArchitecture(module_arch); + // Fix the target architecture if necessary + const ArchSpec &module_arch = exe_module_sp->GetArchitecture(); + if (module_arch.IsValid() && + !GetTarget().GetArchitecture().IsExactMatch(module_arch)) + GetTarget().SetArchitecture(module_arch); - // Initialize the target module list - GetTarget().SetExecutableModule (exe_module_sp, true); + // Initialize the target module list + GetTarget().SetExecutableModule(exe_module_sp, true); - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); - SetID(pid); + SetID(pid); - return error; + return error; } -Error -ProcessFreeBSD::WillLaunch(Module* module) -{ - Error error; - return error; +Error ProcessFreeBSD::WillLaunch(Module *module) { + Error error; + return error; } FileSpec ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action, - const FileSpec &default_file_spec, - const FileSpec &dbg_pts_file_spec) -{ - FileSpec file_spec{}; - - if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) - { - file_spec = file_action->GetFileSpec(); - // By default the stdio paths passed in will be pseudo-terminal - // (/dev/pts). If so, convert to using a different default path - // instead to redirect I/O to the debugger console. This should - // also handle user overrides to /dev/null or a different file. - if (!file_spec || file_spec == dbg_pts_file_spec) - file_spec = default_file_spec; - } - return file_spec; -} - -Error -ProcessFreeBSD::DoLaunch (Module *module, - ProcessLaunchInfo &launch_info) -{ - Error error; - assert(m_monitor == NULL); - - 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; - } + const FileSpec &default_file_spec, + const FileSpec &dbg_pts_file_spec) { + FileSpec file_spec{}; + + if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) { + file_spec = file_action->GetFileSpec(); + // By default the stdio paths passed in will be pseudo-terminal + // (/dev/pts). If so, convert to using a different default path + // instead to redirect I/O to the debugger console. This should + // also handle user overrides to /dev/null or a different file. + if (!file_spec || file_spec == dbg_pts_file_spec) + file_spec = default_file_spec; + } + return file_spec; +} + +Error ProcessFreeBSD::DoLaunch(Module *module, ProcessLaunchInfo &launch_info) { + Error error; + assert(m_monitor == NULL); + + 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; + } - SetPrivateState(eStateLaunching); + SetPrivateState(eStateLaunching); - const lldb_private::FileAction *file_action; + const lldb_private::FileAction *file_action; - // Default of empty will mean to use existing open file descriptors - FileSpec stdin_file_spec{}; - FileSpec stdout_file_spec{}; - FileSpec stderr_file_spec{}; + // Default of empty will mean to use existing open file descriptors + FileSpec stdin_file_spec{}; + FileSpec stdout_file_spec{}; + FileSpec stderr_file_spec{}; - const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false}; + const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL, 0), + false}; - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec); + file_action = launch_info.GetFileActionForFD(STDIN_FILENO); + stdin_file_spec = + GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec); - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec); + file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); + stdout_file_spec = + GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec); - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec); + file_action = launch_info.GetFileActionForFD(STDERR_FILENO); + stderr_file_spec = + GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec); - m_monitor = new ProcessMonitor(this, - module, - launch_info.GetArguments().GetConstArgumentVector(), - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir, - launch_info, - error); + m_monitor = new ProcessMonitor( + this, module, launch_info.GetArguments().GetConstArgumentVector(), + launch_info.GetEnvironmentEntries().GetConstArgumentVector(), + stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir, + launch_info, error); - m_module = module; + m_module = module; - if (!error.Success()) - return error; + if (!error.Success()) + return error; - int terminal = m_monitor->GetTerminalFD(); - if (terminal >= 0) { - // The reader thread will close the file descriptor when done, so we pass it a copy. + int terminal = m_monitor->GetTerminalFD(); + if (terminal >= 0) { +// The reader thread will close the file descriptor when done, so we pass it a +// copy. #ifdef F_DUPFD_CLOEXEC - int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } + int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } #else - // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD) - int stdio = fcntl(terminal, F_DUPFD, 0); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } - stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } -#endif - SetSTDIOFileDescriptor(stdio); + // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD) + int stdio = fcntl(terminal, F_DUPFD, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } + stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; } +#endif + SetSTDIOFileDescriptor(stdio); + } - SetID(m_monitor->GetPID()); - return error; + SetID(m_monitor->GetPID()); + return error; } -void -ProcessFreeBSD::DidLaunch() -{ -} +void ProcessFreeBSD::DidLaunch() {} -addr_t -ProcessFreeBSD::GetImageInfoAddress() -{ - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(target); +addr_t ProcessFreeBSD::GetImageInfoAddress() { + Target *target = &GetTarget(); + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(target); - if (addr.IsValid()) - return addr.GetLoadAddress(target); - return LLDB_INVALID_ADDRESS; + if (addr.IsValid()) + return addr.GetLoadAddress(target); + return LLDB_INVALID_ADDRESS; } -Error -ProcessFreeBSD::DoHalt(bool &caused_stop) -{ - Error error; +Error ProcessFreeBSD::DoHalt(bool &caused_stop) { + Error error; - if (IsStopped()) - { - caused_stop = false; - } - else if (kill(GetID(), SIGSTOP)) - { - caused_stop = false; - error.SetErrorToErrno(); - } - else - { - caused_stop = true; - } - return error; + if (IsStopped()) { + caused_stop = false; + } else if (kill(GetID(), SIGSTOP)) { + caused_stop = false; + error.SetErrorToErrno(); + } else { + caused_stop = true; + } + return error; } -Error -ProcessFreeBSD::DoSignal(int signal) -{ - Error error; +Error ProcessFreeBSD::DoSignal(int signal) { + Error error; - if (kill(GetID(), signal)) - error.SetErrorToErrno(); + if (kill(GetID(), signal)) + error.SetErrorToErrno(); - return error; + return error; } -Error -ProcessFreeBSD::DoDestroy() -{ - Error error; - - if (!HasExited()) - { - assert(m_monitor); - m_exit_now = true; - if (GetID() == LLDB_INVALID_PROCESS_ID) - { - error.SetErrorString("invalid process id"); - return error; - } - if (!m_monitor->Kill()) - { - error.SetErrorToErrno(); - return error; - } - - SetPrivateState(eStateExited); - } +Error ProcessFreeBSD::DoDestroy() { + Error error; - return error; -} + if (!HasExited()) { + assert(m_monitor); + m_exit_now = true; + if (GetID() == LLDB_INVALID_PROCESS_ID) { + error.SetErrorString("invalid process id"); + return error; + } + if (!m_monitor->Kill()) { + error.SetErrorToErrno(); + return error; + } -void -ProcessFreeBSD::DoDidExec() -{ - Target *target = &GetTarget(); - if (target) - { - PlatformSP platform_sp (target->GetPlatform()); - assert (platform_sp.get()); - if (platform_sp) - { - ProcessInstanceInfo process_info; - platform_sp->GetProcessInfo(GetID(), process_info); - ModuleSP exe_module_sp; - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture()); - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - Error error = platform_sp->ResolveExecutable(exe_module_spec, - exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return; - target->SetExecutableModule(exe_module_sp, true); - } + SetPrivateState(eStateExited); + } + + return error; +} + +void ProcessFreeBSD::DoDidExec() { + Target *target = &GetTarget(); + if (target) { + PlatformSP platform_sp(target->GetPlatform()); + assert(platform_sp.get()); + if (platform_sp) { + ProcessInstanceInfo process_info; + platform_sp->GetProcessInfo(GetID(), process_info); + ModuleSP exe_module_sp; + ModuleSpec exe_module_spec(process_info.GetExecutableFile(), + target->GetArchitecture()); + FileSpecList executable_search_paths( + Target::GetDefaultExecutableSearchPaths()); + Error error = platform_sp->ResolveExecutable( + exe_module_spec, exe_module_sp, + executable_search_paths.GetSize() ? &executable_search_paths : NULL); + if (!error.Success()) + return; + target->SetExecutableModule(exe_module_sp, true); } + } } -bool -ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) -{ - bool added_to_set = false; - ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid); - if (it == m_seen_initial_stop.end()) - { - m_seen_initial_stop.insert(stop_tid); - added_to_set = true; - } - return added_to_set; +bool ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) { + bool added_to_set = false; + ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid); + if (it == m_seen_initial_stop.end()) { + m_seen_initial_stop.insert(stop_tid); + added_to_set = true; + } + return added_to_set; } -bool -ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) -{ - return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); +bool ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) { + return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); } FreeBSDThread * -ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid) -{ - return new FreeBSDThread(process, tid); +ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, + lldb::tid_t tid) { + return new FreeBSDThread(process, tid); } -void -ProcessFreeBSD::RefreshStateAfterStop() -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size()); - - std::lock_guard<std::recursive_mutex> guard(m_message_mutex); +void ProcessFreeBSD::RefreshStateAfterStop() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, + (int)m_message_queue.size()); - // This method used to only handle one message. Changing it to loop allows - // it to handle the case where we hit a breakpoint while handling a different - // breakpoint. - while (!m_message_queue.empty()) - { - ProcessMessage &message = m_message_queue.front(); + std::lock_guard<std::recursive_mutex> guard(m_message_mutex); - // Resolve the thread this message corresponds to and pass it along. - lldb::tid_t tid = message.GetTID(); - if (log) - log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); + // This method used to only handle one message. Changing it to loop allows + // it to handle the case where we hit a breakpoint while handling a different + // breakpoint. + while (!m_message_queue.empty()) { + ProcessMessage &message = m_message_queue.front(); - m_thread_list.RefreshStateAfterStop(); + // Resolve the thread this message corresponds to and pass it along. + lldb::tid_t tid = message.GetTID(); + if (log) + log->Printf( + "ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, + __FUNCTION__, (int)m_message_queue.size(), tid); - FreeBSDThread *thread = static_cast<FreeBSDThread*>( - GetThreadList().FindThreadByID(tid, false).get()); - if (thread) - thread->Notify(message); + m_thread_list.RefreshStateAfterStop(); - if (message.GetKind() == ProcessMessage::eExitMessage) - { - // FIXME: We should tell the user about this, but the limbo message is probably better for that. - if (log) - log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + GetThreadList().FindThreadByID(tid, false).get()); + if (thread) + thread->Notify(message); - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + if (message.GetKind() == ProcessMessage::eExitMessage) { + // FIXME: We should tell the user about this, but the limbo message is + // probably better for that. + if (log) + log->Printf("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, + __FUNCTION__, tid); - ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); - thread_sp.reset(); - m_seen_initial_stop.erase(tid); - } + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - m_message_queue.pop(); + ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); + thread_sp.reset(); + m_seen_initial_stop.erase(tid); } + + m_message_queue.pop(); + } } -bool -ProcessFreeBSD::IsAlive() -{ - StateType state = GetPrivateState(); - return state != eStateDetached - && state != eStateExited - && state != eStateInvalid - && state != eStateUnloaded; +bool ProcessFreeBSD::IsAlive() { + StateType state = GetPrivateState(); + return state != eStateDetached && state != eStateExited && + state != eStateInvalid && state != eStateUnloaded; } -size_t -ProcessFreeBSD::DoReadMemory(addr_t vm_addr, - void *buf, size_t size, Error &error) -{ - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); +size_t ProcessFreeBSD::DoReadMemory(addr_t vm_addr, void *buf, size_t size, + Error &error) { + assert(m_monitor); + return m_monitor->ReadMemory(vm_addr, buf, size, error); } -size_t -ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, - Error &error) -{ - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); +size_t ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, + size_t size, Error &error) { + assert(m_monitor); + return m_monitor->WriteMemory(vm_addr, buf, size, error); } -addr_t -ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) -{ - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } +addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) { + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; - return allocated_addr; + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { + m_addr_to_mmap_size[allocated_addr] = size; + error.Clear(); + } else { + allocated_addr = LLDB_INVALID_ADDRESS; + error.SetErrorStringWithFormat( + "unable to allocate %zu bytes of memory with permissions %s", size, + GetPermissionsAsCString(permissions)); + } + + return allocated_addr; } -Error -ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) -{ - Error error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); +Error ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) { + Error error; + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); + if (pos != m_addr_to_mmap_size.end() && + InferiorCallMunmap(this, addr, pos->second)) + m_addr_to_mmap_size.erase(pos); + else + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, + addr); - return error; + return error; } size_t -ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) -{ - static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 }; - static const uint8_t g_i386_opcode[] = { 0xCC }; - - ArchSpec arch = GetTarget().GetArchitecture(); - const uint8_t *opcode = NULL; - size_t opcode_size = 0; - - switch (arch.GetMachine()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case llvm::Triple::arm: - { - // The ARM reference recommends the use of 0xe7fddefe and 0xdefe - // but the linux kernel does otherwise. - static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; - static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; - - lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); - AddressClass addr_class = eAddressClassUnknown; - - if (bp_loc_sp) - addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); - - if (addr_class == eAddressClassCodeAlternateISA - || (addr_class == eAddressClassUnknown - && bp_loc_sp->GetAddress().GetOffset() & 1)) - { - opcode = g_thumb_breakpoint_opcode; - opcode_size = sizeof(g_thumb_breakpoint_opcode); - } - else - { - opcode = g_arm_breakpoint_opcode; - opcode_size = sizeof(g_arm_breakpoint_opcode); - } - } - break; - case llvm::Triple::aarch64: - opcode = g_aarch64_opcode; - opcode_size = sizeof(g_aarch64_opcode); - break; - - case llvm::Triple::x86: - case llvm::Triple::x86_64: - opcode = g_i386_opcode; - opcode_size = sizeof(g_i386_opcode); - break; +ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) { + static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xD4}; + static const uint8_t g_i386_opcode[] = {0xCC}; + + ArchSpec arch = GetTarget().GetArchitecture(); + const uint8_t *opcode = NULL; + size_t opcode_size = 0; + + switch (arch.GetMachine()) { + default: + assert(false && "CPU type not supported!"); + break; + + case llvm::Triple::arm: { + // The ARM reference recommends the use of 0xe7fddefe and 0xdefe + // but the linux kernel does otherwise. + static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; + static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; + + lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); + AddressClass addr_class = eAddressClassUnknown; + + if (bp_loc_sp) + addr_class = bp_loc_sp->GetAddress().GetAddressClass(); + + if (addr_class == eAddressClassCodeAlternateISA || + (addr_class == eAddressClassUnknown && + bp_loc_sp->GetAddress().GetOffset() & 1)) { + opcode = g_thumb_breakpoint_opcode; + opcode_size = sizeof(g_thumb_breakpoint_opcode); + } else { + opcode = g_arm_breakpoint_opcode; + opcode_size = sizeof(g_arm_breakpoint_opcode); } + } break; + case llvm::Triple::aarch64: + opcode = g_aarch64_opcode; + opcode_size = sizeof(g_aarch64_opcode); + break; + + case llvm::Triple::x86: + case llvm::Triple::x86_64: + opcode = g_i386_opcode; + opcode_size = sizeof(g_i386_opcode); + break; + } - bp_site->SetTrapOpcode(opcode, opcode_size); - return opcode_size; + bp_site->SetTrapOpcode(opcode, opcode_size); + return opcode_size; } -Error -ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) -{ - return EnableSoftwareBreakpoint(bp_site); +Error ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) { + return EnableSoftwareBreakpoint(bp_site); } -Error -ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) -{ - return DisableSoftwareBreakpoint(bp_site); +Error ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) { + return DisableSoftwareBreakpoint(bp_site); } -Error -ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (wp->IsEnabled()) - { - if (log) - log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); - return error; - } - - // Try to find a vacant watchpoint slot in the inferiors' main thread - uint32_t wp_hw_index = LLDB_INVALID_INDEX32; - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - FreeBSDThread *thread = static_cast<FreeBSDThread*>( - m_thread_list.GetThreadAtIndex(0, false).get()); +Error ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + if (wp) { + user_id_t watchID = wp->GetID(); + addr_t addr = wp->GetLoadAddress(); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + if (log) + log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (wp->IsEnabled()) { + if (log) + log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); + return error; + } - if (thread) - wp_hw_index = thread->FindVacantWatchpointIndex(); + // Try to find a vacant watchpoint slot in the inferiors' main thread + uint32_t wp_hw_index = LLDB_INVALID_INDEX32; + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + m_thread_list.GetThreadAtIndex(0, false).get()); + + if (thread) + wp_hw_index = thread->FindVacantWatchpointIndex(); - if (wp_hw_index == LLDB_INVALID_INDEX32) - { - error.SetErrorString("Setting hardware watchpoint failed."); - } + if (wp_hw_index == LLDB_INVALID_INDEX32) { + error.SetErrorString("Setting hardware watchpoint failed."); + } else { + wp->SetHardwareIndex(wp_hw_index); + bool wp_enabled = true; + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) { + thread = static_cast<FreeBSDThread *>( + m_thread_list.GetThreadAtIndex(i, false).get()); + if (thread) + wp_enabled &= thread->EnableHardwareWatchpoint(wp); else - { - wp->SetHardwareIndex(wp_hw_index); - bool wp_enabled = true; - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - thread = static_cast<FreeBSDThread*>( - m_thread_list.GetThreadAtIndex(i, false).get()); - if (thread) - wp_enabled &= thread->EnableHardwareWatchpoint(wp); - else - wp_enabled = false; - } - if (wp_enabled) - { - wp->SetEnabled(true, notify); - return error; - } - else - { - // Watchpoint enabling failed on at least one - // of the threads so roll back all of them - DisableWatchpoint(wp, false); - error.SetErrorString("Setting hardware watchpoint failed"); - } - } + wp_enabled = false; + } + if (wp_enabled) { + wp->SetEnabled(true, notify); + return error; + } else { + // Watchpoint enabling failed on at least one + // of the threads so roll back all of them + DisableWatchpoint(wp, false); + error.SetErrorString("Setting hardware watchpoint failed"); + } } - else - error.SetErrorString("Watchpoint argument was NULL."); - return error; + } else + error.SetErrorString("Watchpoint argument was NULL."); + return error; } -Error -ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (!wp->IsEnabled()) - { - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", - watchID, (uint64_t)addr); - // This is needed (for now) to keep watchpoints disabled correctly - wp->SetEnabled(false, notify); - return error; - } - - if (wp->IsHardware()) - { - bool wp_disabled = true; - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - FreeBSDThread *thread = static_cast<FreeBSDThread*>( - m_thread_list.GetThreadAtIndex(i, false).get()); - if (thread) - wp_disabled &= thread->DisableHardwareWatchpoint(wp); - else - wp_disabled = false; - } - if (wp_disabled) - { - wp->SetHardwareIndex(LLDB_INVALID_INDEX32); - wp->SetEnabled(false, notify); - return error; - } - else - error.SetErrorString("Disabling hardware watchpoint failed"); - } +Error ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + if (wp) { + user_id_t watchID = wp->GetID(); + addr_t addr = wp->GetLoadAddress(); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + if (log) + log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (!wp->IsEnabled()) { + if (log) + log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", + watchID, (uint64_t)addr); + // This is needed (for now) to keep watchpoints disabled correctly + wp->SetEnabled(false, notify); + return error; } - else - error.SetErrorString("Watchpoint argument was NULL."); - return error; + + if (wp->IsHardware()) { + bool wp_disabled = true; + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) { + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + m_thread_list.GetThreadAtIndex(i, false).get()); + if (thread) + wp_disabled &= thread->DisableHardwareWatchpoint(wp); + else + wp_disabled = false; + } + if (wp_disabled) { + wp->SetHardwareIndex(LLDB_INVALID_INDEX32); + wp->SetEnabled(false, notify); + return error; + } else + error.SetErrorString("Disabling hardware watchpoint failed"); + } + } else + error.SetErrorString("Watchpoint argument was NULL."); + return error; } -Error -ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) -{ - Error error; - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - FreeBSDThread *thread = static_cast<FreeBSDThread*>( - m_thread_list.GetThreadAtIndex(0, false).get()); - if (thread) - num = thread->NumSupportedHardwareWatchpoints(); - else - error.SetErrorString("Process does not exist."); - return error; +Error ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) { + Error error; + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + m_thread_list.GetThreadAtIndex(0, false).get()); + if (thread) + num = thread->NumSupportedHardwareWatchpoints(); + else + error.SetErrorString("Process does not exist."); + return error; } -Error -ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) -{ - Error error = GetWatchpointSupportInfo(num); - // Watchpoints trigger and halt the inferior after - // the corresponding instruction has been executed. - after = true; - return error; +Error ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) { + Error error = GetWatchpointSupportInfo(num); + // Watchpoints trigger and halt the inferior after + // the corresponding instruction has been executed. + after = true; + return error; } -uint32_t -ProcessFreeBSD::UpdateThreadListIfNeeded() -{ - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - // Do not allow recursive updates. - return m_thread_list.GetSize(false); +uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() { + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + // Do not allow recursive updates. + return m_thread_list.GetSize(false); } #if 0 @@ -955,91 +839,77 @@ ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_th } #endif -ByteOrder -ProcessFreeBSD::GetByteOrder() const -{ - // FIXME: We should be able to extract this value directly. See comment in - // ProcessFreeBSD(). - return m_byte_order; +ByteOrder ProcessFreeBSD::GetByteOrder() const { + // FIXME: We should be able to extract this value directly. See comment in + // ProcessFreeBSD(). + return m_byte_order; } -size_t -ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error) -{ - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - error.SetErrorToErrno(); - return 0; - } - return status; +size_t ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error) { + ssize_t status; + if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) { + error.SetErrorToErrno(); + return 0; + } + return status; } //------------------------------------------------------------------------------ // Utility functions. -bool -ProcessFreeBSD::HasExited() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} +bool ProcessFreeBSD::HasExited() { + switch (GetPrivateState()) { + default: + break; -bool -ProcessFreeBSD::IsStopped() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } + case eStateDetached: + case eStateExited: + return true; + } - return false; + return false; } -bool -ProcessFreeBSD::IsAThreadRunning() -{ - bool is_running = false; - std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - FreeBSDThread *thread = static_cast<FreeBSDThread*>( - m_thread_list.GetThreadAtIndex(i, false).get()); - StateType thread_state = thread->GetState(); - if (thread_state == eStateRunning || thread_state == eStateStepping) - { - is_running = true; - break; - } - } - return is_running; -} +bool ProcessFreeBSD::IsStopped() { + switch (GetPrivateState()) { + default: + break; -const DataBufferSP -ProcessFreeBSD::GetAuxvData () -{ - // If we're the local platform, we can ask the host for auxv data. - PlatformSP platform_sp = GetTarget().GetPlatform (); - if (platform_sp && platform_sp->IsHost ()) - return lldb_private::Host::GetAuxvData(this); - - // Somewhat unexpected - the process is not running locally or we don't have a platform. - assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?"); - return DataBufferSP (); + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + return true; + } + + return false; +} + +bool ProcessFreeBSD::IsAThreadRunning() { + bool is_running = false; + std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) { + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + m_thread_list.GetThreadAtIndex(i, false).get()); + StateType thread_state = thread->GetState(); + if (thread_state == eStateRunning || thread_state == eStateStepping) { + is_running = true; + break; + } + } + return is_running; +} + +const DataBufferSP ProcessFreeBSD::GetAuxvData() { + // If we're the local platform, we can ask the host for auxv data. + PlatformSP platform_sp = GetTarget().GetPlatform(); + if (platform_sp && platform_sp->IsHost()) + return lldb_private::Host::GetAuxvData(this); + + // Somewhat unexpected - the process is not running locally or we don't have a + // platform. + assert( + false && + "no platform or not the host - how did we get here with ProcessFreeBSD?"); + return DataBufferSP(); } diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h index 888e2a90ad7..cd38989f973 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -1,4 +1,5 @@ -//===-- ProcessFreeBSD.h ------------------------------------------*- C++ -*-===// +//===-- ProcessFreeBSD.h ------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -18,233 +19,200 @@ #include <set> // Other libraries and framework includes +#include "ProcessFreeBSD.h" +#include "ProcessMessage.h" #include "lldb/Target/Process.h" #include "lldb/Target/ThreadList.h" -#include "ProcessMessage.h" -#include "ProcessFreeBSD.h" class ProcessMonitor; class FreeBSDThread; -class ProcessFreeBSD : - public lldb_private::Process -{ +class ProcessFreeBSD : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Static functions. - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); + //------------------------------------------------------------------ + // Static functions. + //------------------------------------------------------------------ + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path); - static void - Initialize(); + static void Initialize(); - static void - Terminate(); + static void Terminate(); - static lldb_private::ConstString - GetPluginNameStatic(); + static lldb_private::ConstString GetPluginNameStatic(); - static const char * - GetPluginDescriptionStatic(); + static const char *GetPluginDescriptionStatic(); - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessFreeBSD(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - lldb::UnixSignalsSP &unix_signals_sp); + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + lldb::UnixSignalsSP &unix_signals_sp); - ~ProcessFreeBSD(); + ~ProcessFreeBSD(); - virtual lldb_private::Error - WillResume() override; + virtual lldb_private::Error WillResume() override; - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName() override; + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString GetPluginName() override; - virtual uint32_t - GetPluginVersion() override; + virtual uint32_t GetPluginVersion() override; public: - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - void - Finalize() override; + //------------------------------------------------------------------ + // Process protocol. + //------------------------------------------------------------------ + void Finalize() override; - bool - CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; - lldb_private::Error - WillLaunch(lldb_private::Module *module) override; + lldb_private::Error WillLaunch(lldb_private::Module *module) override; - lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; + lldb_private::Error DoAttachToProcessWithID( + lldb::pid_t pid, + const lldb_private::ProcessAttachInfo &attach_info) override; - lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info) override; + lldb_private::Error + DoLaunch(lldb_private::Module *exe_module, + lldb_private::ProcessLaunchInfo &launch_info) override; - void - DidLaunch() override; + void DidLaunch() override; - lldb_private::Error - DoResume() override; + lldb_private::Error DoResume() override; - lldb_private::Error - DoHalt(bool &caused_stop) override; + lldb_private::Error DoHalt(bool &caused_stop) override; - lldb_private::Error - DoDetach(bool keep_stopped) override; + lldb_private::Error DoDetach(bool keep_stopped) override; - lldb_private::Error - DoSignal(int signal) override; + lldb_private::Error DoSignal(int signal) override; - lldb_private::Error - DoDestroy() override; + lldb_private::Error DoDestroy() override; - void - DoDidExec() override; + void DoDidExec() override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - bool - IsAlive() override; + bool IsAlive() override; - size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error) override; + size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error) override; - size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error) override; + size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) override; - lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error) override; + lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, + lldb_private::Error &error) override; - lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr) override; + lldb_private::Error DoDeallocateMemory(lldb::addr_t ptr) override; - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); + virtual size_t + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite *bp_site); - lldb_private::Error - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + lldb_private::Error + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - lldb_private::Error - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + lldb_private::Error + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - lldb_private::Error - EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + lldb_private::Error EnableWatchpoint(lldb_private::Watchpoint *wp, + bool notify = true) override; - lldb_private::Error - DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + lldb_private::Error DisableWatchpoint(lldb_private::Watchpoint *wp, + bool notify = true) override; - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num) override; + lldb_private::Error GetWatchpointSupportInfo(uint32_t &num) override; - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num, bool &after) override; + lldb_private::Error GetWatchpointSupportInfo(uint32_t &num, + bool &after) override; - virtual uint32_t - UpdateThreadListIfNeeded(); + virtual uint32_t UpdateThreadListIfNeeded(); - bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; - virtual lldb::ByteOrder - GetByteOrder() const; + virtual lldb::ByteOrder GetByteOrder() const; - lldb::addr_t - GetImageInfoAddress() override; + lldb::addr_t GetImageInfoAddress() override; - size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; + size_t PutSTDIN(const char *buf, size_t len, + lldb_private::Error &error) override; - const lldb::DataBufferSP - GetAuxvData () override; + const lldb::DataBufferSP GetAuxvData() override; - //-------------------------------------------------------------------------- - // ProcessFreeBSD internal API. + //-------------------------------------------------------------------------- + // ProcessFreeBSD internal API. - /// Registers the given message with this process. - virtual void - SendMessage(const ProcessMessage &message); + /// Registers the given message with this process. + virtual void SendMessage(const ProcessMessage &message); - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } + ProcessMonitor &GetMonitor() { + assert(m_monitor); + return *m_monitor; + } - lldb_private::FileSpec - GetFileSpec(const lldb_private::FileAction *file_action, - const lldb_private::FileSpec &default_file_spec, - const lldb_private::FileSpec &dbg_pts_file_spec); + lldb_private::FileSpec + GetFileSpec(const lldb_private::FileAction *file_action, + const lldb_private::FileSpec &default_file_spec, + const lldb_private::FileSpec &dbg_pts_file_spec); - /// Adds the thread to the list of threads for which we have received the initial stopping signal. - /// The \p stop_tid parameter indicates the thread which the stop happened for. - bool - AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); + /// Adds the thread to the list of threads for which we have received the + /// initial stopping signal. + /// The \p stop_tid parameter indicates the thread which the stop happened + /// for. + bool AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); - bool - WaitingForInitialStop(lldb::tid_t stop_tid); + bool WaitingForInitialStop(lldb::tid_t stop_tid); - virtual FreeBSDThread * - CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid); + virtual FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process, + lldb::tid_t tid); protected: - /// Target byte order. - lldb::ByteOrder m_byte_order; - - /// Process monitor; - ProcessMonitor *m_monitor; + /// Target byte order. + lldb::ByteOrder m_byte_order; - /// The module we are executing. - lldb_private::Module *m_module; + /// Process monitor; + ProcessMonitor *m_monitor; - /// Message queue notifying this instance of inferior process state changes. - std::recursive_mutex m_message_mutex; - std::queue<ProcessMessage> m_message_queue; + /// The module we are executing. + lldb_private::Module *m_module; - /// Drive any exit events to completion. - bool m_exit_now; + /// Message queue notifying this instance of inferior process state changes. + std::recursive_mutex m_message_mutex; + std::queue<ProcessMessage> m_message_queue; - /// Returns true if the process has exited. - bool HasExited(); + /// Drive any exit events to completion. + bool m_exit_now; - /// Returns true if the process is stopped. - bool IsStopped(); + /// Returns true if the process has exited. + bool HasExited(); - /// Returns true if at least one running is currently running - bool IsAThreadRunning(); + /// Returns true if the process is stopped. + bool IsStopped(); - typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; - MMapMap m_addr_to_mmap_size; + /// Returns true if at least one running is currently running + bool IsAThreadRunning(); - typedef std::set<lldb::tid_t> ThreadStopSet; - /// Every thread begins with a stop signal. This keeps track - /// of the threads for which we have received the stop signal. - ThreadStopSet m_seen_initial_stop; + typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; + MMapMap m_addr_to_mmap_size; - friend class FreeBSDThread; + typedef std::set<lldb::tid_t> ThreadStopSet; + /// Every thread begins with a stop signal. This keeps track + /// of the threads for which we have received the stop signal. + ThreadStopSet m_seen_initial_stop; - typedef std::vector<lldb::tid_t> tid_collection; - tid_collection m_suspend_tids; - tid_collection m_run_tids; - tid_collection m_step_tids; + friend class FreeBSDThread; - int m_resume_signo; + typedef std::vector<lldb::tid_t> tid_collection; + tid_collection m_suspend_tids; + tid_collection m_run_tids; + tid_collection m_step_tids; + int m_resume_signo; }; -#endif // liblldb_ProcessFreeBSD_H_ +#endif // liblldb_ProcessFreeBSD_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 16707a5c8b9..afc649de3b6 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -10,14 +10,14 @@ // C Includes #include <errno.h> #include <poll.h> -#include <string.h> -#include <stdint.h> -#include <unistd.h> #include <signal.h> +#include <stdint.h> +#include <string.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> +#include <unistd.h> // C++ Includes // Other libraries and framework includes @@ -26,20 +26,20 @@ #include "lldb/Core/Scalar.h" #include "lldb/Host/Host.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/PseudoTerminal.h" -#include "Plugins/Process/POSIX/CrashReason.h" #include "FreeBSDThread.h" +#include "Plugins/Process/POSIX/CrashReason.h" #include "ProcessFreeBSD.h" -#include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" +#include "ProcessPOSIXLog.h" extern "C" { - extern char ** environ; - } +extern char **environ; +} using namespace lldb; using namespace lldb_private; @@ -49,96 +49,103 @@ using namespace lldb_private; #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION // Wrapper for ptrace to catch errors and log calls. -const char * -Get_PT_IO_OP(int op) -{ - switch (op) { - case PIOD_READ_D: return "READ_D"; - case PIOD_WRITE_D: return "WRITE_D"; - case PIOD_READ_I: return "READ_I"; - case PIOD_WRITE_I: return "WRITE_I"; - default: return "Unknown op"; - } +const char *Get_PT_IO_OP(int op) { + switch (op) { + case PIOD_READ_D: + return "READ_D"; + case PIOD_WRITE_D: + return "WRITE_D"; + case PIOD_READ_I: + return "READ_I"; + case PIOD_WRITE_I: + return "WRITE_I"; + default: + return "Unknown op"; + } } // Wrapper for ptrace to catch errors and log calls. -// Note that ptrace sets errno on error because -1 is reserved as a valid result. -extern long -PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, - const char* reqName, const char* file, int line) -{ - long int result; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - if (log) { - log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", - reqName, pid, addr, data, file, line); - if (req == PT_IO) { - struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; - - log->Printf("PT_IO: op=%s offs=%zx size=%zu", - Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); - } +// Note that ptrace sets errno on error because -1 is reserved as a valid +// result. +extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, + const char *reqName, const char *file, int line) { + long int result; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + + if (log) { + log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", + reqName, pid, addr, data, file, line); + if (req == PT_IO) { + struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr; + + log->Printf("PT_IO: op=%s offs=%zx size=%zu", Get_PT_IO_OP(pi->piod_op), + (size_t)pi->piod_offs, pi->piod_len); } - - //PtraceDisplayBytes(req, data); - - errno = 0; - result = ptrace(req, pid, (caddr_t) addr, data); - - //PtraceDisplayBytes(req, data); - - if (log && errno != 0) - { - const char* str; - switch (errno) - { - case ESRCH: str = "ESRCH"; break; - case EINVAL: str = "EINVAL"; break; - case EBUSY: str = "EBUSY"; break; - case EPERM: str = "EPERM"; break; - default: str = "<unknown>"; - } - log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + } + + // PtraceDisplayBytes(req, data); + + errno = 0; + result = ptrace(req, pid, (caddr_t)addr, data); + + // PtraceDisplayBytes(req, data); + + if (log && errno != 0) { + const char *str; + switch (errno) { + case ESRCH: + str = "ESRCH"; + break; + case EINVAL: + str = "EINVAL"; + break; + case EBUSY: + str = "EBUSY"; + break; + case EPERM: + str = "EPERM"; + break; + default: + str = "<unknown>"; } + log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + } - if (log) { + if (log) { #ifdef __amd64__ - if (req == PT_GETREGS) { - struct reg *r = (struct reg *) addr; - - log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", - r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); - } - if (req == PT_GETDBREGS || req == PT_SETDBREGS) { - struct dbreg *r = (struct dbreg *) addr; - char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; - - for (int i = 0; i <= 7; i++) - log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); - } -#endif + if (req == PT_GETREGS) { + struct reg *r = (struct reg *)addr; + + log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", + r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); } - - return result; + if (req == PT_GETDBREGS || req == PT_SETDBREGS) { + struct dbreg *r = (struct dbreg *)addr; + char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; + + for (int i = 0; i <= 7; i++) + log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); + } +#endif + } + + return result; } // Wrapper for ptrace when logging is not required. // Sets errno to 0 prior to calling ptrace. -extern long -PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) -{ - long result = 0; - errno = 0; - result = ptrace(req, pid, (caddr_t)addr, data); - return result; +extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { + long result = 0; + errno = 0; + result = ptrace(req, pid, (caddr_t)addr, data); + return result; } -#define PTRACE(req, pid, addr, data) \ - PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) +#define PTRACE(req, pid, addr, data) \ + PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) #else - PtraceWrapper((req), (pid), (addr), (data)) +PtraceWrapper((req), (pid), (addr), (data)) #endif //------------------------------------------------------------------------------ @@ -146,58 +153,50 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) // ProcessMonitor::WriteMemory. This enables mutual recursion between these // functions without needed to go thru the thread funnel. -static size_t -DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, - Error &error) -{ - struct ptrace_io_desc pi_desc; +static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, + size_t size, Error &error) { + struct ptrace_io_desc pi_desc; - pi_desc.piod_op = PIOD_READ_D; - pi_desc.piod_offs = (void *)vm_addr; - pi_desc.piod_addr = buf; - pi_desc.piod_len = size; + pi_desc.piod_op = PIOD_READ_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = buf; + pi_desc.piod_len = size; - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) - error.SetErrorToErrno(); - return pi_desc.piod_len; + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; } -static size_t -DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, - size_t size, Error &error) -{ - struct ptrace_io_desc pi_desc; +static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, + const void *buf, size_t size, Error &error) { + struct ptrace_io_desc pi_desc; - pi_desc.piod_op = PIOD_WRITE_D; - pi_desc.piod_offs = (void *)vm_addr; - pi_desc.piod_addr = (void *)buf; - pi_desc.piod_len = size; + pi_desc.piod_op = PIOD_WRITE_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = (void *)buf; + pi_desc.piod_len = size; - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) - error.SetErrorToErrno(); - return pi_desc.piod_len; + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; } // Simple helper function to ensure flags are enabled on the given file // descriptor. -static bool -EnsureFDFlags(int fd, int flags, Error &error) -{ - int status; - - if ((status = fcntl(fd, F_GETFL)) == -1) - { - error.SetErrorToErrno(); - return false; - } +static bool EnsureFDFlags(int fd, int flags, Error &error) { + int status; - if (fcntl(fd, F_SETFL, status | flags) == -1) - { - error.SetErrorToErrno(); - return false; - } + if ((status = fcntl(fd, F_GETFL)) == -1) { + error.SetErrorToErrno(); + return false; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) { + error.SetErrorToErrno(); + return false; + } - return true; + return true; } //------------------------------------------------------------------------------ @@ -211,1383 +210,1216 @@ EnsureFDFlags(int fd, int flags, Error &error) /// task. The Operation class provides an abstract base for all services the /// ProcessMonitor must perform via the single virtual function Execute, thus /// encapsulating the code that needs to run in the privileged context. -class Operation -{ +class Operation { public: - virtual ~Operation() {} - virtual void Execute(ProcessMonitor *monitor) = 0; + virtual ~Operation() {} + virtual void Execute(ProcessMonitor *monitor) = 0; }; //------------------------------------------------------------------------------ /// @class ReadOperation /// @brief Implements ProcessMonitor::ReadMemory. -class ReadOperation : public Operation -{ +class ReadOperation : public Operation { public: - ReadOperation(lldb::addr_t addr, void *buff, size_t size, - Error &error, size_t &result) - : m_addr(addr), m_buff(buff), m_size(size), - m_error(error), m_result(result) - { } + ReadOperation(lldb::addr_t addr, void *buff, size_t size, Error &error, + size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), m_error(error), + m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::addr_t m_addr; - void *m_buff; - size_t m_size; - Error &m_error; - size_t &m_result; + lldb::addr_t m_addr; + void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; }; -void -ReadOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); +void ReadOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); - m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); + m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); } //------------------------------------------------------------------------------ /// @class WriteOperation /// @brief Implements ProcessMonitor::WriteMemory. -class WriteOperation : public Operation -{ +class WriteOperation : public Operation { public: - WriteOperation(lldb::addr_t addr, const void *buff, size_t size, - Error &error, size_t &result) - : m_addr(addr), m_buff(buff), m_size(size), - m_error(error), m_result(result) - { } + WriteOperation(lldb::addr_t addr, const void *buff, size_t size, Error &error, + size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), m_error(error), + m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::addr_t m_addr; - const void *m_buff; - size_t m_size; - Error &m_error; - size_t &m_result; + lldb::addr_t m_addr; + const void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; }; -void -WriteOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); +void WriteOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); - m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); + m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); } //------------------------------------------------------------------------------ /// @class ReadRegOperation /// @brief Implements ProcessMonitor::ReadRegisterValue. -class ReadRegOperation : public Operation -{ +class ReadRegOperation : public Operation { public: - ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, - RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_size(size), - m_value(value), m_result(result) - { } + ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, + RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), m_size(size), m_value(value), + m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - unsigned m_offset; - unsigned m_size; - RegisterValue &m_value; - bool &m_result; + lldb::tid_t m_tid; + unsigned m_offset; + unsigned m_size; + RegisterValue &m_value; + bool &m_result; }; -void -ReadRegOperation::Execute(ProcessMonitor *monitor) -{ - struct reg regs; - int rc; - - if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) { - m_result = false; - } else { - // 'struct reg' contains only 32- or 64-bit register values. Punt on - // others. Also, not all entries may be uintptr_t sized, such as 32-bit - // processes on powerpc64 (probably the same for i386 on amd64) - if (m_size == sizeof(uint32_t)) - m_value = *(uint32_t *)(((caddr_t)®s) + m_offset); - else if (m_size == sizeof(uint64_t)) - m_value = *(uint64_t *)(((caddr_t)®s) + m_offset); - else - memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); - m_result = true; - } +void ReadRegOperation::Execute(ProcessMonitor *monitor) { + struct reg regs; + int rc; + + if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) { + m_result = false; + } else { + // 'struct reg' contains only 32- or 64-bit register values. Punt on + // others. Also, not all entries may be uintptr_t sized, such as 32-bit + // processes on powerpc64 (probably the same for i386 on amd64) + if (m_size == sizeof(uint32_t)) + m_value = *(uint32_t *)(((caddr_t)®s) + m_offset); + else if (m_size == sizeof(uint64_t)) + m_value = *(uint64_t *)(((caddr_t)®s) + m_offset); + else + memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); + m_result = true; + } } //------------------------------------------------------------------------------ /// @class WriteRegOperation /// @brief Implements ProcessMonitor::WriteRegisterValue. -class WriteRegOperation : public Operation -{ +class WriteRegOperation : public Operation { public: - WriteRegOperation(lldb::tid_t tid, unsigned offset, - const RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), - m_value(value), m_result(result) - { } + WriteRegOperation(lldb::tid_t tid, unsigned offset, + const RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - unsigned m_offset; - const RegisterValue &m_value; - bool &m_result; + lldb::tid_t m_tid; + unsigned m_offset; + const RegisterValue &m_value; + bool &m_result; }; -void -WriteRegOperation::Execute(ProcessMonitor *monitor) -{ - struct reg regs; +void WriteRegOperation::Execute(ProcessMonitor *monitor) { + struct reg regs; - if (PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0) < 0) { - m_result = false; - return; - } - *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); - if (PTRACE(PT_SETREGS, m_tid, (caddr_t)®s, 0) < 0) - m_result = false; - else - m_result = true; + if (PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0) < 0) { + m_result = false; + return; + } + *(uintptr_t *)(((caddr_t)®s) + m_offset) = + (uintptr_t)m_value.GetAsUInt64(); + if (PTRACE(PT_SETREGS, m_tid, (caddr_t)®s, 0) < 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class ReadDebugRegOperation /// @brief Implements ProcessMonitor::ReadDebugRegisterValue. -class ReadDebugRegOperation : public Operation -{ +class ReadDebugRegOperation : public Operation { public: - ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, - RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_size(size), - m_value(value), m_result(result) - { } + ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, + RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), m_size(size), m_value(value), + m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - unsigned m_offset; - unsigned m_size; - RegisterValue &m_value; - bool &m_result; + lldb::tid_t m_tid; + unsigned m_offset; + unsigned m_size; + RegisterValue &m_value; + bool &m_result; }; -void -ReadDebugRegOperation::Execute(ProcessMonitor *monitor) -{ - struct dbreg regs; - int rc; - - if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) { - m_result = false; - } else { - if (m_size == sizeof(uintptr_t)) - m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); - else - memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); - m_result = true; - } +void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) { + struct dbreg regs; + int rc; + + if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) { + m_result = false; + } else { + if (m_size == sizeof(uintptr_t)) + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); + else + memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); + m_result = true; + } } //------------------------------------------------------------------------------ /// @class WriteDebugRegOperation /// @brief Implements ProcessMonitor::WriteDebugRegisterValue. -class WriteDebugRegOperation : public Operation -{ +class WriteDebugRegOperation : public Operation { public: - WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, - const RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), - m_value(value), m_result(result) - { } + WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, + const RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - unsigned m_offset; - const RegisterValue &m_value; - bool &m_result; + lldb::tid_t m_tid; + unsigned m_offset; + const RegisterValue &m_value; + bool &m_result; }; -void -WriteDebugRegOperation::Execute(ProcessMonitor *monitor) -{ - struct dbreg regs; +void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) { + struct dbreg regs; - if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) { - m_result = false; - return; - } - *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); - if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0) - m_result = false; - else - m_result = true; + if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) { + m_result = false; + return; + } + *(uintptr_t *)(((caddr_t)®s) + m_offset) = + (uintptr_t)m_value.GetAsUInt64(); + if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class ReadGPROperation /// @brief Implements ProcessMonitor::ReadGPR. -class ReadGPROperation : public Operation -{ +class ReadGPROperation : public Operation { public: - ReadGPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) - { } + ReadGPROperation(lldb::tid_t tid, void *buf, bool &result) + : m_tid(tid), m_buf(buf), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; + lldb::tid_t m_tid; + void *m_buf; + bool &m_result; }; -void -ReadGPROperation::Execute(ProcessMonitor *monitor) -{ - int rc; +void ReadGPROperation::Execute(ProcessMonitor *monitor) { + int rc; - errno = 0; - rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0); - if (errno != 0) - m_result = false; - else - m_result = true; + errno = 0; + rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0); + if (errno != 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class ReadFPROperation /// @brief Implements ProcessMonitor::ReadFPR. -class ReadFPROperation : public Operation -{ +class ReadFPROperation : public Operation { public: - ReadFPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) - { } + ReadFPROperation(lldb::tid_t tid, void *buf, bool &result) + : m_tid(tid), m_buf(buf), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; + lldb::tid_t m_tid; + void *m_buf; + bool &m_result; }; -void -ReadFPROperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; +void ReadFPROperation::Execute(ProcessMonitor *monitor) { + if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class WriteGPROperation /// @brief Implements ProcessMonitor::WriteGPR. -class WriteGPROperation : public Operation -{ +class WriteGPROperation : public Operation { public: - WriteGPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) - { } + WriteGPROperation(lldb::tid_t tid, void *buf, bool &result) + : m_tid(tid), m_buf(buf), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; + lldb::tid_t m_tid; + void *m_buf; + bool &m_result; }; -void -WriteGPROperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; +void WriteGPROperation::Execute(ProcessMonitor *monitor) { + if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class WriteFPROperation /// @brief Implements ProcessMonitor::WriteFPR. -class WriteFPROperation : public Operation -{ +class WriteFPROperation : public Operation { public: - WriteFPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) - { } + WriteFPROperation(lldb::tid_t tid, void *buf, bool &result) + : m_tid(tid), m_buf(buf), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; + lldb::tid_t m_tid; + void *m_buf; + bool &m_result; }; -void -WriteFPROperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; +void WriteFPROperation::Execute(ProcessMonitor *monitor) { + if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class ResumeOperation /// @brief Implements ProcessMonitor::Resume. -class ResumeOperation : public Operation -{ +class ResumeOperation : public Operation { public: - ResumeOperation(uint32_t signo, bool &result) : - m_signo(signo), m_result(result) { } + ResumeOperation(uint32_t signo, bool &result) + : m_signo(signo), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - uint32_t m_signo; - bool &m_result; + uint32_t m_signo; + bool &m_result; }; -void -ResumeOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); - int data = 0; +void ResumeOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); + int data = 0; - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; - if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) - { - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log) - log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", pid, strerror(errno)); - m_result = false; - } - else - m_result = true; + if (log) + log->Printf("ResumeOperation (%" PRIu64 ") failed: %s", pid, + strerror(errno)); + m_result = false; + } else + m_result = true; } //------------------------------------------------------------------------------ /// @class SingleStepOperation /// @brief Implements ProcessMonitor::SingleStep. -class SingleStepOperation : public Operation -{ +class SingleStepOperation : public Operation { public: - SingleStepOperation(uint32_t signo, bool &result) - : m_signo(signo), m_result(result) { } + SingleStepOperation(uint32_t signo, bool &result) + : m_signo(signo), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - uint32_t m_signo; - bool &m_result; + uint32_t m_signo; + bool &m_result; }; -void -SingleStepOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); - int data = 0; +void SingleStepOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); + int data = 0; - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; - if (PTRACE(PT_STEP, pid, NULL, data)) - m_result = false; - else - m_result = true; + if (PTRACE(PT_STEP, pid, NULL, data)) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class LwpInfoOperation /// @brief Implements ProcessMonitor::GetLwpInfo. -class LwpInfoOperation : public Operation -{ +class LwpInfoOperation : public Operation { public: - LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) - : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { } + LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) + : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - void *m_info; - bool &m_result; - int &m_err; + lldb::tid_t m_tid; + void *m_info; + bool &m_result; + int &m_err; }; -void -LwpInfoOperation::Execute(ProcessMonitor *monitor) -{ - struct ptrace_lwpinfo plwp; - - if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) { - m_result = false; - m_err = errno; - } else { - memcpy(m_info, &plwp, sizeof(plwp)); - m_result = true; - } +void LwpInfoOperation::Execute(ProcessMonitor *monitor) { + struct ptrace_lwpinfo plwp; + + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) { + m_result = false; + m_err = errno; + } else { + memcpy(m_info, &plwp, sizeof(plwp)); + m_result = true; + } } //------------------------------------------------------------------------------ /// @class ThreadSuspendOperation /// @brief Implements ProcessMonitor::ThreadSuspend. -class ThreadSuspendOperation : public Operation -{ +class ThreadSuspendOperation : public Operation { public: - ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result) - : m_tid(tid), m_suspend(suspend), m_result(result) { } + ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result) + : m_tid(tid), m_suspend(suspend), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - bool m_suspend; - bool &m_result; -} ; - -void -ThreadSuspendOperation::Execute(ProcessMonitor *monitor) -{ - m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0); -} - + lldb::tid_t m_tid; + bool m_suspend; + bool &m_result; +}; +void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) { + m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0); +} //------------------------------------------------------------------------------ /// @class EventMessageOperation /// @brief Implements ProcessMonitor::GetEventMessage. -class EventMessageOperation : public Operation -{ +class EventMessageOperation : public Operation { public: - EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) - : m_tid(tid), m_message(message), m_result(result) { } + EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) + : m_tid(tid), m_message(message), m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - lldb::tid_t m_tid; - unsigned long *m_message; - bool &m_result; + lldb::tid_t m_tid; + unsigned long *m_message; + bool &m_result; }; -void -EventMessageOperation::Execute(ProcessMonitor *monitor) -{ - struct ptrace_lwpinfo plwp; +void EventMessageOperation::Execute(ProcessMonitor *monitor) { + struct ptrace_lwpinfo plwp; - if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) - m_result = false; - else { - if (plwp.pl_flags & PL_FLAG_FORKED) { - *m_message = plwp.pl_child_pid; - m_result = true; - } else - m_result = false; - } + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) + m_result = false; + else { + if (plwp.pl_flags & PL_FLAG_FORKED) { + *m_message = plwp.pl_child_pid; + m_result = true; + } else + m_result = false; + } } //------------------------------------------------------------------------------ /// @class KillOperation /// @brief Implements ProcessMonitor::Kill. -class KillOperation : public Operation -{ +class KillOperation : public Operation { public: - KillOperation(bool &result) : m_result(result) { } + KillOperation(bool &result) : m_result(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - bool &m_result; + bool &m_result; }; -void -KillOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); +void KillOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); - if (PTRACE(PT_KILL, pid, NULL, 0)) - m_result = false; - else - m_result = true; + if (PTRACE(PT_KILL, pid, NULL, 0)) + m_result = false; + else + m_result = true; } //------------------------------------------------------------------------------ /// @class DetachOperation /// @brief Implements ProcessMonitor::Detach. -class DetachOperation : public Operation -{ +class DetachOperation : public Operation { public: - DetachOperation(Error &result) : m_error(result) { } + DetachOperation(Error &result) : m_error(result) {} - void Execute(ProcessMonitor *monitor); + void Execute(ProcessMonitor *monitor); private: - Error &m_error; + Error &m_error; }; -void -DetachOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); +void DetachOperation::Execute(ProcessMonitor *monitor) { + lldb::pid_t pid = monitor->GetPID(); - if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) - m_error.SetErrorToErrno(); - + if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) + m_error.SetErrorToErrno(); } ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) - : m_monitor(monitor) -{ - sem_init(&m_semaphore, 0, 0); + : m_monitor(monitor) { + sem_init(&m_semaphore, 0, 0); } -ProcessMonitor::OperationArgs::~OperationArgs() -{ - sem_destroy(&m_semaphore); -} +ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); } ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module, - char const **argv, - char const **envp, + char const **argv, char const **envp, const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir) - : OperationArgs(monitor), - m_module(module), - m_argv(argv), - m_envp(envp), - m_stdin_file_spec(stdin_file_spec), - m_stdout_file_spec(stdout_file_spec), - m_stderr_file_spec(stderr_file_spec), - m_working_dir(working_dir) { } + : OperationArgs(monitor), m_module(module), m_argv(argv), m_envp(envp), + m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec), + m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {} -ProcessMonitor::LaunchArgs::~LaunchArgs() -{ } +ProcessMonitor::LaunchArgs::~LaunchArgs() {} -ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, - lldb::pid_t pid) - : OperationArgs(monitor), m_pid(pid) { } +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid) + : OperationArgs(monitor), m_pid(pid) {} -ProcessMonitor::AttachArgs::~AttachArgs() -{ } +ProcessMonitor::AttachArgs::~AttachArgs() {} //------------------------------------------------------------------------------ /// The basic design of the ProcessMonitor is built around two threads. /// /// One thread (@see SignalThread) simply blocks on a call to waitpid() looking /// for changes in the debugee state. When a change is detected a -/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread +/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This +/// thread /// "drives" state changes in the debugger. /// /// The second thread (@see OperationThread) is responsible for two things 1) /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, - Module *module, - const char *argv[], - const char *envp[], - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo & /* launch_info */, - lldb_private::Error &error) +ProcessMonitor::ProcessMonitor( + ProcessFreeBSD *process, Module *module, const char *argv[], + const char *envp[], const FileSpec &stdin_file_spec, + const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, + const FileSpec &working_dir, + const lldb_private::ProcessLaunchInfo & /* launch_info */, + lldb_private::Error &error) : m_process(static_cast<ProcessFreeBSD *>(process)), - m_pid(LLDB_INVALID_PROCESS_ID), - m_terminal_fd(-1), - m_operation(0) -{ - using namespace std::placeholders; - - std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp, - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir)); - - - sem_init(&m_operation_pending, 0, 0); - sem_init(&m_operation_done, 0, 0); - - StartLaunchOpThread(args.get(), error); - if (!error.Success()) - return; + m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { + using namespace std::placeholders; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) - { - if (errno == EINTR) - goto WAIT_AGAIN; - else - { - error.SetErrorToErrno(); - return; - } - } + std::unique_ptr<LaunchArgs> args( + new LaunchArgs(this, module, argv, envp, stdin_file_spec, + stdout_file_spec, stderr_file_spec, working_dir)); - // Check that the launch was a success. - if (!args->m_error.Success()) - { - StopOpThread(); - error = args->m_error; - return; - } + sem_init(&m_operation_pending, 0, 0); + sem_init(&m_operation_done, 0, 0); + + StartLaunchOpThread(args.get(), error); + if (!error.Success()) + return; - // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( - std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread.IsJoinable()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Process launch failed."); - return; +WAIT_AGAIN: + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) { + if (errno == EINTR) + goto WAIT_AGAIN; + else { + error.SetErrorToErrno(); + return; } -} + } -ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, - lldb::pid_t pid, + // Check that the launch was a success. + if (!args->m_error.Success()) { + StopOpThread(); + error = args->m_error; + return; + } + + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), + GetPID(), true); + if (!m_monitor_thread.IsJoinable()) { + error.SetErrorToGenericError(); + error.SetErrorString("Process launch failed."); + return; + } +} + +ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Error &error) - : m_process(static_cast<ProcessFreeBSD *>(process)), - m_pid(pid), - m_terminal_fd(-1), - m_operation(0) -{ - using namespace std::placeholders; - - sem_init(&m_operation_pending, 0, 0); - sem_init(&m_operation_done, 0, 0); + : m_process(static_cast<ProcessFreeBSD *>(process)), m_pid(pid), + m_terminal_fd(-1), m_operation(0) { + using namespace std::placeholders; + sem_init(&m_operation_pending, 0, 0); + sem_init(&m_operation_done, 0, 0); - std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid)); + std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid)); - StartAttachOpThread(args.get(), error); - if (!error.Success()) - return; + StartAttachOpThread(args.get(), error); + if (!error.Success()) + return; WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) - { - if (errno == EINTR) - goto WAIT_AGAIN; - else - { - error.SetErrorToErrno(); - return; - } + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) { + if (errno == EINTR) + goto WAIT_AGAIN; + else { + error.SetErrorToErrno(); + return; } + } - // Check that the attach was a success. - if (!args->m_error.Success()) - { - StopOpThread(); - error = args->m_error; - return; - } + // Check that the attach was a success. + if (!args->m_error.Success()) { + StopOpThread(); + error = args->m_error; + return; + } - // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( - std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread.IsJoinable()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Process attach failed."); - return; - } + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), + GetPID(), true); + if (!m_monitor_thread.IsJoinable()) { + error.SetErrorToGenericError(); + error.SetErrorString("Process attach failed."); + return; + } } -ProcessMonitor::~ProcessMonitor() -{ - StopMonitor(); -} +ProcessMonitor::~ProcessMonitor() { StopMonitor(); } //------------------------------------------------------------------------------ // Thread setup and tear down. -void -ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) -{ - static const char *g_thread_name = "lldb.process.freebsd.operation"; +void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) { + static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread.IsJoinable()) - return; + if (m_operation_thread.IsJoinable()) + return; - m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); + m_operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); } -void * -ProcessMonitor::LaunchOpThread(void *arg) -{ - LaunchArgs *args = static_cast<LaunchArgs*>(arg); +void *ProcessMonitor::LaunchOpThread(void *arg) { + LaunchArgs *args = static_cast<LaunchArgs *>(arg); - if (!Launch(args)) { - sem_post(&args->m_semaphore); - return NULL; - } - - ServeOperation(args); + if (!Launch(args)) { + sem_post(&args->m_semaphore); return NULL; -} - -bool -ProcessMonitor::Launch(LaunchArgs *args) -{ - ProcessMonitor *monitor = args->m_monitor; - ProcessFreeBSD &process = monitor->GetProcess(); - const char **argv = args->m_argv; - const char **envp = args->m_envp; - const FileSpec &stdin_file_spec = args->m_stdin_file_spec; - const FileSpec &stdout_file_spec = args->m_stdout_file_spec; - const FileSpec &stderr_file_spec = args->m_stderr_file_spec; - const FileSpec &working_dir = args->m_working_dir; - - lldb_utility::PseudoTerminal terminal; - const size_t err_len = 1024; - char err_str[err_len]; - ::pid_t pid; - - // Propagate the environment if one is not supplied. - if (envp == NULL || envp[0] == NULL) - envp = const_cast<const char **>(environ); - - if ((pid = terminal.Fork(err_str, err_len)) == -1) - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Process fork failed."); - goto FINISH; - } - - // Recognized child exit status codes. - enum { - ePtraceFailed = 1, - eDupStdinFailed, - eDupStdoutFailed, - eDupStderrFailed, - eChdirFailed, - eExecFailed, - eSetGidFailed - }; - - // Child process. - if (pid == 0) - { - // Trace this process. - if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) - exit(ePtraceFailed); - - // terminal has already dupped the tty descriptors to stdin/out/err. - // This closes original fd from which they were copied (and avoids - // leaking descriptors to the debugged process. - terminal.CloseSlaveFileDescriptor(); - - // Do not inherit setgid powers. - if (setgid(getgid()) != 0) - exit(eSetGidFailed); - - // Let us have our own process group. - setpgid(0, 0); - - // Dup file descriptors if needed. - // - // FIXME: If two or more of the paths are the same we needlessly open - // the same file multiple times. - if (stdin_file_spec) - if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY)) - exit(eDupStdinFailed); - - if (stdout_file_spec) - if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT)) - exit(eDupStdoutFailed); - - if (stderr_file_spec) - if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT)) - exit(eDupStderrFailed); - - // Change working directory - if (working_dir && 0 != ::chdir(working_dir.GetCString())) - exit(eChdirFailed); - - // Execute. We should never return. - execve(argv[0], - const_cast<char *const *>(argv), - const_cast<char *const *>(envp)); - exit(eExecFailed); - } - - // Wait for the child process to to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - else if (WIFEXITED(status)) - { - // open, dup or execve likely failed for some reason. - args->m_error.SetErrorToGenericError(); - switch (WEXITSTATUS(status)) - { - case ePtraceFailed: - args->m_error.SetErrorString("Child ptrace failed."); - break; - case eDupStdinFailed: - args->m_error.SetErrorString("Child open stdin failed."); - break; - case eDupStdoutFailed: - args->m_error.SetErrorString("Child open stdout failed."); - break; - case eDupStderrFailed: - args->m_error.SetErrorString("Child open stderr failed."); - break; - case eChdirFailed: - args->m_error.SetErrorString("Child failed to set working directory."); - break; - case eExecFailed: - args->m_error.SetErrorString("Child exec failed."); - break; - case eSetGidFailed: - args->m_error.SetErrorString("Child setgid failed."); - break; - default: - args->m_error.SetErrorString("Child returned unknown exit status."); - break; - } - goto FINISH; + } + + ServeOperation(args); + return NULL; +} + +bool ProcessMonitor::Launch(LaunchArgs *args) { + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); + const char **argv = args->m_argv; + const char **envp = args->m_envp; + const FileSpec &stdin_file_spec = args->m_stdin_file_spec; + const FileSpec &stdout_file_spec = args->m_stdout_file_spec; + const FileSpec &stderr_file_spec = args->m_stderr_file_spec; + const FileSpec &working_dir = args->m_working_dir; + + lldb_utility::PseudoTerminal terminal; + const size_t err_len = 1024; + char err_str[err_len]; + ::pid_t pid; + + // Propagate the environment if one is not supplied. + if (envp == NULL || envp[0] == NULL) + envp = const_cast<const char **>(environ); + + if ((pid = terminal.Fork(err_str, err_len)) == -1) { + args->m_error.SetErrorToGenericError(); + args->m_error.SetErrorString("Process fork failed."); + goto FINISH; + } + + // Recognized child exit status codes. + enum { + ePtraceFailed = 1, + eDupStdinFailed, + eDupStdoutFailed, + eDupStderrFailed, + eChdirFailed, + eExecFailed, + eSetGidFailed + }; + + // Child process. + if (pid == 0) { + // Trace this process. + if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) + exit(ePtraceFailed); + + // terminal has already dupped the tty descriptors to stdin/out/err. + // This closes original fd from which they were copied (and avoids + // leaking descriptors to the debugged process. + terminal.CloseSlaveFileDescriptor(); + + // Do not inherit setgid powers. + if (setgid(getgid()) != 0) + exit(eSetGidFailed); + + // Let us have our own process group. + setpgid(0, 0); + + // Dup file descriptors if needed. + // + // FIXME: If two or more of the paths are the same we needlessly open + // the same file multiple times. + if (stdin_file_spec) + if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY)) + exit(eDupStdinFailed); + + if (stdout_file_spec) + if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStdoutFailed); + + if (stderr_file_spec) + if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStderrFailed); + + // Change working directory + if (working_dir && 0 != ::chdir(working_dir.GetCString())) + exit(eChdirFailed); + + // Execute. We should never return. + execve(argv[0], const_cast<char *const *>(argv), + const_cast<char *const *>(envp)); + exit(eExecFailed); + } + + // Wait for the child process to to trap on its call to execve. + ::pid_t wpid; + int status; + if ((wpid = waitpid(pid, &status, 0)) < 0) { + args->m_error.SetErrorToErrno(); + goto FINISH; + } else if (WIFEXITED(status)) { + // open, dup or execve likely failed for some reason. + args->m_error.SetErrorToGenericError(); + switch (WEXITSTATUS(status)) { + case ePtraceFailed: + args->m_error.SetErrorString("Child ptrace failed."); + break; + case eDupStdinFailed: + args->m_error.SetErrorString("Child open stdin failed."); + break; + case eDupStdoutFailed: + args->m_error.SetErrorString("Child open stdout failed."); + break; + case eDupStderrFailed: + args->m_error.SetErrorString("Child open stderr failed."); + break; + case eChdirFailed: + args->m_error.SetErrorString("Child failed to set working directory."); + break; + case eExecFailed: + args->m_error.SetErrorString("Child exec failed."); + break; + case eSetGidFailed: + args->m_error.SetErrorString("Child setgid failed."); + break; + default: + args->m_error.SetErrorString("Child returned unknown exit status."); + break; } - assert(WIFSTOPPED(status) && wpid == (::pid_t)pid && - "Could not sync with inferior process."); + goto FINISH; + } + assert(WIFSTOPPED(status) && wpid == (::pid_t)pid && + "Could not sync with inferior process."); #ifdef notyet - // Have the child raise an event on exit. This is used to keep the child in - // limbo until it is destroyed. - if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } + // Have the child raise an event on exit. This is used to keep the child in + // limbo until it is destroyed. + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) { + args->m_error.SetErrorToErrno(); + goto FINISH; + } #endif - // Release the master terminal descriptor and pass it off to the - // ProcessMonitor instance. Similarly stash the inferior pid. - monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); - monitor->m_pid = pid; + // Release the master terminal descriptor and pass it off to the + // ProcessMonitor instance. Similarly stash the inferior pid. + monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); + monitor->m_pid = pid; - // Set the terminal fd to be in non blocking mode (it simplifies the - // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking - // descriptor to read from). - if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) - goto FINISH; + // Set the terminal fd to be in non blocking mode (it simplifies the + // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking + // descriptor to read from). + if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) + goto FINISH; - process.SendMessage(ProcessMessage::Attach(pid)); + process.SendMessage(ProcessMessage::Attach(pid)); FINISH: - return args->m_error.Success(); + return args->m_error.Success(); } -void -ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) -{ - static const char *g_thread_name = "lldb.process.freebsd.operation"; +void ProcessMonitor::StartAttachOpThread(AttachArgs *args, + lldb_private::Error &error) { + static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread.IsJoinable()) - return; + if (m_operation_thread.IsJoinable()) + return; - m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); + m_operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); } -void * -ProcessMonitor::AttachOpThread(void *arg) -{ - AttachArgs *args = static_cast<AttachArgs*>(arg); +void *ProcessMonitor::AttachOpThread(void *arg) { + AttachArgs *args = static_cast<AttachArgs *>(arg); - Attach(args); + Attach(args); - ServeOperation(args); - return NULL; + ServeOperation(args); + return NULL; } -void -ProcessMonitor::Attach(AttachArgs *args) -{ - lldb::pid_t pid = args->m_pid; +void ProcessMonitor::Attach(AttachArgs *args) { + lldb::pid_t pid = args->m_pid; - ProcessMonitor *monitor = args->m_monitor; - ProcessFreeBSD &process = monitor->GetProcess(); + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); - if (pid <= 1) - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Attaching to process 1 is not allowed."); - return; - } + if (pid <= 1) { + args->m_error.SetErrorToGenericError(); + args->m_error.SetErrorString("Attaching to process 1 is not allowed."); + return; + } - // Attach to the requested process. - if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) - { - args->m_error.SetErrorToErrno(); - return; - } + // Attach to the requested process. + if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) { + args->m_error.SetErrorToErrno(); + return; + } - int status; - if ((status = waitpid(pid, NULL, 0)) < 0) - { - args->m_error.SetErrorToErrno(); - return; - } + int status; + if ((status = waitpid(pid, NULL, 0)) < 0) { + args->m_error.SetErrorToErrno(); + return; + } - process.SendMessage(ProcessMessage::Attach(pid)); + process.SendMessage(ProcessMessage::Attach(pid)); } size_t -ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t>&thread_ids) -{ - lwpid_t *tids; - int tdcnt; - - thread_ids.clear(); - - tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0); - if (tdcnt <= 0) - return 0; - tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids)); - if (tids == NULL) - return 0; - if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) { - free(tids); - return 0; - } - thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt); +ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids) { + lwpid_t *tids; + int tdcnt; + + thread_ids.clear(); + + tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0); + if (tdcnt <= 0) + return 0; + tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids)); + if (tids == NULL) + return 0; + if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) { free(tids); - return thread_ids.size(); + return 0; + } + thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt); + free(tids); + return thread_ids.size(); } -bool -ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, bool exited, int signal, int status) -{ - ProcessMessage message; - ProcessFreeBSD *process = monitor->m_process; - assert(process); - bool stop_monitoring; - struct ptrace_lwpinfo plwp; - int ptrace_err; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - if (exited) - { - if (log) - log->Printf ("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, __FUNCTION__, pid); - message = ProcessMessage::Exit(pid, status); - process->SendMessage(message); - return pid == process->GetID(); - } +bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, + bool exited, int signal, int status) { + ProcessMessage message; + ProcessFreeBSD *process = monitor->m_process; + assert(process); + bool stop_monitoring; + struct ptrace_lwpinfo plwp; + int ptrace_err; - if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err)) - stop_monitoring = true; // pid is gone. Bail. - else { - switch (plwp.pl_siginfo.si_signo) - { - case SIGTRAP: - message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); - break; - - default: - message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); - break; - } - - process->SendMessage(message); - stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; - } - - return stop_monitoring; -} + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); -ProcessMessage -ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, - const siginfo_t *info, lldb::tid_t tid) -{ - ProcessMessage message; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - assert(monitor); - assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!"); + if (exited) { + if (log) + log->Printf("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, + __FUNCTION__, pid); + message = ProcessMessage::Exit(pid, status); + process->SendMessage(message); + return pid == process->GetID(); + } + + if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err)) + stop_monitoring = true; // pid is gone. Bail. + else { + switch (plwp.pl_siginfo.si_signo) { + case SIGTRAP: + message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); + break; - switch (info->si_code) - { default: - assert(false && "Unexpected SIGTRAP code!"); - break; - - case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): - { - // The inferior process is about to exit. Maintain the process in a - // state of "limbo" until we are explicitly commanded to detach, - // destroy, resume, etc. - unsigned long data = 0; - if (!monitor->GetEventMessage(tid, &data)) - data = -1; - if (log) - log->Printf ("ProcessMonitor::%s() received exit? event, data = %lx, tid = %" PRIu64, __FUNCTION__, data, tid); - message = ProcessMessage::Limbo(tid, (data >> 8)); - break; + message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); + break; } - case 0: - case TRAP_TRACE: - if (log) - log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64 " : si_code = %d", __FUNCTION__, tid, info->si_code); - message = ProcessMessage::Trace(tid); - break; - - case SI_KERNEL: - case TRAP_BRKPT: - if (log) - log->Printf ("ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, __FUNCTION__, tid); - message = ProcessMessage::Break(tid); - break; - } + process->SendMessage(message); + stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; + } - return message; + return stop_monitoring; } -ProcessMessage -ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, - const siginfo_t *info, lldb::tid_t tid) -{ - ProcessMessage message; - int signo = info->si_signo; +ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, + lldb::tid_t tid) { + ProcessMessage message; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - // POSIX says that process behaviour is undefined after it ignores a SIGFPE, - // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a - // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. - // - // IOW, user generated signals never generate what we consider to be a - // "crash". - // - // Similarly, ACK signals generated by this monitor. - if (info->si_code == SI_USER) - { - if (log) - log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d", - __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo), - "SI_USER", - info->si_pid); - if (info->si_pid == getpid()) - return ProcessMessage::SignalDelivered(tid, signo); - else - return ProcessMessage::Signal(tid, signo); - } + assert(monitor); + assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!"); + switch (info->si_code) { + default: + assert(false && "Unexpected SIGTRAP code!"); + break; + + case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): { + // The inferior process is about to exit. Maintain the process in a + // state of "limbo" until we are explicitly commanded to detach, + // destroy, resume, etc. + unsigned long data = 0; + if (!monitor->GetEventMessage(tid, &data)) + data = -1; if (log) - log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo)); - - switch (signo) - { - case SIGSEGV: - case SIGILL: - case SIGFPE: - case SIGBUS: - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - const auto reason = GetCrashReason(*info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } + log->Printf("ProcessMonitor::%s() received exit? event, data = %lx, tid " + "= %" PRIu64, + __FUNCTION__, data, tid); + message = ProcessMessage::Limbo(tid, (data >> 8)); + break; + } + + case 0: + case TRAP_TRACE: + if (log) + log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64 + " : si_code = %d", + __FUNCTION__, tid, info->si_code); + message = ProcessMessage::Trace(tid); + break; + + case SI_KERNEL: + case TRAP_BRKPT: + if (log) + log->Printf( + "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, + __FUNCTION__, tid); + message = ProcessMessage::Break(tid); + break; + } + + return message; +} + +ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, + lldb::tid_t tid) { + ProcessMessage message; + int signo = info->si_signo; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a + // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. + // + // IOW, user generated signals never generate what we consider to be a + // "crash". + // + // Similarly, ACK signals generated by this monitor. + if (info->si_code == SI_USER) { + if (log) + log->Printf( + "ProcessMonitor::%s() received signal %s with code %s, pid = %d", + __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), + "SI_USER", info->si_pid); + if (info->si_pid == getpid()) + return ProcessMessage::SignalDelivered(tid, signo); + else + return ProcessMessage::Signal(tid, signo); + } + + if (log) + log->Printf( + "ProcessMonitor::%s() received signal %s", __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); - // Everything else is "normal" and does not require any special action on - // our part. - return ProcessMessage::Signal(tid, signo); + switch (signo) { + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: + lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); + const auto reason = GetCrashReason(*info); + return ProcessMessage::Crash(tid, reason, signo, fault_addr); + } + + // Everything else is "normal" and does not require any special action on + // our part. + return ProcessMessage::Signal(tid, signo); } -void -ProcessMonitor::ServeOperation(OperationArgs *args) -{ - ProcessMonitor *monitor = args->m_monitor; +void ProcessMonitor::ServeOperation(OperationArgs *args) { + ProcessMonitor *monitor = args->m_monitor; - // We are finised with the arguments and are ready to go. Sync with the - // parent thread and start serving operations on the inferior. - sem_post(&args->m_semaphore); + // We are finised with the arguments and are ready to go. Sync with the + // parent thread and start serving operations on the inferior. + sem_post(&args->m_semaphore); - for (;;) - { - // wait for next pending operation - sem_wait(&monitor->m_operation_pending); + for (;;) { + // wait for next pending operation + sem_wait(&monitor->m_operation_pending); - monitor->m_operation->Execute(monitor); + monitor->m_operation->Execute(monitor); - // notify calling thread that operation is complete - sem_post(&monitor->m_operation_done); - } + // notify calling thread that operation is complete + sem_post(&monitor->m_operation_done); + } } -void -ProcessMonitor::DoOperation(Operation *op) -{ - std::lock_guard<std::mutex> guard(m_operation_mutex); +void ProcessMonitor::DoOperation(Operation *op) { + std::lock_guard<std::mutex> guard(m_operation_mutex); - m_operation = op; + m_operation = op; - // notify operation thread that an operation is ready to be processed - sem_post(&m_operation_pending); + // notify operation thread that an operation is ready to be processed + sem_post(&m_operation_pending); - // wait for operation to complete - sem_wait(&m_operation_done); + // wait for operation to complete + sem_wait(&m_operation_done); } -size_t -ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - Error &error) -{ - size_t result; - ReadOperation op(vm_addr, buf, size, error, result); - DoOperation(&op); - return result; +size_t ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + Error &error) { + size_t result; + ReadOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; } -size_t -ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error) -{ - size_t result; - WriteOperation op(vm_addr, buf, size, error, result); - DoOperation(&op); - return result; +size_t ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, + size_t size, lldb_private::Error &error) { + size_t result; + WriteOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name, - unsigned size, RegisterValue &value) -{ - bool result; - ReadRegOperation op(tid, offset, size, value, result); - DoOperation(&op); - return result; +bool ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, unsigned size, + RegisterValue &value) { + bool result; + ReadRegOperation op(tid, offset, size, value, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char* reg_name, const RegisterValue &value) -{ - bool result; - WriteRegOperation op(tid, offset, value, result); - DoOperation(&op); - return result; +bool ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, + const RegisterValue &value) { + bool result; + WriteRegOperation op(tid, offset, value, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, unsigned size, - lldb_private::RegisterValue &value) -{ - bool result; - ReadDebugRegOperation op(tid, offset, size, value, result); - DoOperation(&op); - return result; +bool ProcessMonitor::ReadDebugRegisterValue( + lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size, + lldb_private::RegisterValue &value) { + bool result; + ReadDebugRegOperation op(tid, offset, size, value, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, - const lldb_private::RegisterValue &value) -{ - bool result; - WriteDebugRegOperation op(tid, offset, value, result); - DoOperation(&op); - return result; +bool ProcessMonitor::WriteDebugRegisterValue( + lldb::tid_t tid, unsigned offset, const char *reg_name, + const lldb_private::RegisterValue &value) { + bool result; + WriteDebugRegOperation op(tid, offset, value, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - ReadGPROperation op(tid, buf, result); - DoOperation(&op); - return result; +bool ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) { + bool result; + ReadGPROperation op(tid, buf, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - ReadFPROperation op(tid, buf, result); - DoOperation(&op); - return result; +bool ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) { + bool result; + ReadFPROperation op(tid, buf, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - return false; +bool ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, + size_t buf_size, unsigned int regset) { + return false; } -bool -ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - WriteGPROperation op(tid, buf, result); - DoOperation(&op); - return result; +bool ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) { + bool result; + WriteGPROperation op(tid, buf, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - WriteFPROperation op(tid, buf, result); - DoOperation(&op); - return result; +bool ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) { + bool result; + WriteFPROperation op(tid, buf, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - return false; +bool ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, + size_t buf_size, unsigned int regset) { + return false; } -bool -ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) -{ - return false; +bool ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) { + return false; } -bool -ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) -{ - bool result; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - if (log) { - const char *signame = m_process->GetUnixSignals()->GetSignalAsCString (signo); - if (signame == nullptr) - signame = "<none>"; - log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", - __FUNCTION__, GetPID(), signame); - } - ResumeOperation op(signo, result); - DoOperation(&op); - if (log) - log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false"); - return result; +bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) { + bool result; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + if (log) { + const char *signame = + m_process->GetUnixSignals()->GetSignalAsCString(signo); + if (signame == nullptr) + signame = "<none>"; + log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", + __FUNCTION__, GetPID(), signame); + } + ResumeOperation op(signo, result); + DoOperation(&op); + if (log) + log->Printf("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, + result ? "true" : "false"); + return result; } -bool -ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) -{ - bool result; - SingleStepOperation op(signo, result); - DoOperation(&op); - return result; +bool ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) { + bool result; + SingleStepOperation op(signo, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::Kill() -{ - bool result; - KillOperation op(result); - DoOperation(&op); - return result; +bool ProcessMonitor::Kill() { + bool result; + KillOperation op(result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err) -{ - bool result; - LwpInfoOperation op(tid, lwpinfo, result, ptrace_err); - DoOperation(&op); - return result; +bool ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, + int &ptrace_err) { + bool result; + LwpInfoOperation op(tid, lwpinfo, result, ptrace_err); + DoOperation(&op); + return result; } -bool -ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) -{ - bool result; - ThreadSuspendOperation op(tid, suspend, result); - DoOperation(&op); - return result; +bool ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) { + bool result; + ThreadSuspendOperation op(tid, suspend, result); + DoOperation(&op); + return result; } -bool -ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) -{ - bool result; - EventMessageOperation op(tid, message, result); - DoOperation(&op); - return result; +bool ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) { + bool result; + EventMessageOperation op(tid, message, result); + DoOperation(&op); + return result; } -lldb_private::Error -ProcessMonitor::Detach(lldb::tid_t tid) -{ - lldb_private::Error error; - if (tid != LLDB_INVALID_THREAD_ID) - { - DetachOperation op(error); - DoOperation(&op); - } - return error; -} +lldb_private::Error ProcessMonitor::Detach(lldb::tid_t tid) { + lldb_private::Error error; + if (tid != LLDB_INVALID_THREAD_ID) { + DetachOperation op(error); + DoOperation(&op); + } + return error; +} -bool -ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, int flags) -{ - int target_fd = open(file_spec.GetCString(), flags, 0666); +bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, + int flags) { + int target_fd = open(file_spec.GetCString(), flags, 0666); - if (target_fd == -1) - return false; + if (target_fd == -1) + return false; - if (dup2(target_fd, fd) == -1) - return false; + if (dup2(target_fd, fd) == -1) + return false; - return (close(target_fd) == -1) ? false : true; + return (close(target_fd) == -1) ? false : true; } -void -ProcessMonitor::StopMonitoringChildProcess() -{ - if (m_monitor_thread.IsJoinable()) - { - m_monitor_thread.Cancel(); - m_monitor_thread.Join(nullptr); - m_monitor_thread.Reset(); - } +void ProcessMonitor::StopMonitoringChildProcess() { + if (m_monitor_thread.IsJoinable()) { + m_monitor_thread.Cancel(); + m_monitor_thread.Join(nullptr); + m_monitor_thread.Reset(); + } } -void -ProcessMonitor::StopMonitor() -{ - StopMonitoringChildProcess(); - StopOpThread(); - sem_destroy(&m_operation_pending); - sem_destroy(&m_operation_done); - if (m_terminal_fd >= 0) { - close(m_terminal_fd); - m_terminal_fd = -1; - } +void ProcessMonitor::StopMonitor() { + StopMonitoringChildProcess(); + StopOpThread(); + sem_destroy(&m_operation_pending); + sem_destroy(&m_operation_done); + if (m_terminal_fd >= 0) { + close(m_terminal_fd); + m_terminal_fd = -1; + } } // FIXME: On Linux, when a new thread is created, we receive to notifications, @@ -1607,19 +1439,13 @@ ProcessMonitor::StopMonitor() // We really should figure out what actually happens on FreeBSD and move the // Linux-specific logic out of ProcessPOSIX as needed. -bool -ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) -{ - return true; -} +bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; } -void -ProcessMonitor::StopOpThread() -{ - if (!m_operation_thread.IsJoinable()) - return; +void ProcessMonitor::StopOpThread() { + if (!m_operation_thread.IsJoinable()) + return; - m_operation_thread.Cancel(); - m_operation_thread.Join(nullptr); - m_operation_thread.Reset(); + m_operation_thread.Cancel(); + m_operation_thread.Join(nullptr); + m_operation_thread.Reset(); } diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 93f6be11136..4c2594e9da6 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -18,12 +18,11 @@ #include <mutex> // Other libraries and framework includes -#include "lldb/lldb-types.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" +#include "lldb/lldb-types.h" -namespace lldb_private -{ +namespace lldb_private { class Error; class Module; class Scalar; @@ -44,285 +43,242 @@ class Operation; /// /// A purposely minimal set of operations are provided to interrogate and change /// the inferior process state. -class ProcessMonitor -{ +class ProcessMonitor { public: - - /// Launches an inferior process ready for debugging. Forms the - /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessFreeBSD *process, - lldb_private::Module *module, - char const *argv[], - char const *envp[], - const lldb_private::FileSpec &stdin_file_spec, - const lldb_private::FileSpec &stdout_file_spec, - const lldb_private::FileSpec &stderr_file_spec, - const lldb_private::FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo &launch_info, - lldb_private::Error &error); - - ProcessMonitor(ProcessFreeBSD *process, - lldb::pid_t pid, - lldb_private::Error &error); - - ~ProcessMonitor(); - - /// Provides the process number of debugee. - lldb::pid_t - GetPID() const { return m_pid; } - - /// Returns the process associated with this ProcessMonitor. - ProcessFreeBSD & - GetProcess() { return *m_process; } - - /// Returns a file descriptor to the controlling terminal of the inferior - /// process. - /// - /// Reads from this file descriptor yield both the standard output and - /// standard error of this debugee. Even if stderr and stdout were - /// redirected on launch it may still happen that data is available on this - /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is - /// closed after a call to StopMonitor(). - /// - /// If this monitor was attached to an existing process this method returns - /// -1. - int - GetTerminalFD() const { return m_terminal_fd; } - - /// Reads @p size bytes from address @vm_adder in the inferior process - /// address space. - /// - /// This method is provided to implement Process::DoReadMemory. - size_t - ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - lldb_private::Error &error); - - /// Writes @p size bytes from address @p vm_adder in the inferior process - /// address space. - /// - /// This method is provided to implement Process::DoWriteMemory. - size_t - WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); - - /// Reads the contents from the register identified by the given (architecture - /// dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - unsigned size, lldb_private::RegisterValue &value); - - /// Writes the given value to the register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - const lldb_private::RegisterValue &value); - - /// Reads the contents from the debug register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, unsigned size, - lldb_private::RegisterValue &value); - - /// Writes the given value to the debug register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, - const lldb_private::RegisterValue &value); - /// Reads all general purpose registers into the specified buffer. - bool - ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Reads all floating point registers into the specified buffer. - bool - ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Reads the specified register set into the specified buffer. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - /// Writes all general purpose registers into the specified buffer. - bool - WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Writes all floating point registers into the specified buffer. - bool - WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Writes the specified register set into the specified buffer. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool - WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - /// Reads the value of the thread-specific pointer for a given thread ID. - bool - ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value); - - /// Returns current thread IDs in process - size_t - GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids); - - /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID - /// to the memory region pointed to by @p lwpinfo. - bool - GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no); - - /// Suspends or unsuspends a thread prior to process resume or step. - bool - ThreadSuspend(lldb::tid_t tid, bool suspend); - - /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) - /// corresponding to the given thread IDto the memory pointed to by @p - /// message. - bool - GetEventMessage(lldb::tid_t tid, unsigned long *message); - - /// Resumes the process. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. - bool - Resume(lldb::tid_t unused, uint32_t signo); - - /// Single steps the process. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. - bool - SingleStep(lldb::tid_t unused, uint32_t signo); - - /// Terminate the traced process. - bool - Kill(); - - lldb_private::Error - Detach(lldb::tid_t tid); - - void - StopMonitor(); - - // Waits for the initial stop message from a new thread. - bool - WaitForInitialTIDStop(lldb::tid_t tid); + /// Launches an inferior process ready for debugging. Forms the + /// implementation of Process::DoLaunch. + ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module, + char const *argv[], char const *envp[], + const lldb_private::FileSpec &stdin_file_spec, + const lldb_private::FileSpec &stdout_file_spec, + const lldb_private::FileSpec &stderr_file_spec, + const lldb_private::FileSpec &working_dir, + const lldb_private::ProcessLaunchInfo &launch_info, + lldb_private::Error &error); + + ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, + lldb_private::Error &error); + + ~ProcessMonitor(); + + /// Provides the process number of debugee. + lldb::pid_t GetPID() const { return m_pid; } + + /// Returns the process associated with this ProcessMonitor. + ProcessFreeBSD &GetProcess() { return *m_process; } + + /// Returns a file descriptor to the controlling terminal of the inferior + /// process. + /// + /// Reads from this file descriptor yield both the standard output and + /// standard error of this debugee. Even if stderr and stdout were + /// redirected on launch it may still happen that data is available on this + /// descriptor (if the inferior process opens /dev/tty, for example). This + /// descriptor is + /// closed after a call to StopMonitor(). + /// + /// If this monitor was attached to an existing process this method returns + /// -1. + int GetTerminalFD() const { return m_terminal_fd; } + + /// Reads @p size bytes from address @vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoReadMemory. + size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error); + + /// Writes @p size bytes from address @p vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoWriteMemory. + size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error); + + /// Reads the contents from the register identified by the given (architecture + /// dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, + unsigned size, lldb_private::RegisterValue &value); + + /// Writes the given value to the register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool WriteRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, + const lldb_private::RegisterValue &value); + + /// Reads the contents from the debug register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, unsigned size, + lldb_private::RegisterValue &value); + + /// Writes the given value to the debug register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, + const lldb_private::RegisterValue &value); + /// Reads all general purpose registers into the specified buffer. + bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); + + /// Reads all floating point registers into the specified buffer. + bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); + + /// Reads the specified register set into the specified buffer. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, + unsigned int regset); + + /// Writes all general purpose registers into the specified buffer. + bool WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size); + + /// Writes all floating point registers into the specified buffer. + bool WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size); + + /// Writes the specified register set into the specified buffer. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, + unsigned int regset); + + /// Reads the value of the thread-specific pointer for a given thread ID. + bool ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value); + + /// Returns current thread IDs in process + size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids); + + /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID + /// to the memory region pointed to by @p lwpinfo. + bool GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no); + + /// Suspends or unsuspends a thread prior to process resume or step. + bool ThreadSuspend(lldb::tid_t tid, bool suspend); + + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) + /// corresponding to the given thread IDto the memory pointed to by @p + /// message. + bool GetEventMessage(lldb::tid_t tid, unsigned long *message); + + /// Resumes the process. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. + bool Resume(lldb::tid_t unused, uint32_t signo); + + /// Single steps the process. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. + bool SingleStep(lldb::tid_t unused, uint32_t signo); + + /// Terminate the traced process. + bool Kill(); + + lldb_private::Error Detach(lldb::tid_t tid); + + void StopMonitor(); + + // Waits for the initial stop message from a new thread. + bool WaitForInitialTIDStop(lldb::tid_t tid); private: - ProcessFreeBSD *m_process; + ProcessFreeBSD *m_process; - lldb_private::HostThread m_operation_thread; - lldb_private::HostThread m_monitor_thread; - lldb::pid_t m_pid; + lldb_private::HostThread m_operation_thread; + lldb_private::HostThread m_monitor_thread; + lldb::pid_t m_pid; - int m_terminal_fd; + int m_terminal_fd; - // current operation which must be executed on the privileged thread - Operation *m_operation; - std::mutex m_operation_mutex; + // current operation which must be executed on the privileged thread + Operation *m_operation; + std::mutex m_operation_mutex; - // semaphores notified when Operation is ready to be processed and when - // the operation is complete. - sem_t m_operation_pending; - sem_t m_operation_done; + // semaphores notified when Operation is ready to be processed and when + // the operation is complete. + sem_t m_operation_pending; + sem_t m_operation_done; - struct OperationArgs - { - OperationArgs(ProcessMonitor *monitor); + struct OperationArgs { + OperationArgs(ProcessMonitor *monitor); - ~OperationArgs(); + ~OperationArgs(); - ProcessMonitor *m_monitor; // The monitor performing the attach. - sem_t m_semaphore; // Posted to once operation complete. - lldb_private::Error m_error; // Set if process operation failed. - }; + ProcessMonitor *m_monitor; // The monitor performing the attach. + sem_t m_semaphore; // Posted to once operation complete. + lldb_private::Error m_error; // Set if process operation failed. + }; - /// @class LauchArgs - /// - /// @brief Simple structure to pass data to the thread responsible for - /// launching a child process. - struct LaunchArgs : OperationArgs - { - LaunchArgs(ProcessMonitor *monitor, - lldb_private::Module *module, - char const **argv, - char const **envp, - const lldb_private::FileSpec &stdin_file_spec, - const lldb_private::FileSpec &stdout_file_spec, - const lldb_private::FileSpec &stderr_file_spec, - const lldb_private::FileSpec &working_dir); + /// @class LauchArgs + /// + /// @brief Simple structure to pass data to the thread responsible for + /// launching a child process. + struct LaunchArgs : OperationArgs { + LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module, + char const **argv, char const **envp, + const lldb_private::FileSpec &stdin_file_spec, + const lldb_private::FileSpec &stdout_file_spec, + const lldb_private::FileSpec &stderr_file_spec, + const lldb_private::FileSpec &working_dir); - ~LaunchArgs(); + ~LaunchArgs(); - lldb_private::Module *m_module; // The executable image to launch. - char const **m_argv; // Process arguments. - char const **m_envp; // Process environment. - const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty. - const lldb_private::FileSpec m_stdout_file_spec; // Redirect stdout or empty. - const lldb_private::FileSpec m_stderr_file_spec; // Redirect stderr or empty. - const lldb_private::FileSpec m_working_dir; // Working directory or empty. - }; + lldb_private::Module *m_module; // The executable image to launch. + char const **m_argv; // Process arguments. + char const **m_envp; // Process environment. + const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty. + const lldb_private::FileSpec + m_stdout_file_spec; // Redirect stdout or empty. + const lldb_private::FileSpec + m_stderr_file_spec; // Redirect stderr or empty. + const lldb_private::FileSpec m_working_dir; // Working directory or empty. + }; - void - StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); + void StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); - static void * - LaunchOpThread(void *arg); + static void *LaunchOpThread(void *arg); - static bool - Launch(LaunchArgs *args); + static bool Launch(LaunchArgs *args); - struct AttachArgs : OperationArgs - { - AttachArgs(ProcessMonitor *monitor, - lldb::pid_t pid); + struct AttachArgs : OperationArgs { + AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid); - ~AttachArgs(); + ~AttachArgs(); - lldb::pid_t m_pid; // pid of the process to be attached. - }; + lldb::pid_t m_pid; // pid of the process to be attached. + }; - void - StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); + void StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); - static void * - AttachOpThread(void *args); + static void *AttachOpThread(void *args); - static void - Attach(AttachArgs *args); + static void Attach(AttachArgs *args); - static void - ServeOperation(OperationArgs *args); + static void ServeOperation(OperationArgs *args); - static bool - DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, int flags); + static bool DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, + int flags); - static bool - MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, bool exited, int signal, int status); + static bool MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, + bool exited, int signal, int status); - static ProcessMessage - MonitorSIGTRAP(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid); + static ProcessMessage MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); - static ProcessMessage - MonitorSignal(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid); + static ProcessMessage MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); - void - DoOperation(Operation *op); + void DoOperation(Operation *op); - /// Stops the child monitor thread. - void - StopMonitoringChildProcess(); + /// Stops the child monitor thread. + void StopMonitoringChildProcess(); - /// Stops the operation thread used to attach/launch a process. - void - StopOpThread(); + /// Stops the operation thread used to attach/launch a process. + void StopOpThread(); }; #endif // #ifndef liblldb_ProcessMonitor_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h index 6ddd9cfe4c2..c0b9b2f4a2d 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h @@ -13,67 +13,56 @@ // C Includes // C++ Includes // Other libraries and framework includes +#include "RegisterInfoInterface.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Target/RegisterContext.h" -#include "RegisterInfoInterface.h" //------------------------------------------------------------------------------ /// @class POSIXBreakpointProtocol /// /// @brief Extends RegisterClass with a few virtual operations useful on POSIX. -class POSIXBreakpointProtocol -{ +class POSIXBreakpointProtocol { public: - POSIXBreakpointProtocol() - { m_watchpoints_initialized = false; } - virtual ~POSIXBreakpointProtocol() {} + POSIXBreakpointProtocol() { m_watchpoints_initialized = false; } + virtual ~POSIXBreakpointProtocol() {} - /// Updates the register state of the associated thread after hitting a - /// breakpoint (if that make sense for the architecture). Default - /// implementation simply returns true for architectures which do not - /// require any update. - /// - /// @return - /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() = 0; + /// Updates the register state of the associated thread after hitting a + /// breakpoint (if that make sense for the architecture). Default + /// implementation simply returns true for architectures which do not + /// require any update. + /// + /// @return + /// True if the operation succeeded and false otherwise. + virtual bool UpdateAfterBreakpoint() = 0; - /// Determines the index in lldb's register file given a kernel byte offset. - virtual unsigned - GetRegisterIndexFromOffset(unsigned offset) = 0; + /// Determines the index in lldb's register file given a kernel byte offset. + virtual unsigned GetRegisterIndexFromOffset(unsigned offset) = 0; - // Checks to see if a watchpoint specified by hw_index caused the inferior - // to stop. - virtual bool - IsWatchpointHit (uint32_t hw_index) = 0; + // Checks to see if a watchpoint specified by hw_index caused the inferior + // to stop. + virtual bool IsWatchpointHit(uint32_t hw_index) = 0; - // Resets any watchpoints that have been hit. - virtual bool - ClearWatchpointHits () = 0; + // Resets any watchpoints that have been hit. + virtual bool ClearWatchpointHits() = 0; - // Returns the watchpoint address associated with a watchpoint hardware - // index. - virtual lldb::addr_t - GetWatchpointAddress (uint32_t hw_index) = 0; + // Returns the watchpoint address associated with a watchpoint hardware + // index. + virtual lldb::addr_t GetWatchpointAddress(uint32_t hw_index) = 0; - virtual bool - IsWatchpointVacant (uint32_t hw_index) = 0; + virtual bool IsWatchpointVacant(uint32_t hw_index) = 0; - virtual bool - SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) = 0; + virtual bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, + bool read, bool write, + uint32_t hw_index) = 0; - // From lldb_private::RegisterContext - virtual uint32_t - NumSupportedHardwareWatchpoints () = 0; + // From lldb_private::RegisterContext + virtual uint32_t NumSupportedHardwareWatchpoints() = 0; - // Force m_watchpoints_initialized to TRUE - void - ForceWatchpointsInitialized () {m_watchpoints_initialized = true;} + // Force m_watchpoints_initialized to TRUE + void ForceWatchpointsInitialized() { m_watchpoints_initialized = true; } protected: - bool m_watchpoints_initialized; + bool m_watchpoints_initialized; }; #endif // #ifndef liblldb_RegisterContextPOSIX_H_ - diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp index 9922311fd9d..f8d5f2edd3a 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -11,312 +11,250 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX_arm.h" #include "ProcessFreeBSD.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" #include "ProcessMonitor.h" +#include "RegisterContextPOSIXProcessMonitor_arm.h" +#include "RegisterContextPOSIX_arm.h" using namespace lldb_private; using namespace lldb; #define REG_CONTEXT_SIZE (GetGPRSize()) -RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_arm(thread, concrete_frame_idx, register_info) -{ -} +RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm( + Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : RegisterContextPOSIX_arm(thread, concrete_frame_idx, register_info) {} -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_arm::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get()); - return process->GetMonitor(); +ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm::GetMonitor() { + ProcessSP base = CalculateProcess(); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get()); + return process->GetMonitor(); } -bool -RegisterContextPOSIXProcessMonitor_arm::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_arm::ReadGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_arm::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); +bool RegisterContextPOSIXProcessMonitor_arm::ReadFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); } -bool -RegisterContextPOSIXProcessMonitor_arm::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_arm::WriteGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_arm::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); +bool RegisterContextPOSIXProcessMonitor_arm::WriteFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); } -bool -RegisterContextPOSIXProcessMonitor_arm::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); +bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister( + const unsigned reg, RegisterValue &value) { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), + GetRegisterName(reg), GetRegisterSize(reg), + value); } -bool -RegisterContextPOSIXProcessMonitor_arm::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } +bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister( + const unsigned reg, const RegisterValue &value) { + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; } + } } + } - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), value_to_write); } -bool -RegisterContextPOSIXProcessMonitor_arm::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; - } - else - { - return ReadRegister(reg, value); - } +bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (!reg_info) + return false; - // Get pointer to m_fpr variable and set the data from it. - assert (reg_info->byte_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; - switch (reg_info->byte_size) - { - case 2: - value.SetUInt16(*(uint16_t *)src); - return true; - case 4: - value.SetUInt32(*(uint32_t *)src); - return true; - case 8: - value.SetUInt64(*(uint64_t *)src); - return true; - default: - assert(false && "Unhandled data size."); - return false; - } + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsFPR(reg)) { + if (!ReadFPR()) + return false; + } else { + return ReadRegister(reg, value); + } + + // Get pointer to m_fpr variable and set the data from it. + assert(reg_info->byte_offset < sizeof m_fpr); + uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; + switch (reg_info->byte_size) { + case 2: + value.SetUInt16(*(uint16_t *)src); + return true; + case 4: + value.SetUInt32(*(uint32_t *)src); + return true; + case 8: + value.SetUInt64(*(uint64_t *)src); + return true; + default: + assert(false && "Unhandled data size."); + return false; + } } -bool -RegisterContextPOSIXProcessMonitor_arm::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; +bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsGPR(reg)) - { - return WriteRegister(reg, value); - } - else if (IsFPR(reg)) - { - return WriteFPR(); - } + if (IsGPR(reg)) { + return WriteRegister(reg, value); + } else if (IsFPR(reg)) { + return WriteFPR(); + } - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_arm, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); - } +bool RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues( + DataBufferSP &data_sp) { + bool success = false; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR() && ReadFPR()) { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) { + ::memcpy(dst, &m_gpr_arm, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr, sizeof(m_fpr)); } - return success; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_arm, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - ::memcpy (&m_fpr, src, sizeof(m_fpr)); - - success = WriteFPR(); - } - } +bool RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues( + const DataBufferSP &data_sp) { + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + uint8_t *src = data_sp->GetBytes(); + if (src) { + ::memcpy(&m_gpr_arm, src, GetGPRSize()); + + if (WriteGPR()) { + src += GetGPRSize(); + ::memcpy(&m_fpr, src, sizeof(m_fpr)); + + success = WriteFPR(); + } } - return success; + } + return success; } -uint32_t -RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } +uint32_t RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint( + addr_t addr, size_t size, bool read, bool write) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; + + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index); + } - return LLDB_INVALID_INDEX32; + return LLDB_INVALID_INDEX32; } -bool -RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() -{ - lldb::addr_t pc; +bool RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() { + lldb::addr_t pc; - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; - return true; + return true; } -unsigned -RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_arm; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_arm && "Invalid register offset."); - return reg; +unsigned RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset( + unsigned offset) { + unsigned reg; + for (reg = 0; reg < k_num_registers_arm; reg++) { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers_arm && "Invalid register offset."); + return reg; } -bool -RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() { + return false; } -addr_t -RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; +addr_t RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress( + uint32_t hw_index) { + return LLDB_INVALID_ADDRESS; } -bool -RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex( + addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { + return false; } uint32_t -RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() -{ - return 0; +RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() { + return 0; } - diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h index 3787502a390..6aa71c24f1c 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h @@ -10,87 +10,68 @@ #ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ #define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ -#include "RegisterContextPOSIX.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" +#include "RegisterContextPOSIX.h" -class RegisterContextPOSIXProcessMonitor_arm: - public RegisterContextPOSIX_arm, - public POSIXBreakpointProtocol -{ +class RegisterContextPOSIXProcessMonitor_arm : public RegisterContextPOSIX_arm, + public POSIXBreakpointProtocol { public: - RegisterContextPOSIXProcessMonitor_arm(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIXProcessMonitor_arm( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); protected: - bool - ReadGPR(); + bool ReadGPR(); - bool - ReadFPR(); + bool ReadFPR(); - bool - WriteGPR(); + bool WriteGPR(); - bool - WriteFPR(); + bool WriteFPR(); - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + // lldb_private::RegisterContext + bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + bool WriteRegister(const unsigned reg, + const lldb_private::RegisterValue &value); - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write); - bool - ClearHardwareWatchpoint(uint32_t hw_index); + bool ClearHardwareWatchpoint(uint32_t hw_index); - bool - HardwareSingleStep(bool enable); + bool HardwareSingleStep(bool enable); - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); + // POSIXBreakpointProtocol + bool UpdateAfterBreakpoint(); - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - bool - IsWatchpointHit(uint32_t hw_index); + bool IsWatchpointHit(uint32_t hw_index); - bool - ClearWatchpointHits(); + bool ClearWatchpointHits(); - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); + lldb::addr_t GetWatchpointAddress(uint32_t hw_index); - bool - IsWatchpointVacant(uint32_t hw_index); + bool IsWatchpointVacant(uint32_t hw_index); - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, + bool write, uint32_t hw_index); - uint32_t - NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); private: - ProcessMonitor & - GetMonitor(); + ProcessMonitor &GetMonitor(); }; #endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp index a1a0cab82a1..98a213a370f 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -21,298 +21,245 @@ using namespace lldb; using namespace lldb_private; -RegisterContextPOSIXProcessMonitor_arm64::RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info) -{ +RegisterContextPOSIXProcessMonitor_arm64:: + RegisterContextPOSIXProcessMonitor_arm64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info) {} + +ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() { + lldb::ProcessSP base = CalculateProcess(); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get()); + return process->GetMonitor(); } -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() -{ - lldb::ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get()); - return process->GetMonitor(); +bool RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); } -bool -RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); +bool RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); } -bool -RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); +bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister( + const unsigned reg, lldb_private::RegisterValue &value) { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), + GetRegisterName(reg), GetRegisterSize(reg), + value); } -bool -RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const unsigned reg, - lldb_private::RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); -} - -bool -RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const unsigned reg, - const lldb_private::RegisterValue &value) -{ - unsigned reg_to_write = reg; - lldb_private::RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - lldb_private::RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const lldb_private::RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - lldb_private::Error error; - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - ::memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } +bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister( + const unsigned reg, const lldb_private::RegisterValue &value) { + unsigned reg_to_write = reg; + lldb_private::RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + lldb_private::RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const lldb_private::RegisterInfo *full_reg_info = + GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) { + lldb_private::Error error; + lldb::ByteOrder byte_order = GetByteOrder(); + uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + ::memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; } + } } + } - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), value_to_write); } -bool -RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) -{ - if (!reg_info) - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister( + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) { + if (!reg_info) + return false; - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; - } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - return ReadRegister(full_reg, value); - } + if (IsFPR(reg)) { + if (!ReadFPR()) + return false; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - // Get pointer to m_fpr variable and set the data from it. - assert (reg_info->byte_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; - switch (reg_info->byte_size) - { - case 2: - value.SetUInt16(*(uint16_t *)src); - return true; - case 4: - value.SetUInt32(*(uint32_t *)src); - return true; - case 8: - value.SetUInt64(*(uint64_t *)src); - return true; - default: - assert(false && "Unhandled data size."); - return false; + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } + return ReadRegister(full_reg, value); + } + + // Get pointer to m_fpr variable and set the data from it. + assert(reg_info->byte_offset < sizeof m_fpr); + uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; + switch (reg_info->byte_size) { + case 2: + value.SetUInt16(*(uint16_t *)src); + return true; + case 4: + value.SetUInt32(*(uint32_t *)src); + return true; + case 8: + value.SetUInt64(*(uint64_t *)src); + return true; + default: + assert(false && "Unhandled data size."); + return false; + } } -bool -RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; +bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister( + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) { + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (IsGPR(reg)) - return WriteRegister(reg, value); + if (IsGPR(reg)) + return WriteRegister(reg, value); - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new lldb_private::DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy (dst, &m_fpr, sizeof m_fpr); - } +bool RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + bool success = false; + data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR() && ReadFPR()) { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) { + ::memcpy(dst, &m_gpr_arm64, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr, sizeof m_fpr); } - return success; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_arm64, src, GetGPRSize()); - if (WriteGPR()) { - src += GetGPRSize(); - ::memcpy (&m_fpr, src, sizeof m_fpr); - success = WriteFPR(); - } - } +bool RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + uint8_t *src = data_sp->GetBytes(); + if (src) { + ::memcpy(&m_gpr_arm64, src, GetGPRSize()); + if (WriteGPR()) { + src += GetGPRSize(); + ::memcpy(&m_fpr, src, sizeof m_fpr); + success = WriteFPR(); + } } - return success; + } + return success; } -uint32_t -RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } +uint32_t RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, bool read, bool write) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; + + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index); + } - return LLDB_INVALID_INDEX32; + return LLDB_INVALID_INDEX32; } -bool -RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() -{ - if (GetPC() == LLDB_INVALID_ADDRESS) - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() { + if (GetPC() == LLDB_INVALID_ADDRESS) + return false; - return true; + return true; } -unsigned -RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_arm64; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_arm64 && "Invalid register offset."); - return reg; +unsigned RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset( + unsigned offset) { + unsigned reg; + for (reg = 0; reg < k_num_registers_arm64; reg++) { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers_arm64 && "Invalid register offset."); + return reg; } -bool -RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() { + return false; } -lldb::addr_t -RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; +lldb::addr_t RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress( + uint32_t hw_index) { + return LLDB_INVALID_ADDRESS; } -bool -RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex( + lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { + return false; } uint32_t -RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() -{ - return 0; +RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() { + return 0; } diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h index 729385c4a76..8591c83be54 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h @@ -10,87 +10,69 @@ #ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ #define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ -#include "RegisterContextPOSIX.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "RegisterContextPOSIX.h" -class RegisterContextPOSIXProcessMonitor_arm64: - public RegisterContextPOSIX_arm64, - public POSIXBreakpointProtocol -{ +class RegisterContextPOSIXProcessMonitor_arm64 + : public RegisterContextPOSIX_arm64, + public POSIXBreakpointProtocol { public: - RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIXProcessMonitor_arm64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); protected: - bool - ReadGPR(); + bool ReadGPR(); - bool - ReadFPR(); + bool ReadFPR(); - bool - WriteGPR(); + bool WriteGPR(); - bool - WriteFPR(); + bool WriteFPR(); - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + // lldb_private::RegisterContext + bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + bool WriteRegister(const unsigned reg, + const lldb_private::RegisterValue &value); - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write); - bool - ClearHardwareWatchpoint(uint32_t hw_index); + bool ClearHardwareWatchpoint(uint32_t hw_index); - bool - HardwareSingleStep(bool enable); + bool HardwareSingleStep(bool enable); - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); + // POSIXBreakpointProtocol + bool UpdateAfterBreakpoint(); - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - bool - IsWatchpointHit(uint32_t hw_index); + bool IsWatchpointHit(uint32_t hw_index); - bool - ClearWatchpointHits(); + bool ClearWatchpointHits(); - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); + lldb::addr_t GetWatchpointAddress(uint32_t hw_index); - bool - IsWatchpointVacant(uint32_t hw_index); + bool IsWatchpointVacant(uint32_t hw_index); - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, + bool write, uint32_t hw_index); - uint32_t - NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); private: - ProcessMonitor & - GetMonitor(); + ProcessMonitor &GetMonitor(); }; #endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp index eeada4b1633..f175192970e 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -21,298 +21,243 @@ using namespace lldb; #define REG_CONTEXT_SIZE (GetGPRSize()) -RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) -{ +RegisterContextPOSIXProcessMonitor_mips64:: + RegisterContextPOSIXProcessMonitor_mips64( + Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) {} + +ProcessMonitor &RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() { + ProcessSP base = CalculateProcess(); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get()); + return process->GetMonitor(); } -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get()); - return process->GetMonitor(); +bool RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() { + // XXX not yet implemented + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() -{ - // XXX not yet implemented - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() -{ - // XXX not yet implemented - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() { + // XXX not yet implemented + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); +bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister( + const unsigned reg, RegisterValue &value) { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), + GetRegisterName(reg), GetRegisterSize(reg), + value); } -bool -RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } +bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister( + const unsigned reg, const RegisterValue &value) { + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; } + } } + } - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), value_to_write); } -bool -RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (!reg_info) + return false; + + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + if (IsFPR(reg)) { + if (!ReadFPR()) + return false; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - bool success = ReadRegister(full_reg, value); + bool success = ReadRegister(full_reg, value); - if (success) - { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); + if (success) { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value + // one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + value.SetUInt64(value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (value.GetByteSize() > reg_info->byte_size) - value.SetType(reg_info); - } - return success; + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (value.GetByteSize() > reg_info->byte_size) + value.SetType(reg_info); } + return success; + } - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; +bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsGPR(reg)) - return WriteRegister(reg, value); + if (IsGPR(reg)) + return WriteRegister(reg, value); - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_mips64, GetGPRSize()); - } +bool RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues( + DataBufferSP &data_sp) { + bool success = false; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR() && ReadFPR()) { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) { + ::memcpy(dst, &m_gpr_mips64, GetGPRSize()); } - return success; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_mips64, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - } - } +bool RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues( + const DataBufferSP &data_sp) { + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + uint8_t *src = data_sp->GetBytes(); + if (src) { + ::memcpy(&m_gpr_mips64, src, GetGPRSize()); + + if (WriteGPR()) { + src += GetGPRSize(); + } } - return success; + } + return success; } -uint32_t -RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } +uint32_t RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint( + addr_t addr, size_t size, bool read, bool write) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; - return LLDB_INVALID_INDEX32; + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index); + } + + return LLDB_INVALID_INDEX32; } -bool -RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep( + bool enable) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; +bool RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() { + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; - SetPC(pc - 1); - return true; + SetPC(pc - 1); + return true; } -unsigned -RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_mips64; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_mips64 && "Invalid register offset."); - return reg; +unsigned RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset( + unsigned offset) { + unsigned reg; + for (reg = 0; reg < k_num_registers_mips64; reg++) { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers_mips64 && "Invalid register offset."); + return reg; } -bool -RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() { + return false; } -addr_t -RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; +addr_t RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress( + uint32_t hw_index) { + return LLDB_INVALID_ADDRESS; } -bool -RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex( + addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { + return false; } uint32_t -RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() -{ - return 0; +RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() { + return 0; } - diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h index e61621bec19..2f75e6058fb 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h @@ -10,87 +10,69 @@ #ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ #define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ -#include "RegisterContextPOSIX.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" +#include "RegisterContextPOSIX.h" -class RegisterContextPOSIXProcessMonitor_mips64: - public RegisterContextPOSIX_mips64, - public POSIXBreakpointProtocol -{ +class RegisterContextPOSIXProcessMonitor_mips64 + : public RegisterContextPOSIX_mips64, + public POSIXBreakpointProtocol { public: - RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIXProcessMonitor_mips64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); protected: - bool - ReadGPR(); + bool ReadGPR(); - bool - ReadFPR(); + bool ReadFPR(); - bool - WriteGPR(); + bool WriteGPR(); - bool - WriteFPR(); + bool WriteFPR(); - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + // lldb_private::RegisterContext + bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + bool WriteRegister(const unsigned reg, + const lldb_private::RegisterValue &value); - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write); - bool - ClearHardwareWatchpoint(uint32_t hw_index); + bool ClearHardwareWatchpoint(uint32_t hw_index); - bool - HardwareSingleStep(bool enable); + bool HardwareSingleStep(bool enable); - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); + // POSIXBreakpointProtocol + bool UpdateAfterBreakpoint(); - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - bool - IsWatchpointHit(uint32_t hw_index); + bool IsWatchpointHit(uint32_t hw_index); - bool - ClearWatchpointHits(); + bool ClearWatchpointHits(); - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); + lldb::addr_t GetWatchpointAddress(uint32_t hw_index); - bool - IsWatchpointVacant(uint32_t hw_index); + bool IsWatchpointVacant(uint32_t hw_index); - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, + bool write, uint32_t hw_index); - uint32_t - NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); private: - ProcessMonitor & - GetMonitor(); + ProcessMonitor &GetMonitor(); }; #endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp index 321e6ea262c..6b7155bd693 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -11,327 +11,265 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX_powerpc.h" #include "ProcessFreeBSD.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" #include "ProcessMonitor.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" +#include "RegisterContextPOSIX_powerpc.h" using namespace lldb_private; using namespace lldb; #define REG_CONTEXT_SIZE (GetGPRSize()) -RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) -{ -} +RegisterContextPOSIXProcessMonitor_powerpc:: + RegisterContextPOSIXProcessMonitor_powerpc( + Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {} -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get()); - return process->GetMonitor(); +ProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() { + ProcessSP base = CalculateProcess(); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get()); + return process->GetMonitor(); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, + sizeof(m_fpr_powerpc)); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() -{ - // XXX: Need a way to read/write process VMX registers with ptrace. - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() { + // XXX: Need a way to read/write process VMX registers with ptrace. + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, + sizeof(m_fpr_powerpc)); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() -{ - // XXX: Need a way to read/write process VMX registers with ptrace. - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() { + // XXX: Need a way to read/write process VMX registers with ptrace. + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister( + const unsigned reg, RegisterValue &value) { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), + GetRegisterName(reg), GetRegisterSize(reg), + value); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister( + const unsigned reg, const RegisterValue &value) { + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; } + } } - - ProcessMonitor &monitor = GetMonitor(); - // Account for the fact that 32-bit targets on powerpc64 really use 64-bit - // registers in ptrace, but expose here 32-bit registers with a higher - // offset. - uint64_t offset = GetRegisterOffset(reg_to_write); - offset &= ~(sizeof(uintptr_t) - 1); - return monitor.WriteRegisterValue(m_thread.GetID(), - offset, - GetRegisterName(reg_to_write), - value_to_write); + } + + ProcessMonitor &monitor = GetMonitor(); + // Account for the fact that 32-bit targets on powerpc64 really use 64-bit + // registers in ptrace, but expose here 32-bit registers with a higher + // offset. + uint64_t offset = GetRegisterOffset(reg_to_write); + offset &= ~(sizeof(uintptr_t) - 1); + return monitor.WriteRegisterValue( + m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write); } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (!reg_info) + return false; - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; - uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; - value.SetUInt64(*(uint64_t*)src); - } - else if (IsGPR(reg)) - { - bool success = ReadRegister(reg, value); - - if (success) - { - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (value.GetByteSize() > reg_info->byte_size) - value.SetType(reg_info); - } - return success; + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsFPR(reg)) { + if (!ReadFPR()) + return false; + uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + value.SetUInt64(*(uint64_t *)src); + } else if (IsGPR(reg)) { + bool success = ReadRegister(reg, value); + + if (success) { + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (value.GetByteSize() > reg_info->byte_size) + value.SetType(reg_info); } + return success; + } - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsGPR(reg)) - { - return WriteRegister(reg, value); - } - else if (IsFPR(reg)) - { - assert (reg_info->byte_offset < sizeof(m_fpr_powerpc)); - uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; - *(uint64_t *)dst = value.GetAsUInt64(); - return WriteFPR(); - } + if (IsGPR(reg)) { + return WriteRegister(reg, value); + } else if (IsFPR(reg)) { + assert(reg_info->byte_offset < sizeof(m_fpr_powerpc)); + uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + *(uint64_t *)dst = value.GetAsUInt64(); + return WriteFPR(); + } - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_powerpc, GetGPRSize()); - dst += GetGPRSize(); - } +bool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues( + DataBufferSP &data_sp) { + bool success = false; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR() && ReadFPR()) { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) { + ::memcpy(dst, &m_gpr_powerpc, GetGPRSize()); + dst += GetGPRSize(); } - return success; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_powerpc, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); - - success = WriteFPR(); - } - } +bool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues( + const DataBufferSP &data_sp) { + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + uint8_t *src = data_sp->GetBytes(); + if (src) { + ::memcpy(&m_gpr_powerpc, src, GetGPRSize()); + + if (WriteGPR()) { + src += GetGPRSize(); + ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); + + success = WriteFPR(); + } } - return success; + } + return success; } -uint32_t -RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } +uint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint( + addr_t addr, size_t size, bool read, bool write) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; - return LLDB_INVALID_INDEX32; + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index); + } + + return LLDB_INVALID_INDEX32; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep( + bool enable) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() -{ - lldb::addr_t pc; +bool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() { + lldb::addr_t pc; - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; - return true; + return true; } -unsigned -RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_powerpc; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_powerpc && "Invalid register offset."); - return reg; +unsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset( + unsigned offset) { + unsigned reg; + for (reg = 0; reg < k_num_registers_powerpc; reg++) { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers_powerpc && "Invalid register offset."); + return reg; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() { + return false; } -addr_t -RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; +addr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress( + uint32_t hw_index) { + return LLDB_INVALID_ADDRESS; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant( + uint32_t hw_index) { + return false; } -bool -RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; +bool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex( + addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { + return false; } uint32_t -RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() -{ - return 0; +RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() { + return 0; } - diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h index ff1d0f36171..188ddea7d47 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -1,4 +1,5 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,96 +11,75 @@ #ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ #define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ -#include "RegisterContextPOSIX.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" +#include "RegisterContextPOSIX.h" -class RegisterContextPOSIXProcessMonitor_powerpc: - public RegisterContextPOSIX_powerpc, - public POSIXBreakpointProtocol -{ +class RegisterContextPOSIXProcessMonitor_powerpc + : public RegisterContextPOSIX_powerpc, + public POSIXBreakpointProtocol { public: - RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIXProcessMonitor_powerpc( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); protected: - bool - IsVMX(); + bool IsVMX(); - bool - ReadGPR(); + bool ReadGPR(); - bool - ReadFPR(); + bool ReadFPR(); - bool - ReadVMX(); + bool ReadVMX(); - bool - WriteGPR(); + bool WriteGPR(); - bool - WriteFPR(); + bool WriteFPR(); - bool - WriteVMX(); + bool WriteVMX(); - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + // lldb_private::RegisterContext + bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + bool WriteRegister(const unsigned reg, + const lldb_private::RegisterValue &value); - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write); - bool - ClearHardwareWatchpoint(uint32_t hw_index); + bool ClearHardwareWatchpoint(uint32_t hw_index); - bool - HardwareSingleStep(bool enable); + bool HardwareSingleStep(bool enable); - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); + // POSIXBreakpointProtocol + bool UpdateAfterBreakpoint(); - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - bool - IsWatchpointHit(uint32_t hw_index); + bool IsWatchpointHit(uint32_t hw_index); - bool - ClearWatchpointHits(); + bool ClearWatchpointHits(); - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); + lldb::addr_t GetWatchpointAddress(uint32_t hw_index); - bool - IsWatchpointVacant(uint32_t hw_index); + bool IsWatchpointVacant(uint32_t hw_index); - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, + bool write, uint32_t hw_index); - uint32_t - NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); private: - ProcessMonitor & - GetMonitor(); + ProcessMonitor &GetMonitor(); }; #endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 31b9e7a38b2..48d86504871 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -12,662 +12,603 @@ #include "lldb/Target/Thread.h" #include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" -#include "RegisterContextPOSIXProcessMonitor_x86.h" #include "Plugins/Process/FreeBSD/ProcessMonitor.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" using namespace lldb_private; using namespace lldb; // Support ptrace extensions even when compiled without required kernel support #ifndef NT_X86_XSTATE - #define NT_X86_XSTATE 0x202 +#define NT_X86_XSTATE 0x202 #endif #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR)) -static uint32_t -size_and_rw_bits(size_t size, bool read, bool write) -{ - uint32_t rw; - - if (read) - rw = 0x3; // READ or READ/WRITE - else if (write) - rw = 0x1; // WRITE - else - assert(0 && "read and write cannot both be false"); - - switch (size) - { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - default: - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - return 0; // Unreachable. Just to silence compiler. - } +static uint32_t size_and_rw_bits(size_t size, bool read, bool write) { + uint32_t rw; + + if (read) + rw = 0x3; // READ or READ/WRITE + else if (write) + rw = 0x1; // WRITE + else + assert(0 && "read and write cannot both be false"); + + switch (size) { + case 1: + return rw; + case 2: + return (0x1 << 2) | rw; + case 4: + return (0x3 << 2) | rw; + case 8: + return (0x2 << 2) | rw; + default: + assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); + return 0; // Unreachable. Just to silence compiler. + } } -RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) -{ - // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' - const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); - m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; +RegisterContextPOSIXProcessMonitor_x86_64:: + RegisterContextPOSIXProcessMonitor_x86_64( + Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) { + // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' + const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); + m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; } -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get()); - return process->GetMonitor(); +ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() { + ProcessSP base = CalculateProcess(); + ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get()); + return process->GetMonitor(); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - if (GetFPRType() == eFXSAVE) - return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); +bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() { + ProcessMonitor &monitor = GetMonitor(); + if (GetFPRType() == eFXSAVE) + return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, + sizeof(m_fpr.xstate.fxsave)); - if (GetFPRType() == eXSAVE) - return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); - return false; + if (GetFPRType() == eXSAVE) + return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, + sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + return false; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); +bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - if (GetFPRType() == eFXSAVE) - return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); +bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() { + ProcessMonitor &monitor = GetMonitor(); + if (GetFPRType() == eFXSAVE) + return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, + sizeof(m_fpr.xstate.fxsave)); - if (GetFPRType() == eXSAVE) - return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); - return false; + if (GetFPRType() == eXSAVE) + return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, + sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + return false; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); +bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( + const unsigned reg, RegisterValue &value) { + ProcessMonitor &monitor = GetMonitor(); #if defined(__FreeBSD__) - if (reg >= m_reg_info.first_dr) - return monitor.ReadDebugRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); + if (reg >= m_reg_info.first_dr) + return monitor.ReadDebugRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg), + GetRegisterSize(reg), value); #endif - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); + return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), + GetRegisterName(reg), GetRegisterSize(reg), + value); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } +bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( + const unsigned reg, const RegisterValue &value) { + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; } + } } + } - ProcessMonitor &monitor = GetMonitor(); + ProcessMonitor &monitor = GetMonitor(); #if defined(__FreeBSD__) - if (reg >= m_reg_info.first_dr) - return monitor.WriteDebugRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); + if (reg >= m_reg_info.first_dr) + return monitor.WriteDebugRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), value_to_write); #endif - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); + return monitor.WriteRegisterValue( + m_thread.GetID(), GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), value_to_write); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; +bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (!reg_info) + return false; - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsFPR(reg, GetFPRType())) - { - if (!ReadFPR()) - return false; + if (IsFPR(reg, GetFPRType())) { + if (!ReadFPR()) + return false; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - bool success = ReadRegister(full_reg, value); + bool success = ReadRegister(full_reg, value); - if (success) - { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); + if (success) { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value + // one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + value.SetUInt64(value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (value.GetByteSize() > reg_info->byte_size) - value.SetType(reg_info); - } - return success; + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (value.GetByteSize() > reg_info->byte_size) + value.SetType(reg_info); } + return success; + } + + if (reg_info->encoding == eEncodingVector) { + ByteOrder byte_order = GetByteOrder(); + + if (byte_order != ByteOrder::eByteOrderInvalid) { + if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) + value.SetBytes( + m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) + value.SetBytes( + m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) + value.SetBytes( + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { + // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes + if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) + value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + reg_info->byte_size, byte_order); + else + return false; + } + return value.GetType() == RegisterValue::eTypeBytes; + } + return false; + } + + // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + // Byte offsets of all registers are calculated wrt 'UserArea' structure. + // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} + // and stores them in 'm_fpr' (of type FPR structure). To extract values of + // fpu + // registers, m_fpr should be read at byte offsets calculated wrt to FPR + // structure. + + // Since, FPR structure is also one of the member of UserArea structure. + // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - + // byte_offset(fctrl wrt UserArea) + assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); + uint8_t *src = + (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; + switch (reg_info->byte_size) { + case 1: + value.SetUInt8(*(uint8_t *)src); + return true; + case 2: + value.SetUInt16(*(uint16_t *)src); + return true; + case 4: + value.SetUInt32(*(uint32_t *)src); + return true; + case 8: + value.SetUInt64(*(uint64_t *)src); + return true; + default: + assert(false && "Unhandled data size."); + return false; + } +} - if (reg_info->encoding == eEncodingVector) - { - ByteOrder byte_order = GetByteOrder(); - - if (byte_order != ByteOrder::eByteOrderInvalid) - { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) - { - // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes - if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) - value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order); - else - return false; - } - return value.GetType() == RegisterValue::eTypeBytes; - } +bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsGPR(reg)) + return WriteRegister(reg, value); + + if (IsFPR(reg, GetFPRType())) { + if (reg_info->encoding == eEncodingVector) { + if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) + ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, + value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) + ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { + if (GetFPRType() != eXSAVE) + return false; // the target processor does not support AVX + + // Store ymm register content, and split into the register halves in + // xmm.bytes and ymmh.bytes + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + value.GetBytes(), value.GetByteSize()); + if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) + return false; + } + } else { + // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + // Byte offsets of all registers are calculated wrt 'UserArea' structure. + // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only + // fpu + // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should + // be written in m_fpr at byte offsets calculated wrt FPR structure. + + // Since, FPR structure is also one of the member of UserArea structure. + // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - + // byte_offset(fctrl wrt UserArea) + assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < + sizeof(m_fpr)); + uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - + m_fctrl_offset_in_userarea; + switch (reg_info->byte_size) { + case 1: + *(uint8_t *)dst = value.GetAsUInt8(); + break; + case 2: + *(uint16_t *)dst = value.GetAsUInt16(); + break; + case 4: + *(uint32_t *)dst = value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); return false; + } } - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} - // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu - // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) - assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) - { - case 1: - value.SetUInt8(*(uint8_t *)src); - return true; - case 2: - value.SetUInt16(*(uint16_t *)src); - return true; - case 4: - value.SetUInt32(*(uint32_t *)src); - return true; - case 8: - value.SetUInt64(*(uint64_t *)src); - return true; - default: - assert(false && "Unhandled data size."); - return false; + if (WriteFPR()) { + if (IsAVX(reg)) + return CopyYMMtoXSTATE(reg, GetByteOrder()); + return true; } + } + return false; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsGPR(reg)) - return WriteRegister(reg, value); - - if (IsFPR(reg, GetFPRType())) - { - if (reg_info->encoding == eEncodingVector) - { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - ::memcpy (m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) - { - if (GetFPRType() != eXSAVE) - return false; // the target processor does not support AVX - - // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes - ::memcpy (m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, value.GetBytes(), value.GetByteSize()); - if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) - return false; - } - } - else - { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu - // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should - // be written in m_fpr at byte offsets calculated wrt FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) - assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) - { - case 1: - *(uint8_t *)dst = value.GetAsUInt8(); - break; - case 2: - *(uint16_t *)dst = value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return false; - } - } +bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues( + DataBufferSP &data_sp) { + bool success = false; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR() && ReadFPR()) { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) { + ::memcpy(dst, &m_gpr_x86_64, GetGPRSize()); + dst += GetGPRSize(); + if (GetFPRType() == eFXSAVE) + ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + } - if (WriteFPR()) - { - if (IsAVX(reg)) - return CopyYMMtoXSTATE(reg, GetByteOrder()); - return true; - } + if (GetFPRType() == eXSAVE) { + ByteOrder byte_order = GetByteOrder(); + + // Assemble the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; + success && reg <= m_reg_info.last_ymm; ++reg) + success = CopyXSTATEtoYMM(reg, byte_order); + + if (success) { + // Copy the extended register state including the assembled ymm + // registers. + ::memcpy(dst, &m_fpr, sizeof(m_fpr)); + } } - return false; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_x86_64, GetGPRSize()); - dst += GetGPRSize(); - if (GetFPRType() == eFXSAVE) - ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); - } - +bool RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues( + const DataBufferSP &data_sp) { + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + uint8_t *src = data_sp->GetBytes(); + if (src) { + ::memcpy(&m_gpr_x86_64, src, GetGPRSize()); + + if (WriteGPR()) { + src += GetGPRSize(); + if (GetFPRType() == eFXSAVE) + ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); if (GetFPRType() == eXSAVE) - { - ByteOrder byte_order = GetByteOrder(); + ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); - // Assemble the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg) - success = CopyXSTATEtoYMM(reg, byte_order); + success = WriteFPR(); + if (success) { + if (GetFPRType() == eXSAVE) { + ByteOrder byte_order = GetByteOrder(); - if (success) - { - // Copy the extended register state including the assembled ymm registers. - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); - } + // Parse the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; + success && reg <= m_reg_info.last_ymm; ++reg) + success = CopyYMMtoXSTATE(reg, byte_order); + } } + } } - return success; + } + return success; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_x86_64, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - if (GetFPRType() == eFXSAVE) - ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); - if (GetFPRType() == eXSAVE) - ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); - - success = WriteFPR(); - if (success) - { - if (GetFPRType() == eXSAVE) - { - ByteOrder byte_order = GetByteOrder(); - - // Parse the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg) - success = CopyYMMtoXSTATE(reg, byte_order); - } - } - } - } - } - return success; -} +uint32_t RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint( + addr_t addr, size_t size, bool read, bool write) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; -uint32_t -RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index); + } - return LLDB_INVALID_INDEX32; + return LLDB_INVALID_INDEX32; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(uint32_t hw_index) -{ - if (hw_index < NumSupportedHardwareWatchpoints()) - { - RegisterValue current_dr7_bits; +bool RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint( + uint32_t hw_index) { + if (hw_index < NumSupportedHardwareWatchpoints()) { + RegisterValue current_dr7_bits; - if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) - { - uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index)); + if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) { + uint64_t new_dr7_bits = + current_dr7_bits.GetAsUInt64() & ~(3 << (2 * hw_index)); - if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) - return true; - } + if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) + return true; } + } - return false; + return false; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; +bool RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep( + bool enable) { + enum { TRACE_BIT = 0x100 }; + uint64_t rflags; - if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (rflags & TRACE_BIT) - return true; + if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL) + return false; - rflags |= TRACE_BIT; - } - else - { - if (!(rflags & TRACE_BIT)) - return false; + if (enable) { + if (rflags & TRACE_BIT) + return true; - rflags &= ~TRACE_BIT; - } + rflags |= TRACE_BIT; + } else { + if (!(rflags & TRACE_BIT)) + return false; + + rflags &= ~TRACE_BIT; + } - return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags); + return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags); } -bool -RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; +bool RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() { + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; - SetPC(pc - 1); - return true; + SetPC(pc - 1); + return true; } -unsigned -RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < m_reg_info.num_registers; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return reg; +unsigned RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset( + unsigned offset) { + unsigned reg; + for (reg = 0; reg < m_reg_info.num_registers; reg++) { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return reg; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(uint32_t hw_index) -{ - bool is_hit = false; - - if (m_watchpoints_initialized == false) - { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } - - if (hw_index < NumSupportedHardwareWatchpoints()) - { - RegisterValue value; - - if (ReadRegister(m_reg_info.first_dr + 6, value)) - { - uint64_t val = value.GetAsUInt64(); - is_hit = val & (1 << hw_index); - } - } - - return is_hit; +bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit( + uint32_t hw_index) { + bool is_hit = false; + + if (m_watchpoints_initialized == false) { + // Reset the debug status and debug control registers + RegisterValue zero_bits = RegisterValue(uint64_t(0)); + if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || + !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) + assert(false && "Could not initialize watchpoint registers"); + m_watchpoints_initialized = true; + } + + if (hw_index < NumSupportedHardwareWatchpoints()) { + RegisterValue value; + + if (ReadRegister(m_reg_info.first_dr + 6, value)) { + uint64_t val = value.GetAsUInt64(); + is_hit = val & (1 << hw_index); + } + } + + return is_hit; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() -{ - return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0)); +bool RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() { + return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0)); } -addr_t -RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index) -{ - addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; +addr_t RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress( + uint32_t hw_index) { + addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; - if (hw_index < NumSupportedHardwareWatchpoints()) - { - if (!IsWatchpointVacant(hw_index)) - { - RegisterValue value; + if (hw_index < NumSupportedHardwareWatchpoints()) { + if (!IsWatchpointVacant(hw_index)) { + RegisterValue value; - if (ReadRegister(m_reg_info.first_dr + hw_index, value)) - wp_monitor_addr = value.GetAsUInt64(); - } + if (ReadRegister(m_reg_info.first_dr + hw_index, value)) + wp_monitor_addr = value.GetAsUInt64(); } + } - return wp_monitor_addr; + return wp_monitor_addr; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index) -{ - bool is_vacant = false; - RegisterValue value; +bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant( + uint32_t hw_index) { + bool is_vacant = false; + RegisterValue value; - assert(hw_index < NumSupportedHardwareWatchpoints()); + assert(hw_index < NumSupportedHardwareWatchpoints()); - if (m_watchpoints_initialized == false) - { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } + if (m_watchpoints_initialized == false) { + // Reset the debug status and debug control registers + RegisterValue zero_bits = RegisterValue(uint64_t(0)); + if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || + !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) + assert(false && "Could not initialize watchpoint registers"); + m_watchpoints_initialized = true; + } - if (ReadRegister(m_reg_info.first_dr + 7, value)) - { - uint64_t val = value.GetAsUInt64(); - is_vacant = (val & (3 << 2*hw_index)) == 0; - } + if (ReadRegister(m_reg_info.first_dr + 7, value)) { + uint64_t val = value.GetAsUInt64(); + is_vacant = (val & (3 << 2 * hw_index)) == 0; + } - return is_vacant; + return is_vacant; } -bool -RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); +bool RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex( + addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints) - return false; + if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints) + return false; - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return false; + if (!(size == 1 || size == 2 || size == 4 || size == 8)) + return false; - if (read == false && write == false) - return false; + if (read == false && write == false) + return false; - if (!IsWatchpointVacant(hw_index)) - return false; + if (!IsWatchpointVacant(hw_index)) + return false; - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/global enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, - // 0b10: io read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - if (hw_index < num_hw_watchpoints) - { - RegisterValue current_dr7_bits; - - if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) - { - uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() | - (1 << (2*hw_index) | - size_and_rw_bits(size, read, write) << - (16+4*hw_index)); - - if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) && - WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) - return true; - } + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/global enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, + // 0b10: io read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + if (hw_index < num_hw_watchpoints) { + RegisterValue current_dr7_bits; + + if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) { + uint64_t new_dr7_bits = + current_dr7_bits.GetAsUInt64() | + (1 << (2 * hw_index) | + size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); + + if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) && + WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) + return true; } + } - return false; + return false; } uint32_t -RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() -{ - // Available debug address registers: dr0, dr1, dr2, dr3 - return 4; +RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3 + return 4; } - diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h index f55d917ee75..57e2d00e668 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h @@ -10,88 +10,71 @@ #ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ #define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ -#include "RegisterContextPOSIX.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "RegisterContextPOSIX.h" -class RegisterContextPOSIXProcessMonitor_x86_64: - public RegisterContextPOSIX_x86, - public POSIXBreakpointProtocol -{ +class RegisterContextPOSIXProcessMonitor_x86_64 + : public RegisterContextPOSIX_x86, + public POSIXBreakpointProtocol { public: - RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIXProcessMonitor_x86_64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); protected: - bool - ReadGPR(); + bool ReadGPR(); - bool - ReadFPR(); + bool ReadFPR(); - bool - WriteGPR(); + bool WriteGPR(); - bool - WriteFPR(); + bool WriteFPR(); - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + // lldb_private::RegisterContext + bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + bool WriteRegister(const unsigned reg, + const lldb_private::RegisterValue &value); - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write); - bool - ClearHardwareWatchpoint(uint32_t hw_index); + bool ClearHardwareWatchpoint(uint32_t hw_index); - bool - HardwareSingleStep(bool enable); + bool HardwareSingleStep(bool enable); - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); + // POSIXBreakpointProtocol + bool UpdateAfterBreakpoint(); - unsigned - GetRegisterIndexFromOffset(unsigned offset); + unsigned GetRegisterIndexFromOffset(unsigned offset); - bool - IsWatchpointHit(uint32_t hw_index); + bool IsWatchpointHit(uint32_t hw_index); - bool - ClearWatchpointHits(); + bool ClearWatchpointHits(); - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); + lldb::addr_t GetWatchpointAddress(uint32_t hw_index); - bool - IsWatchpointVacant(uint32_t hw_index); + bool IsWatchpointVacant(uint32_t hw_index); - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, + bool write, uint32_t hw_index); - uint32_t - NumSupportedHardwareWatchpoints(); + uint32_t NumSupportedHardwareWatchpoints(); private: - ProcessMonitor & - GetMonitor(); - uint32_t m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure + ProcessMonitor &GetMonitor(); + uint32_t + m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure }; #endif diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 4af5b6d1da9..2510d27dc3b 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -11,8 +11,8 @@ // C Includes #include <errno.h> -#include <string.h> #include <stdint.h> +#include <string.h> #include <unistd.h> // C++ Includes @@ -42,12 +42,13 @@ #include "lldb/Utility/PseudoTerminal.h" #include "lldb/Utility/StringExtractor.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "NativeThreadLinux.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "ProcFileReader.h" #include "Procfs.h" -// System includes - They have to be included after framework includes because they define some +// System includes - They have to be included after framework includes because +// they define some // macros which collide with variable names in other modules #include <linux/unistd.h> #include <sys/socket.h> @@ -63,7 +64,7 @@ // Support hardware breakpoints in case it has not been defined #ifndef TRAP_HWBKPT - #define TRAP_HWBKPT 4 +#define TRAP_HWBKPT 4 #endif using namespace lldb; @@ -73,1911 +74,1907 @@ using namespace llvm; // Private bits we only need internally. -static bool ProcessVmReadvSupported() -{ - static bool is_supported; - static std::once_flag flag; - - std::call_once(flag, [] { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - uint32_t source = 0x47424742; - uint32_t dest = 0; - - struct iovec local, remote; - remote.iov_base = &source; - local.iov_base = &dest; - remote.iov_len = local.iov_len = sizeof source; - - // We shall try if cross-process-memory reads work by attempting to read a value from our own process. - ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); - is_supported = (res == sizeof(source) && source == dest); - if (log) - { - if (is_supported) - log->Printf("%s: Detected kernel support for process_vm_readv syscall. Fast memory reads enabled.", - __FUNCTION__); - else - log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast memory reads disabled.", - __FUNCTION__, strerror(errno)); - } - }); +static bool ProcessVmReadvSupported() { + static bool is_supported; + static std::once_flag flag; - return is_supported; -} - -namespace -{ -void -MaybeLogLaunchInfo(const ProcessLaunchInfo &info) -{ + std::call_once(flag, [] { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!log) - return; - - if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) - log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); - else - log->Printf("%s leaving STDIN as is", __FUNCTION__); - if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) - log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); - else - log->Printf("%s leaving STDOUT as is", __FUNCTION__); + uint32_t source = 0x47424742; + uint32_t dest = 0; - if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) - log->Printf("%s setting STDERR to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); - else - log->Printf("%s leaving STDERR as is", __FUNCTION__); - - int i = 0; - for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i) - log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); -} + struct iovec local, remote; + remote.iov_base = &source; + local.iov_base = &dest; + remote.iov_len = local.iov_len = sizeof source; -void -DisplayBytes(StreamString &s, void *bytes, uint32_t count) -{ - uint8_t *ptr = (uint8_t *)bytes; - const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count); - for (uint32_t i = 0; i < loop_count; i++) - { - s.Printf("[%x]", *ptr); - ptr++; + // We shall try if cross-process-memory reads work by attempting to read a + // value from our own process. + ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); + is_supported = (res == sizeof(source) && source == dest); + if (log) { + if (is_supported) + log->Printf("%s: Detected kernel support for process_vm_readv syscall. " + "Fast memory reads enabled.", + __FUNCTION__); + else + log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast " + "memory reads disabled.", + __FUNCTION__, strerror(errno)); } -} + }); - void - PtraceDisplayBytes(int &req, void *data, size_t data_size) - { - StreamString buf; - Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( - POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); - - if (verbose_log) - { - switch(req) - { - case PTRACE_POKETEXT: - { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); - break; - } - case PTRACE_POKEDATA: - { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); - break; - } - case PTRACE_POKEUSER: - { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); - break; - } - case PTRACE_SETREGS: - { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); - break; - } - case PTRACE_SETFPREGS: - { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); - break; - } - case PTRACE_SETSIGINFO: - { - DisplayBytes(buf, data, sizeof(siginfo_t)); - verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); - break; - } - case PTRACE_SETREGSET: - { - // Extract iov_base from data, which is a pointer to the struct IOVEC - DisplayBytes(buf, *(void **)data, data_size); - verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); - break; - } - default: - { - } - } - } - } + return is_supported; +} - static constexpr unsigned k_ptrace_word_size = sizeof(void*); - static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size"); +namespace { +void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (!log) + return; + + if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) + log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, + action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDIN as is", __FUNCTION__); + + if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) + log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, + action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDOUT as is", __FUNCTION__); + + if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) + log->Printf("%s setting STDERR to '%s'", __FUNCTION__, + action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDERR as is", __FUNCTION__); + + int i = 0; + for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; + ++args, ++i) + log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, + *args ? *args : "nullptr"); +} + +void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { + uint8_t *ptr = (uint8_t *)bytes; + const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count); + for (uint32_t i = 0; i < loop_count; i++) { + s.Printf("[%x]", *ptr); + ptr++; + } +} + +void PtraceDisplayBytes(int &req, void *data, size_t data_size) { + StreamString buf; + Log *verbose_log(ProcessPOSIXLog::GetLogIfAllCategoriesSet( + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); + + if (verbose_log) { + switch (req) { + case PTRACE_POKETEXT: { + DisplayBytes(buf, &data, 8); + verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); + break; + } + case PTRACE_POKEDATA: { + DisplayBytes(buf, &data, 8); + verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); + break; + } + case PTRACE_POKEUSER: { + DisplayBytes(buf, &data, 8); + verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); + break; + } + case PTRACE_SETREGS: { + DisplayBytes(buf, data, data_size); + verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); + break; + } + case PTRACE_SETFPREGS: { + DisplayBytes(buf, data, data_size); + verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); + break; + } + case PTRACE_SETSIGINFO: { + DisplayBytes(buf, data, sizeof(siginfo_t)); + verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); + break; + } + case PTRACE_SETREGSET: { + // Extract iov_base from data, which is a pointer to the struct IOVEC + DisplayBytes(buf, *(void **)data, data_size); + verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); + break; + } + default: {} + } + } +} + +static constexpr unsigned k_ptrace_word_size = sizeof(void *); +static_assert(sizeof(long) >= k_ptrace_word_size, + "Size of long must be larger than ptrace word size"); } // end of anonymous namespace // Simple helper function to ensure flags are enabled on the given file // descriptor. -static Error -EnsureFDFlags(int fd, int flags) -{ - Error error; +static Error EnsureFDFlags(int fd, int flags) { + Error error; - int status = fcntl(fd, F_GETFL); - if (status == -1) - { - error.SetErrorToErrno(); - return error; - } - - if (fcntl(fd, F_SETFL, status | flags) == -1) - { - error.SetErrorToErrno(); - return error; - } + int status = fcntl(fd, F_GETFL); + if (status == -1) { + error.SetErrorToErrno(); + return error; + } + if (fcntl(fd, F_SETFL, status | flags) == -1) { + error.SetErrorToErrno(); return error; + } + + return error; } // ----------------------------------------------------------------------------- // Public Static Methods // ----------------------------------------------------------------------------- -Error -NativeProcessProtocol::Launch ( +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; - } + 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; + } - // Create the NativeProcessLinux in launch mode. - native_process_sp.reset (new NativeProcessLinux ()); + // Create the NativeProcessLinux in launch mode. + native_process_sp.reset(new NativeProcessLinux()); - if (!native_process_sp->RegisterNativeDelegate (native_delegate)) - { - native_process_sp.reset (); - error.SetErrorStringWithFormat ("failed to register the native delegate"); - return error; - } + if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { + native_process_sp.reset(); + error.SetErrorStringWithFormat("failed to register the native delegate"); + return error; + } - error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp)->LaunchInferior(mainloop, launch_info); + error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp) + ->LaunchInferior(mainloop, launch_info); - if (error.Fail ()) - { - native_process_sp.reset (); - if (log) - log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ()); - return error; - } + if (error.Fail()) { + native_process_sp.reset(); + if (log) + log->Printf("NativeProcessLinux::%s failed to launch process: %s", + __FUNCTION__, error.AsCString()); + return error; + } - launch_info.SetProcessID (native_process_sp->GetID ()); + launch_info.SetProcessID(native_process_sp->GetID()); - return error; + 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)); - if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE)) - log->Printf ("NativeProcessLinux::%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; +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->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid); - std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ()); + // Retrieve the architecture for the running process. + ArchSpec process_arch; + Error error = ResolveProcessArchitecture(pid, process_arch); + if (!error.Success()) + return error; - if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate)) - { - error.SetErrorStringWithFormat ("failed to register the native delegate"); - return error; - } + std::shared_ptr<NativeProcessLinux> native_process_linux_sp( + new NativeProcessLinux()); - native_process_linux_sp->AttachToInferior (mainloop, pid, error); - if (!error.Success ()) - return error; + if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) { + error.SetErrorStringWithFormat("failed to register the native delegate"); + return error; + } - native_process_sp = native_process_linux_sp; + native_process_linux_sp->AttachToInferior(mainloop, pid, error); + if (!error.Success()) return error; + + native_process_sp = native_process_linux_sp; + return error; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessLinux::NativeProcessLinux () : - NativeProcessProtocol (LLDB_INVALID_PROCESS_ID), - m_arch (), - m_supports_mem_region (eLazyBoolCalculate), - m_mem_region_cache (), - m_pending_notification_tid(LLDB_INVALID_THREAD_ID) -{ -} - -void -NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid); - - m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, - [this] (MainLoopBase &) { SigchldHandler(); }, error); - if (! m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); - - m_pid = pid; - SetState(eStateAttaching); +NativeProcessLinux::NativeProcessLinux() + : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), + m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(), + m_pending_notification_tid(LLDB_INVALID_THREAD_ID) {} + +void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, + Error &error) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, + pid); + + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); + if (!m_sigchld_handle) + return; + + error = ResolveProcessArchitecture(pid, m_arch); + if (!error.Success()) + return; + + // Set the architecture to the exe architecture. + if (log) + log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 + ") detected architecture %s", + __FUNCTION__, pid, m_arch.GetArchitectureName()); + + m_pid = pid; + SetState(eStateAttaching); + + Attach(pid, error); +} + +Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, + ProcessLaunchInfo &launch_info) { + Error error; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); + if (!m_sigchld_handle) + return error; - Attach(pid, error); -} + SetState(eStateLaunching); -Error -NativeProcessLinux::LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info) -{ - Error error; - m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; + MaybeLogLaunchInfo(launch_info); - SetState(eStateLaunching); + ::pid_t pid = + ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId(); + if (error.Fail()) + return error; - MaybeLogLaunchInfo(launch_info); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - ::pid_t pid = ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId(); - if (error.Fail()) - return error; + // Wait for the child process to trap on its call to execve. + ::pid_t wpid; + int status; + if ((wpid = waitpid(pid, &status, 0)) < 0) { + error.SetErrorToErrno(); + if (log) + log->Printf("NativeProcessLinux::%s waitpid for inferior failed with %s", + __FUNCTION__, error.AsCString()); - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + // Mark the inferior as invalid. + // FIXME this could really use a new state - eStateLaunchFailure. For now, + // using eStateInvalid. + SetState(StateType::eStateInvalid); - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) - { - error.SetErrorToErrno(); - if (log) - log->Printf ("NativeProcessLinux::%s waitpid for inferior failed with %s", - __FUNCTION__, error.AsCString ()); + return error; + } + assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && + "Could not sync with inferior process."); - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. - SetState (StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast< ::pid_t> (pid)) && - "Could not sync with inferior process."); + if (log) + log->Printf("NativeProcessLinux::%s inferior started, now in stopped state", + __FUNCTION__); + error = SetDefaultPtraceOpts(pid); + if (error.Fail()) { if (log) - log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__); + log->Printf("NativeProcessLinux::%s inferior failed to set default " + "ptrace options: %s", + __FUNCTION__, error.AsCString()); - error = SetDefaultPtraceOpts(pid); - if (error.Fail()) - { - if (log) - log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s", - __FUNCTION__, error.AsCString ()); + // Mark the inferior as invalid. + // FIXME this could really use a new state - eStateLaunchFailure. For now, + // using eStateInvalid. + SetState(StateType::eStateInvalid); - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. - SetState (StateType::eStateInvalid); + return error; + } + + // Release the master terminal descriptor and pass it off to the + // NativeProcessLinux instance. Similarly stash the inferior pid. + m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); + m_pid = pid; + launch_info.SetProcessID(pid); + + if (m_terminal_fd != -1) { + error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + if (error.Fail()) { + if (log) + log->Printf("NativeProcessLinux::%s inferior EnsureFDFlags failed for " + "ensuring terminal O_NONBLOCK setting: %s", + __FUNCTION__, error.AsCString()); - return error; + // Mark the inferior as invalid. + // FIXME this could really use a new state - eStateLaunchFailure. For + // now, using eStateInvalid. + SetState(StateType::eStateInvalid); + + return error; } + } - // Release the master terminal descriptor and pass it off to the - // NativeProcessLinux instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); + if (log) + log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, + uint64_t(pid)); - if (m_terminal_fd != -1) - { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) - { - if (log) - log->Printf( - "NativeProcessLinux::%s inferior EnsureFDFlags failed for ensuring terminal O_NONBLOCK setting: %s", - __FUNCTION__, error.AsCString()); + ResolveProcessArchitecture(m_pid, m_arch); + NativeThreadLinuxSP thread_sp = AddThread(pid); + assert(thread_sp && "AddThread() returned a nullptr thread"); + thread_sp->SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(*thread_sp); - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. - SetState(StateType::eStateInvalid); + // Let our process instance know the thread has stopped. + SetCurrentThreadID(thread_sp->GetID()); + SetState(StateType::eStateStopped); - return error; + if (log) { + if (error.Success()) + log->Printf("NativeProcessLinux::%s inferior launching succeeded", + __FUNCTION__); + else + log->Printf("NativeProcessLinux::%s inferior launching failed: %s", + __FUNCTION__, error.AsCString()); + } + return error; +} + +::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Use a map to keep track of the threads which we have attached/need to + // attach. + Host::TidMap tids_to_attach; + if (pid <= 1) { + error.SetErrorToGenericError(); + error.SetErrorString("Attaching to process 1 is not allowed."); + return -1; + } + + while (Host::FindProcessThreads(pid, tids_to_attach)) { + for (Host::TidMap::iterator it = tids_to_attach.begin(); + it != tids_to_attach.end();) { + if (it->second == false) { + lldb::tid_t tid = it->first; + + // Attach to the requested process. + // An attach will cause the thread to stop with a SIGSTOP. + error = PtraceWrapper(PTRACE_ATTACH, tid); + if (error.Fail()) { + // No such thread. The thread may have exited. + // More error handling may be needed. + if (error.GetError() == ESRCH) { + it = tids_to_attach.erase(it); + continue; + } else + return -1; } - } - if (log) - log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, uint64_t(pid)); + int status; + // Need to use __WALL otherwise we receive an error with errno=ECHLD + // At this point we should have a thread stopped if waitpid succeeds. + if ((status = waitpid(tid, NULL, __WALL)) < 0) { + // No such thread. The thread may have exited. + // More error handling may be needed. + if (errno == ESRCH) { + it = tids_to_attach.erase(it); + continue; + } else { + error.SetErrorToErrno(); + return -1; + } + } - ResolveProcessArchitecture(m_pid, m_arch); - NativeThreadLinuxSP thread_sp = AddThread(pid); - assert (thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); + error = SetDefaultPtraceOpts(tid); + if (error.Fail()) + return -1; - // Let our process instance know the thread has stopped. - SetCurrentThreadID (thread_sp->GetID ()); - SetState (StateType::eStateStopped); + if (log) + log->Printf("NativeProcessLinux::%s() adding tid = %" PRIu64, + __FUNCTION__, tid); - if (log) - { - if (error.Success ()) - log->Printf("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); - else - log->Printf("NativeProcessLinux::%s inferior launching failed: %s", __FUNCTION__, error.AsCString()); - } - return error; -} + it->second = true; -::pid_t -NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + // Create the thread, mark it as stopped. + NativeThreadLinuxSP thread_sp(AddThread(static_cast<lldb::tid_t>(tid))); + assert(thread_sp && "AddThread() returned a nullptr"); - // Use a map to keep track of the threads which we have attached/need to attach. - Host::TidMap tids_to_attach; - if (pid <= 1) - { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } + // This will notify this is a new thread and tell the system it is + // stopped. + thread_sp->SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(*thread_sp); + SetCurrentThreadID(thread_sp->GetID()); + } - while (Host::FindProcessThreads(pid, tids_to_attach)) - { - for (Host::TidMap::iterator it = tids_to_attach.begin(); - it != tids_to_attach.end();) - { - if (it->second == false) - { - lldb::tid_t tid = it->first; - - // Attach to the requested process. - // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PTRACE_ATTACH, tid); - if (error.Fail()) - { - // No such thread. The thread may have exited. - // More error handling may be needed. - if (error.GetError() == ESRCH) - { - it = tids_to_attach.erase(it); - continue; - } - else - return -1; - } - - int status; - // Need to use __WALL otherwise we receive an error with errno=ECHLD - // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(tid, NULL, __WALL)) < 0) - { - // No such thread. The thread may have exited. - // More error handling may be needed. - if (errno == ESRCH) - { - it = tids_to_attach.erase(it); - continue; - } - else - { - error.SetErrorToErrno(); - return -1; - } - } - - error = SetDefaultPtraceOpts(tid); - if (error.Fail()) - return -1; - - if (log) - log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64, __FUNCTION__, tid); - - it->second = true; - - // Create the thread, mark it as stopped. - NativeThreadLinuxSP thread_sp (AddThread(static_cast<lldb::tid_t>(tid))); - assert (thread_sp && "AddThread() returned a nullptr"); - - // This will notify this is a new thread and tell the system it is stopped. - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - SetCurrentThreadID (thread_sp->GetID ()); - } - - // move the loop forward - ++it; - } + // move the loop forward + ++it; } + } - if (tids_to_attach.size() > 0) - { - m_pid = pid; - // Let our process instance know the thread has stopped. - SetState (StateType::eStateStopped); - } - else - { - error.SetErrorToGenericError(); - error.SetErrorString("No such process."); - return -1; - } + if (tids_to_attach.size() > 0) { + m_pid = pid; + // Let our process instance know the thread has stopped. + SetState(StateType::eStateStopped); + } else { + error.SetErrorToGenericError(); + error.SetErrorString("No such process."); + return -1; + } - return pid; + return pid; } -Error -NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) -{ - long ptrace_opts = 0; +Error NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) { + long ptrace_opts = 0; - // Have the child raise an event on exit. This is used to keep the child in - // limbo until it is destroyed. - ptrace_opts |= PTRACE_O_TRACEEXIT; + // Have the child raise an event on exit. This is used to keep the child in + // limbo until it is destroyed. + ptrace_opts |= PTRACE_O_TRACEEXIT; - // Have the tracer trace threads which spawn in the inferior process. - // TODO: if we want to support tracing the inferiors' child, add the - // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) - ptrace_opts |= PTRACE_O_TRACECLONE; + // Have the tracer trace threads which spawn in the inferior process. + // TODO: if we want to support tracing the inferiors' child, add the + // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) + ptrace_opts |= PTRACE_O_TRACECLONE; - // Have the tracer notify us before execve returns - // (needed to disable legacy SIGTRAP generation) - ptrace_opts |= PTRACE_O_TRACEEXEC; + // Have the tracer notify us before execve returns + // (needed to disable legacy SIGTRAP generation) + ptrace_opts |= PTRACE_O_TRACEEXEC; - return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts); + return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts); } -static ExitType convert_pid_status_to_exit_type (int status) -{ - if (WIFEXITED (status)) - return ExitType::eExitTypeExit; - else if (WIFSIGNALED (status)) - return ExitType::eExitTypeSignal; - else if (WIFSTOPPED (status)) - return ExitType::eExitTypeStop; - else - { - // We don't know what this is. - return ExitType::eExitTypeInvalid; - } +static ExitType convert_pid_status_to_exit_type(int status) { + if (WIFEXITED(status)) + return ExitType::eExitTypeExit; + else if (WIFSIGNALED(status)) + return ExitType::eExitTypeSignal; + else if (WIFSTOPPED(status)) + return ExitType::eExitTypeStop; + else { + // We don't know what this is. + return ExitType::eExitTypeInvalid; + } } -static int convert_pid_status_to_return_code (int status) -{ - if (WIFEXITED (status)) - return WEXITSTATUS (status); - else if (WIFSIGNALED (status)) - return WTERMSIG (status); - else if (WIFSTOPPED (status)) - return WSTOPSIG (status); - else - { - // We don't know what this is. - return ExitType::eExitTypeInvalid; - } +static int convert_pid_status_to_return_code(int status) { + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + return WTERMSIG(status); + else if (WIFSTOPPED(status)) + return WSTOPSIG(status); + else { + // We don't know what this is. + return ExitType::eExitTypeInvalid; + } } // Handles all waitpid events from the inferior process. -void -NativeProcessLinux::MonitorCallback(lldb::pid_t pid, - bool exited, - int signal, - int status) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); +void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, + int signal, int status) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Certain activities differ based on whether the pid is the tid of the main thread. - const bool is_main_thread = (pid == GetID ()); + // Certain activities differ based on whether the pid is the tid of the main + // thread. + const bool is_main_thread = (pid == GetID()); - // Handle when the thread exits. - if (exited) - { + // Handle when the thread exits. + if (exited) { + if (log) + log->Printf( + "NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 + " (%s main thread)", + __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not"); + + // This is a thread that exited. Ensure we're not tracking it anymore. + const bool thread_found = StopTrackingThread(pid); + + if (is_main_thread) { + // We only set the exit status and notify the delegate if we haven't + // already set the process + // state to an exited state. We normally should have received a SIGTRAP | + // (PTRACE_EVENT_EXIT << 8) + // for the main thread. + const bool already_notified = (GetState() == StateType::eStateExited) || + (GetState() == StateType::eStateCrashed); + if (!already_notified) { if (log) - log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not"); - - // This is a thread that exited. Ensure we're not tracking it anymore. - const bool thread_found = StopTrackingThread (pid); - - if (is_main_thread) - { - // We only set the exit status and notify the delegate if we haven't already set the process - // state to an exited state. We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8) - // for the main thread. - const bool already_notified = (GetState() == StateType::eStateExited) || (GetState () == StateType::eStateCrashed); - if (!already_notified) - { - if (log) - log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " handling main thread exit (%s), expected exit state already set but state was %s instead, setting exit state now", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found", StateAsCString (GetState ())); - // The main thread exited. We're done monitoring. Report to delegate. - SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); - - // Notify delegate that our process has exited. - SetState (StateType::eStateExited, true); - } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " main thread now exited (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); - } - } - else - { - // Do we want to report to the delegate in this case? I think not. If this was an orderly - // thread exit, we would already have received the SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, - // and we would have done an all-stop then. - if (log) - log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " handling non-main thread exit (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); - } - return; - } - - siginfo_t info; - const auto info_err = GetSignalInfo(pid, &info); - auto thread_sp = GetThreadByID(pid); - - if (! thread_sp) - { - // Normally, the only situation when we cannot find the thread is if we have just - // received a new thread notification. This is indicated by GetSignalInfo() returning - // si_code == SI_USER and si_pid == 0 + log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 + " handling main thread exit (%s), expected exit state " + "already set but state was %s instead, setting exit " + "state now", + __FUNCTION__, pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found", + StateAsCString(GetState())); + // The main thread exited. We're done monitoring. Report to delegate. + SetExitStatus(convert_pid_status_to_exit_type(status), + convert_pid_status_to_return_code(status), nullptr, true); + + // Notify delegate that our process has exited. + SetState(StateType::eStateExited, true); + } else { if (log) - log->Printf("NativeProcessLinux::%s received notification about an unknown tid %" PRIu64 ".", __FUNCTION__, pid); - - if (info_err.Fail()) - { - if (log) - log->Printf("NativeProcessLinux::%s (tid %" PRIu64 ") GetSignalInfo failed (%s). Ingoring this notification.", __FUNCTION__, pid, info_err.AsCString()); - return; - } - - if (log && (info.si_code != SI_USER || info.si_pid != 0)) - log->Printf("NativeProcessLinux::%s (tid %" PRIu64 ") unexpected signal info (si_code: %d, si_pid: %d). Treating as a new thread notification anyway.", __FUNCTION__, pid, info.si_code, info.si_pid); - - auto thread_sp = AddThread(pid); - // Resume the newly created thread. - ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*thread_sp); - return; - } - - // Get details on the signal raised. - if (info_err.Success()) - { - // We have retrieved the signal info. Dispatch appropriately. - if (info.si_signo == SIGTRAP) - MonitorSIGTRAP(info, *thread_sp); - else - MonitorSignal(info, *thread_sp, exited); - } + log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 + " main thread now exited (%s)", + __FUNCTION__, pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found"); + } + } else { + // Do we want to report to the delegate in this case? I think not. If + // this was an orderly + // thread exit, we would already have received the SIGTRAP | + // (PTRACE_EVENT_EXIT << 8) signal, + // and we would have done an all-stop then. + if (log) + log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 + " handling non-main thread exit (%s)", + __FUNCTION__, pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found"); + } + return; + } + + siginfo_t info; + const auto info_err = GetSignalInfo(pid, &info); + auto thread_sp = GetThreadByID(pid); + + if (!thread_sp) { + // Normally, the only situation when we cannot find the thread is if we have + // just + // received a new thread notification. This is indicated by GetSignalInfo() + // returning + // si_code == SI_USER and si_pid == 0 + if (log) + log->Printf("NativeProcessLinux::%s received notification about an " + "unknown tid %" PRIu64 ".", + __FUNCTION__, pid); + + if (info_err.Fail()) { + if (log) + log->Printf("NativeProcessLinux::%s (tid %" PRIu64 + ") GetSignalInfo failed (%s). Ingoring this notification.", + __FUNCTION__, pid, info_err.AsCString()); + return; + } + + if (log && (info.si_code != SI_USER || info.si_pid != 0)) + log->Printf("NativeProcessLinux::%s (tid %" PRIu64 + ") unexpected signal info (si_code: %d, si_pid: %d). " + "Treating as a new thread notification anyway.", + __FUNCTION__, pid, info.si_code, info.si_pid); + + auto thread_sp = AddThread(pid); + // Resume the newly created thread. + ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(*thread_sp); + return; + } + + // Get details on the signal raised. + if (info_err.Success()) { + // We have retrieved the signal info. Dispatch appropriately. + if (info.si_signo == SIGTRAP) + MonitorSIGTRAP(info, *thread_sp); else - { - if (info_err.GetError() == EINVAL) - { - // This is a group stop reception for this tid. - // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the - // tracee, triggering the group-stop mechanism. Normally receiving these would stop - // the process, pending a SIGCONT. Simulating this state in a debugger is hard and is - // generally not needed (one use case is debugging background task being managed by a - // shell). For general use, it is sufficient to stop the process in a signal-delivery - // stop which happens before the group stop. This done by MonitorSignal and works - // correctly for all signals. - if (log) - log->Printf("NativeProcessLinux::%s received a group stop for pid %" PRIu64 " tid %" PRIu64 ". Transparent handling of group stops not supported, resuming the thread.", __FUNCTION__, GetID (), pid); - ResumeThread(*thread_sp, thread_sp->GetState(), LLDB_INVALID_SIGNAL_NUMBER); - } - else - { - // ptrace(GETSIGINFO) failed (but not due to group-stop). - - // A return value of ESRCH means the thread/process is no longer on the system, - // so it was killed somehow outside of our control. Either way, we can't do anything - // with it anymore. - - // Stop tracking the metadata for the thread since it's entirely off the system now. - const bool thread_found = StopTrackingThread (pid); - - if (log) - log->Printf ("NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d (%s, %s, %s)", - __FUNCTION__, info_err.AsCString(), pid, signal, status, info_err.GetError() == ESRCH ? "thread/process killed" : "unknown reason", is_main_thread ? "is main thread" : "is not main thread", thread_found ? "thread metadata removed" : "thread metadata not found"); - - if (is_main_thread) - { - // Notify the delegate - our process is not available but appears to have been killed outside - // our control. Is eStateExited the right exit state in this case? - SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); - SetState (StateType::eStateExited, true); - } - else - { - // This thread was pulled out from underneath us. Anything to do here? Do we want to do an all stop? - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 " non-main thread exit occurred, didn't tell delegate anything since thread disappeared out from underneath us", __FUNCTION__, GetID (), pid); - } - } - } -} - -void -NativeProcessLinux::WaitForNewThread(::pid_t tid) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); - - if (new_thread_sp) - { - // We are already tracking the thread - we got the event on the new thread (see - // MonitorSignal) before this one. We are done. - return; - } - - // The thread is not tracked yet, let's wait for it to appear. - int status = -1; - ::pid_t wait_pid; - do - { - if (log) - log->Printf ("NativeProcessLinux::%s() received thread creation event for tid %" PRIu32 ". tid not tracked yet, waiting for thread to appear...", __FUNCTION__, tid); - wait_pid = waitpid(tid, &status, __WALL); - } - while (wait_pid == -1 && errno == EINTR); - // Since we are waiting on a specific tid, this must be the creation event. But let's do - // some checks just in case. - if (wait_pid != tid) { - if (log) - log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime", __FUNCTION__, tid); - // The only way I know of this could happen is if the whole process was - // SIGKILLed in the mean time. In any case, we can't do anything about that now. - return; - } - if (WIFEXITED(status)) - { - if (log) - log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " returned an 'exited' event. Not tracking the thread.", __FUNCTION__, tid); - // Also a very improbable event. - return; - } - - siginfo_t info; - Error error = GetSignalInfo(tid, &info); - if (error.Fail()) - { + MonitorSignal(info, *thread_sp, exited); + } else { + if (info_err.GetError() == EINVAL) { + // This is a group stop reception for this tid. + // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU + // into the + // tracee, triggering the group-stop mechanism. Normally receiving these + // would stop + // the process, pending a SIGCONT. Simulating this state in a debugger is + // hard and is + // generally not needed (one use case is debugging background task being + // managed by a + // shell). For general use, it is sufficient to stop the process in a + // signal-delivery + // stop which happens before the group stop. This done by MonitorSignal + // and works + // correctly for all signals. + if (log) + log->Printf( + "NativeProcessLinux::%s received a group stop for pid %" PRIu64 + " tid %" PRIu64 ". Transparent handling of group stops not " + "supported, resuming the thread.", + __FUNCTION__, GetID(), pid); + ResumeThread(*thread_sp, thread_sp->GetState(), + LLDB_INVALID_SIGNAL_NUMBER); + } else { + // ptrace(GETSIGINFO) failed (but not due to group-stop). + + // A return value of ESRCH means the thread/process is no longer on the + // system, + // so it was killed somehow outside of our control. Either way, we can't + // do anything + // with it anymore. + + // Stop tracking the metadata for the thread since it's entirely off the + // system now. + const bool thread_found = StopTrackingThread(pid); + + if (log) + log->Printf( + "NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64 + ", signal = %d, status = %d (%s, %s, %s)", + __FUNCTION__, info_err.AsCString(), pid, signal, status, + info_err.GetError() == ESRCH ? "thread/process killed" + : "unknown reason", + is_main_thread ? "is main thread" : "is not main thread", + thread_found ? "thread metadata removed" + : "thread metadata not found"); + + if (is_main_thread) { + // Notify the delegate - our process is not available but appears to + // have been killed outside + // our control. Is eStateExited the right exit state in this case? + SetExitStatus(convert_pid_status_to_exit_type(status), + convert_pid_status_to_return_code(status), nullptr, true); + SetState(StateType::eStateExited, true); + } else { + // This thread was pulled out from underneath us. Anything to do here? + // Do we want to do an all stop? if (log) - log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime.", __FUNCTION__, tid); - return; + log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 + " non-main thread exit occurred, didn't tell delegate " + "anything since thread disappeared out from underneath " + "us", + __FUNCTION__, GetID(), pid); + } } - - if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log) - { - // We should be getting a thread creation signal here, but we received something - // else. There isn't much we can do about it now, so we will just log that. Since the - // thread is alive and we are receiving events from it, we shall pretend that it was - // created properly. - log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " received unexpected signal with code %d from pid %d.", __FUNCTION__, tid, info.si_code, info.si_pid); - } - - if (log) - log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 ": tracking new thread tid %" PRIu32, - __FUNCTION__, GetID (), tid); - - new_thread_sp = AddThread(tid); - ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*new_thread_sp); + } } -void -NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - const bool is_main_thread = (thread.GetID() == GetID ()); +void NativeProcessLinux::WaitForNewThread(::pid_t tid) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); + NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); - switch (info.si_code) - { - // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor. - // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): - // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): + if (new_thread_sp) { + // We are already tracking the thread - we got the event on the new thread + // (see + // MonitorSignal) before this one. We are done. + return; + } - case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): - { - // This is the notification on the parent thread which informs us of new thread - // creation. - // We don't want to do anything with the parent thread so we just resume it. In case we - // want to implement "break on thread creation" functionality, we would need to stop - // here. - - unsigned long event_message = 0; - if (GetEventMessage(thread.GetID(), &event_message).Fail()) - { - if (log) - log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " received thread creation event but GetEventMessage failed so we don't know the new tid", __FUNCTION__, thread.GetID()); - } else - WaitForNewThread(event_message); + // The thread is not tracked yet, let's wait for it to appear. + int status = -1; + ::pid_t wait_pid; + do { + if (log) + log->Printf("NativeProcessLinux::%s() received thread creation event for " + "tid %" PRIu32 + ". tid not tracked yet, waiting for thread to appear...", + __FUNCTION__, tid); + wait_pid = waitpid(tid, &status, __WALL); + } while (wait_pid == -1 && errno == EINTR); + // Since we are waiting on a specific tid, this must be the creation event. + // But let's do + // some checks just in case. + if (wait_pid != tid) { + if (log) + log->Printf( + "NativeProcessLinux::%s() waiting for tid %" PRIu32 + " failed. Assuming the thread has disappeared in the meantime", + __FUNCTION__, tid); + // The only way I know of this could happen is if the whole process was + // SIGKILLed in the mean time. In any case, we can't do anything about that + // now. + return; + } + if (WIFEXITED(status)) { + if (log) + log->Printf("NativeProcessLinux::%s() waiting for tid %" PRIu32 + " returned an 'exited' event. Not tracking the thread.", + __FUNCTION__, tid); + // Also a very improbable event. + return; + } + + siginfo_t info; + Error error = GetSignalInfo(tid, &info); + if (error.Fail()) { + if (log) + log->Printf( + "NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 + " failed. Assuming the thread has disappeared in the meantime.", + __FUNCTION__, tid); + return; + } + + if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log) { + // We should be getting a thread creation signal here, but we received + // something + // else. There isn't much we can do about it now, so we will just log that. + // Since the + // thread is alive and we are receiving events from it, we shall pretend + // that it was + // created properly. + log->Printf("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 + " received unexpected signal with code %d from pid %d.", + __FUNCTION__, tid, info.si_code, info.si_pid); + } + + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 + ": tracking new thread tid %" PRIu32, + __FUNCTION__, GetID(), tid); + + new_thread_sp = AddThread(tid); + ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(*new_thread_sp); +} + +void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, + NativeThreadLinux &thread) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + const bool is_main_thread = (thread.GetID() == GetID()); + + assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); + + switch (info.si_code) { + // TODO: these two cases are required if we want to support tracing of the + // inferiors' children. We'd need this to debug a monitor. + // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): + // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): + + case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): { + // This is the notification on the parent thread which informs us of new + // thread + // creation. + // We don't want to do anything with the parent thread so we just resume it. + // In case we + // want to implement "break on thread creation" functionality, we would need + // to stop + // here. + + unsigned long event_message = 0; + if (GetEventMessage(thread.GetID(), &event_message).Fail()) { + if (log) + log->Printf("NativeProcessLinux::%s() pid %" PRIu64 + " received thread creation event but GetEventMessage " + "failed so we don't know the new tid", + __FUNCTION__, thread.GetID()); + } else + WaitForNewThread(event_message); + + ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); + break; + } + + case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { + NativeThreadLinuxSP main_thread_sp; + if (log) + log->Printf("NativeProcessLinux::%s() received exec event, code = %d", + __FUNCTION__, info.si_code ^ SIGTRAP); - ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); - break; - } + // Exec clears any pending notifications. + m_pending_notification_tid = LLDB_INVALID_THREAD_ID; - case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): - { - NativeThreadLinuxSP main_thread_sp; + // Remove all but the main thread here. Linux fork creates a new process + // which only copies the main thread. + if (log) + log->Printf("NativeProcessLinux::%s exec received, stop tracking all but " + "main thread", + __FUNCTION__); + + for (auto thread_sp : m_threads) { + const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID(); + if (is_main_thread) { + main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); if (log) - log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info.si_code ^ SIGTRAP); - - // Exec clears any pending notifications. - m_pending_notification_tid = LLDB_INVALID_THREAD_ID; - - // Remove all but the main thread here. Linux fork creates a new process which only copies the main thread. + log->Printf( + "NativeProcessLinux::%s found main thread with tid %" PRIu64 + ", keeping", + __FUNCTION__, main_thread_sp->GetID()); + } else { if (log) - log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__); - - for (auto thread_sp : m_threads) - { - const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID (); - if (is_main_thread) - { - main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); - if (log) - log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ()); - } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ()); - } - } - - m_threads.clear (); - - if (main_thread_sp) - { - m_threads.push_back (main_thread_sp); - SetCurrentThreadID (main_thread_sp->GetID ()); - main_thread_sp->SetStoppedByExec(); - } - else - { - SetCurrentThreadID (LLDB_INVALID_THREAD_ID); - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ()); - } - - // Tell coordinator about about the "new" (since exec) stopped main thread. - ThreadWasCreated(*main_thread_sp); - - // Let our delegate know we have just exec'd. - NotifyDidExec (); - - // If we have a main thread, indicate we are stopped. - assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked"); - - // Let the process know we're stopped. - StopRunningThreads(main_thread_sp->GetID()); - - break; - } - - case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): - { - // The inferior process or one of its threads is about to exit. - // We don't want to do anything with the thread so we just resume it. In case we - // want to implement "break on thread exit" functionality, we would need to stop - // here. - - unsigned long data = 0; - if (GetEventMessage(thread.GetID(), &data).Fail()) - data = -1; - - if (log) - { - log->Printf ("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = %lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)", - __FUNCTION__, - data, WIFEXITED (data) ? "true" : "false", WIFSIGNALED (data) ? "true" : "false", - thread.GetID(), - is_main_thread ? "is main thread" : "not main thread"); - } - - if (is_main_thread) - { - SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true); - } - - StateType state = thread.GetState(); - if (! StateIsRunningState(state)) - { - // Due to a kernel bug, we may sometimes get this stop after the inferior gets a - // SIGKILL. This confuses our state tracking logic in ResumeThread(), since normally, - // we should not be receiving any ptrace events while the inferior is stopped. This - // makes sure that the inferior is resumed and exits normally. - state = eStateRunning; - } - ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); - - break; + log->Printf( + "NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 + " due to exec", + __FUNCTION__, thread_sp->GetID()); + } } - case 0: - case TRAP_TRACE: // We receive this on single stepping. - case TRAP_HWBKPT: // We receive this on watchpoint hit - { - // If a watchpoint was hit, report it - uint32_t wp_index; - Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, (uintptr_t)info.si_addr); - if (error.Fail() && log) - log->Printf("NativeProcessLinux::%s() " - "received error while checking for watchpoint hits, " - "pid = %" PRIu64 " error = %s", - __FUNCTION__, thread.GetID(), error.AsCString()); - if (wp_index != LLDB_INVALID_INDEX32) - { - MonitorWatchpoint(thread, wp_index); - break; - } - - // Otherwise, report step over - MonitorTrace(thread); - break; - } + m_threads.clear(); - case SI_KERNEL: + if (main_thread_sp) { + m_threads.push_back(main_thread_sp); + SetCurrentThreadID(main_thread_sp->GetID()); + main_thread_sp->SetStoppedByExec(); + } else { + SetCurrentThreadID(LLDB_INVALID_THREAD_ID); + if (log) + log->Printf("NativeProcessLinux::%s pid %" PRIu64 + "no main thread found, discarded all threads, we're in a " + "no-thread state!", + __FUNCTION__, GetID()); + } + + // Tell coordinator about about the "new" (since exec) stopped main thread. + ThreadWasCreated(*main_thread_sp); + + // Let our delegate know we have just exec'd. + NotifyDidExec(); + + // If we have a main thread, indicate we are stopped. + assert(main_thread_sp && "exec called during ptraced process but no main " + "thread metadata tracked"); + + // Let the process know we're stopped. + StopRunningThreads(main_thread_sp->GetID()); + + break; + } + + case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { + // The inferior process or one of its threads is about to exit. + // We don't want to do anything with the thread so we just resume it. In + // case we + // want to implement "break on thread exit" functionality, we would need to + // stop + // here. + + unsigned long data = 0; + if (GetEventMessage(thread.GetID(), &data).Fail()) + data = -1; + + if (log) { + log->Printf("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = " + "%lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)", + __FUNCTION__, data, WIFEXITED(data) ? "true" : "false", + WIFSIGNALED(data) ? "true" : "false", thread.GetID(), + is_main_thread ? "is main thread" : "not main thread"); + } + + if (is_main_thread) { + SetExitStatus(convert_pid_status_to_exit_type(data), + convert_pid_status_to_return_code(data), nullptr, true); + } + + StateType state = thread.GetState(); + if (!StateIsRunningState(state)) { + // Due to a kernel bug, we may sometimes get this stop after the inferior + // gets a + // SIGKILL. This confuses our state tracking logic in ResumeThread(), + // since normally, + // we should not be receiving any ptrace events while the inferior is + // stopped. This + // makes sure that the inferior is resumed and exits normally. + state = eStateRunning; + } + ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); + + break; + } + + case 0: + case TRAP_TRACE: // We receive this on single stepping. + case TRAP_HWBKPT: // We receive this on watchpoint hit + { + // If a watchpoint was hit, report it + uint32_t wp_index; + Error error = thread.GetRegisterContext()->GetWatchpointHitIndex( + wp_index, (uintptr_t)info.si_addr); + if (error.Fail() && log) + log->Printf("NativeProcessLinux::%s() " + "received error while checking for watchpoint hits, " + "pid = %" PRIu64 " error = %s", + __FUNCTION__, thread.GetID(), error.AsCString()); + if (wp_index != LLDB_INVALID_INDEX32) { + MonitorWatchpoint(thread, wp_index); + break; + } + + // Otherwise, report step over + MonitorTrace(thread); + break; + } + + case SI_KERNEL: #if defined __mips__ - // For mips there is no special signal for watchpoint - // So we check for watchpoint in kernel trap - { - // If a watchpoint was hit, report it - uint32_t wp_index; - Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS); - if (error.Fail() && log) - log->Printf("NativeProcessLinux::%s() " - "received error while checking for watchpoint hits, " - "pid = %" PRIu64 " error = %s", - __FUNCTION__, thread.GetID(), error.AsCString()); - if (wp_index != LLDB_INVALID_INDEX32) - { - MonitorWatchpoint(thread, wp_index); - break; - } + // For mips there is no special signal for watchpoint + // So we check for watchpoint in kernel trap + { + // If a watchpoint was hit, report it + uint32_t wp_index; + Error error = thread.GetRegisterContext()->GetWatchpointHitIndex( + wp_index, LLDB_INVALID_ADDRESS); + if (error.Fail() && log) + log->Printf("NativeProcessLinux::%s() " + "received error while checking for watchpoint hits, " + "pid = %" PRIu64 " error = %s", + __FUNCTION__, thread.GetID(), error.AsCString()); + if (wp_index != LLDB_INVALID_INDEX32) { + MonitorWatchpoint(thread, wp_index); + break; + } } - // NO BREAK +// NO BREAK #endif - case TRAP_BRKPT: - MonitorBreakpoint(thread); - break; - - case SIGTRAP: - case (SIGTRAP | 0x80): - if (log) - log->Printf ("NativeProcessLinux::%s() received unknown SIGTRAP system call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming", __FUNCTION__, GetID (), thread.GetID()); + case TRAP_BRKPT: + MonitorBreakpoint(thread); + break; - // Ignore these signals until we know more about them. - ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); - break; + case SIGTRAP: + case (SIGTRAP | 0x80): + if (log) + log->Printf("NativeProcessLinux::%s() received unknown SIGTRAP system " + "call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming", + __FUNCTION__, GetID(), thread.GetID()); - default: - assert(false && "Unexpected SIGTRAP code!"); - if (log) - log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64 " received unhandled SIGTRAP code: 0x%d", - __FUNCTION__, GetID(), thread.GetID(), info.si_code); - break; - - } -} + // Ignore these signals until we know more about them. + ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); + break; -void -NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + default: + assert(false && "Unexpected SIGTRAP code!"); if (log) - log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", + log->Printf("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64 + " received unhandled SIGTRAP code: 0x%d", + __FUNCTION__, GetID(), thread.GetID(), info.si_code); + break; + } +} + +void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 + " (single stepping)", __FUNCTION__, thread.GetID()); - // This thread is currently stopped. - thread.SetStoppedByTrace(); + // This thread is currently stopped. + thread.SetStoppedByTrace(); - StopRunningThreads(thread.GetID()); + StopRunningThreads(thread.GetID()); } -void -NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, - __FUNCTION__, thread.GetID()); +void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) { + Log *log( + GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf( + "NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, + __FUNCTION__, thread.GetID()); - // Mark the thread as stopped at breakpoint. - thread.SetStoppedByBreakpoint(); - Error error = FixupBreakpointPCAsNeeded(thread); - if (error.Fail()) - if (log) - log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", - __FUNCTION__, thread.GetID(), error.AsCString()); + // Mark the thread as stopped at breakpoint. + thread.SetStoppedByBreakpoint(); + Error error = FixupBreakpointPCAsNeeded(thread); + if (error.Fail()) + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", + __FUNCTION__, thread.GetID(), error.AsCString()); - if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end()) - thread.SetStoppedByTrace(); + if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != + m_threads_stepping_with_breakpoint.end()) + thread.SetStoppedByTrace(); - StopRunningThreads(thread.GetID()); + StopRunningThreads(thread.GetID()); } -void -NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index) -{ - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("NativeProcessLinux::%s() received watchpoint event, " - "pid = %" PRIu64 ", wp_index = %" PRIu32, - __FUNCTION__, thread.GetID(), wp_index); +void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, + uint32_t wp_index) { + Log *log( + GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf("NativeProcessLinux::%s() received watchpoint event, " + "pid = %" PRIu64 ", wp_index = %" PRIu32, + __FUNCTION__, thread.GetID(), wp_index); - // Mark the thread as stopped at watchpoint. - // The address is at (lldb::addr_t)info->si_addr if we need it. - thread.SetStoppedByWatchpoint(wp_index); + // Mark the thread as stopped at watchpoint. + // The address is at (lldb::addr_t)info->si_addr if we need it. + thread.SetStoppedByWatchpoint(wp_index); - // We need to tell all other running threads before we notify the delegate about this stop. - StopRunningThreads(thread.GetID()); + // We need to tell all other running threads before we notify the delegate + // about this stop. + StopRunningThreads(thread.GetID()); } -void -NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited) -{ - const int signo = info.si_signo; - const bool is_from_llgs = info.si_pid == getpid (); - - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - // POSIX says that process behaviour is undefined after it ignores a SIGFPE, - // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a - // kill(2) or raise(3). Similarly for tgkill(2) on Linux. - // - // IOW, user generated signals never generate what we consider to be a - // "crash". - // - // Similarly, ACK signals generated by this monitor. - - // Handle the signal. - if (info.si_code == SI_TKILL || info.si_code == SI_USER) - { - if (log) - log->Printf ("NativeProcessLinux::%s() received signal %s (%d) with code %s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")", - __FUNCTION__, - Host::GetSignalAsCString(signo), - signo, - (info.si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"), - info.si_pid, - is_from_llgs ? "from llgs" : "not from llgs", - thread.GetID()); - } +void NativeProcessLinux::MonitorSignal(const siginfo_t &info, + NativeThreadLinux &thread, bool exited) { + const int signo = info.si_signo; + const bool is_from_llgs = info.si_pid == getpid(); - // Check for thread stop notification. - if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) - { - // This is a tgkill()-based stop. - if (log) - log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread stopped", - __FUNCTION__, - GetID (), - thread.GetID()); - - // Check that we're not already marked with a stop reason. - // Note this thread really shouldn't already be marked as stopped - if we were, that would imply that - // the kernel signaled us with the thread stopping which we handled and marked as stopped, - // and that, without an intervening resume, we received another stop. It is more likely - // that we are missing the marking of a run state somewhere if we find that the thread was - // marked as stopped. - const StateType thread_state = thread.GetState(); - if (!StateIsStoppedState (thread_state, false)) - { - // An inferior thread has stopped because of a SIGSTOP we have sent it. - // Generally, these are not important stops and we don't want to report them as - // they are just used to stop other threads when one thread (the one with the - // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in the - // case of an asynchronous Interrupt(), this *is* the real stop reason, so we - // leave the signal intact if this is the thread that was chosen as the - // triggering thread. - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) - { - if (m_pending_notification_tid == thread.GetID()) - thread.SetStoppedBySignal(SIGSTOP, &info); - else - thread.SetStoppedWithNoReason(); - - SetCurrentThreadID (thread.GetID ()); - SignalIfAllThreadsStopped(); - } - else - { - // We can end up here if stop was initiated by LLGS but by this time a - // thread stop has occurred - maybe initiated by another event. - Error error = ResumeThread(thread, thread.GetState(), 0); - if (error.Fail() && log) - { - log->Printf("NativeProcessLinux::%s failed to resume thread tid %" PRIu64 ": %s", - __FUNCTION__, thread.GetID(), error.AsCString()); - } - } - } + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a + // kill(2) or raise(3). Similarly for tgkill(2) on Linux. + // + // IOW, user generated signals never generate what we consider to be a + // "crash". + // + // Similarly, ACK signals generated by this monitor. + + // Handle the signal. + if (info.si_code == SI_TKILL || info.si_code == SI_USER) { + if (log) + log->Printf("NativeProcessLinux::%s() received signal %s (%d) with code " + "%s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")", + __FUNCTION__, Host::GetSignalAsCString(signo), signo, + (info.si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"), + info.si_pid, is_from_llgs ? "from llgs" : "not from llgs", + thread.GetID()); + } + + // Check for thread stop notification. + if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) { + // This is a tgkill()-based stop. + if (log) + log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 + ", thread stopped", + __FUNCTION__, GetID(), thread.GetID()); + + // Check that we're not already marked with a stop reason. + // Note this thread really shouldn't already be marked as stopped - if we + // were, that would imply that + // the kernel signaled us with the thread stopping which we handled and + // marked as stopped, + // and that, without an intervening resume, we received another stop. It is + // more likely + // that we are missing the marking of a run state somewhere if we find that + // the thread was + // marked as stopped. + const StateType thread_state = thread.GetState(); + if (!StateIsStoppedState(thread_state, false)) { + // An inferior thread has stopped because of a SIGSTOP we have sent it. + // Generally, these are not important stops and we don't want to report + // them as + // they are just used to stop other threads when one thread (the one with + // the + // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in + // the + // case of an asynchronous Interrupt(), this *is* the real stop reason, so + // we + // leave the signal intact if this is the thread that was chosen as the + // triggering thread. + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { + if (m_pending_notification_tid == thread.GetID()) + thread.SetStoppedBySignal(SIGSTOP, &info); else - { - if (log) - { - // Retrieve the signal name if the thread was stopped by a signal. - int stop_signo = 0; - const bool stopped_by_signal = thread.IsStopped(&stop_signo); - const char *signal_name = stopped_by_signal ? Host::GetSignalAsCString(stop_signo) : "<not stopped by signal>"; - if (!signal_name) - signal_name = "<no-signal-name>"; - - log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread was already marked as a stopped state (state=%s, signal=%d (%s)), leaving stop signal as is", - __FUNCTION__, - GetID (), - thread.GetID(), - StateAsCString (thread_state), - stop_signo, - signal_name); - } - SignalIfAllThreadsStopped(); + thread.SetStoppedWithNoReason(); + + SetCurrentThreadID(thread.GetID()); + SignalIfAllThreadsStopped(); + } else { + // We can end up here if stop was initiated by LLGS but by this time a + // thread stop has occurred - maybe initiated by another event. + Error error = ResumeThread(thread, thread.GetState(), 0); + if (error.Fail() && log) { + log->Printf( + "NativeProcessLinux::%s failed to resume thread tid %" PRIu64 + ": %s", + __FUNCTION__, thread.GetID(), error.AsCString()); } + } + } else { + if (log) { + // Retrieve the signal name if the thread was stopped by a signal. + int stop_signo = 0; + const bool stopped_by_signal = thread.IsStopped(&stop_signo); + const char *signal_name = stopped_by_signal + ? Host::GetSignalAsCString(stop_signo) + : "<not stopped by signal>"; + if (!signal_name) + signal_name = "<no-signal-name>"; - // Done handling. - return; + log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 + ", thread was already marked as a stopped state (state=%s, " + "signal=%d (%s)), leaving stop signal as is", + __FUNCTION__, GetID(), thread.GetID(), + StateAsCString(thread_state), stop_signo, signal_name); + } + SignalIfAllThreadsStopped(); } - if (log) - log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, Host::GetSignalAsCString(signo)); + // Done handling. + return; + } - // This thread is stopped. - thread.SetStoppedBySignal(signo, &info); + if (log) + log->Printf("NativeProcessLinux::%s() received signal %s", __FUNCTION__, + Host::GetSignalAsCString(signo)); - // Send a stop to the debugger after we get all other threads to stop. - StopRunningThreads(thread.GetID()); + // This thread is stopped. + thread.SetStoppedBySignal(signo, &info); + + // Send a stop to the debugger after we get all other threads to stop. + StopRunningThreads(thread.GetID()); } namespace { -struct EmulatorBaton -{ - NativeProcessLinux* m_process; - NativeRegisterContext* m_reg_context; +struct EmulatorBaton { + NativeProcessLinux *m_process; + NativeRegisterContext *m_reg_context; - // eRegisterKindDWARF -> RegsiterValue - std::unordered_map<uint32_t, RegisterValue> m_register_values; + // eRegisterKindDWARF -> RegsiterValue + std::unordered_map<uint32_t, RegisterValue> m_register_values; - EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) : - m_process(process), m_reg_context(reg_context) {} + EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) + : m_process(process), m_reg_context(reg_context) {} }; } // anonymous namespace -static size_t -ReadMemoryCallback (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, - void *dst, - size_t length) -{ - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); +static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, void *dst, size_t length) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - size_t bytes_read; - emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); - return bytes_read; + size_t bytes_read; + emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); + return bytes_read; } -static bool -ReadRegisterCallback (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) -{ - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); - - auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]); - if (it != emulator_baton->m_register_values.end()) - { - reg_value = it->second; - return true; - } +static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - // The emulator only fill in the dwarf regsiter numbers (and in some case - // the generic register numbers). Get the full register info from the - // register context based on the dwarf register numbers. - const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( - eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); - - Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); - if (error.Success()) - return true; + auto it = emulator_baton->m_register_values.find( + reg_info->kinds[eRegisterKindDWARF]); + if (it != emulator_baton->m_register_values.end()) { + reg_value = it->second; + return true; + } + + // The emulator only fill in the dwarf regsiter numbers (and in some case + // the generic register numbers). Get the full register info from the + // register context based on the dwarf register numbers. + const RegisterInfo *full_reg_info = + emulator_baton->m_reg_context->GetRegisterInfo( + eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); + + Error error = + emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + if (error.Success()) + return true; - return false; + return false; } -static bool -WriteRegisterCallback (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) -{ - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); - emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value; - return true; +static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = + reg_value; + return true; } -static size_t -WriteMemoryCallback (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, - const void *dst, - size_t length) -{ - return length; +static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, const void *dst, + size_t length) { + return length; } -static lldb::addr_t -ReadFlags (NativeRegisterContext* regsiter_context) -{ - const RegisterInfo* flags_info = regsiter_context->GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS); +static lldb::addr_t ReadFlags(NativeRegisterContext *regsiter_context) { + const RegisterInfo *flags_info = regsiter_context->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + return regsiter_context->ReadRegisterAsUnsigned(flags_info, + LLDB_INVALID_ADDRESS); } -Error -NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) -{ - Error error; - NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); - - std::unique_ptr<EmulateInstruction> emulator_ap( - EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); +Error NativeProcessLinux::SetupSoftwareSingleStepping( + NativeThreadLinux &thread) { + Error error; + NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); - if (emulator_ap == nullptr) - return Error("Instruction emulator not found!"); + std::unique_ptr<EmulateInstruction> emulator_ap( + EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, + nullptr)); - EmulatorBaton baton(this, register_context_sp.get()); - emulator_ap->SetBaton(&baton); - emulator_ap->SetReadMemCallback(&ReadMemoryCallback); - emulator_ap->SetReadRegCallback(&ReadRegisterCallback); - emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); - emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); + if (emulator_ap == nullptr) + return Error("Instruction emulator not found!"); - if (!emulator_ap->ReadInstruction()) - return Error("Read instruction failed!"); + EmulatorBaton baton(this, register_context_sp.get()); + emulator_ap->SetBaton(&baton); + emulator_ap->SetReadMemCallback(&ReadMemoryCallback); + emulator_ap->SetReadRegCallback(&ReadRegisterCallback); + emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); + emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); - bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); + if (!emulator_ap->ReadInstruction()) + return Error("Read instruction failed!"); - const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + bool emulation_result = + emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); - auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); - auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); + const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const RegisterInfo *reg_info_flags = register_context_sp->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - lldb::addr_t next_pc; - lldb::addr_t next_flags; - if (emulation_result) - { - assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated"); - next_pc = pc_it->second.GetAsUInt64(); + auto pc_it = + baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); + auto flags_it = + baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); - if (flags_it != baton.m_register_values.end()) - next_flags = flags_it->second.GetAsUInt64(); - else - next_flags = ReadFlags (register_context_sp.get()); - } - else if (pc_it == baton.m_register_values.end()) - { - // Emulate instruction failed and it haven't changed PC. Advance PC - // with the size of the current opcode because the emulation of all - // PC modifying instruction should be successful. The failure most - // likely caused by a not supported instruction which don't modify PC. - next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); - next_flags = ReadFlags (register_context_sp.get()); - } - else - { - // The instruction emulation failed after it modified the PC. It is an - // unknown error where we can't continue because the next instruction is - // modifying the PC but we don't know how. - return Error ("Instruction emulation failed unexpectedly."); - } + lldb::addr_t next_pc; + lldb::addr_t next_flags; + if (emulation_result) { + assert(pc_it != baton.m_register_values.end() && + "Emulation was successfull but PC wasn't updated"); + next_pc = pc_it->second.GetAsUInt64(); - if (m_arch.GetMachine() == llvm::Triple::arm) - { - if (next_flags & 0x20) - { - // Thumb mode - error = SetSoftwareBreakpoint(next_pc, 2); - } - else - { - // Arm mode - error = SetSoftwareBreakpoint(next_pc, 4); - } - } - else if (m_arch.GetMachine() == llvm::Triple::mips64 - || m_arch.GetMachine() == llvm::Triple::mips64el - || m_arch.GetMachine() == llvm::Triple::mips - || m_arch.GetMachine() == llvm::Triple::mipsel) - error = SetSoftwareBreakpoint(next_pc, 4); + if (flags_it != baton.m_register_values.end()) + next_flags = flags_it->second.GetAsUInt64(); else - { - // No size hint is given for the next breakpoint - error = SetSoftwareBreakpoint(next_pc, 0); - } - - if (error.Fail()) - return error; + next_flags = ReadFlags(register_context_sp.get()); + } else if (pc_it == baton.m_register_values.end()) { + // Emulate instruction failed and it haven't changed PC. Advance PC + // with the size of the current opcode because the emulation of all + // PC modifying instruction should be successful. The failure most + // likely caused by a not supported instruction which don't modify PC. + next_pc = + register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); + next_flags = ReadFlags(register_context_sp.get()); + } else { + // The instruction emulation failed after it modified the PC. It is an + // unknown error where we can't continue because the next instruction is + // modifying the PC but we don't know how. + return Error("Instruction emulation failed unexpectedly."); + } + + if (m_arch.GetMachine() == llvm::Triple::arm) { + if (next_flags & 0x20) { + // Thumb mode + error = SetSoftwareBreakpoint(next_pc, 2); + } else { + // Arm mode + error = SetSoftwareBreakpoint(next_pc, 4); + } + } else if (m_arch.GetMachine() == llvm::Triple::mips64 || + m_arch.GetMachine() == llvm::Triple::mips64el || + m_arch.GetMachine() == llvm::Triple::mips || + m_arch.GetMachine() == llvm::Triple::mipsel) + error = SetSoftwareBreakpoint(next_pc, 4); + else { + // No size hint is given for the next breakpoint + error = SetSoftwareBreakpoint(next_pc, 0); + } + + if (error.Fail()) + return error; - m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); + m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); - return Error(); + return Error(); } -bool -NativeProcessLinux::SupportHardwareSingleStepping() const -{ - if (m_arch.GetMachine() == llvm::Triple::arm - || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el - || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) - return false; - return true; +bool NativeProcessLinux::SupportHardwareSingleStepping() const { + if (m_arch.GetMachine() == llvm::Triple::arm || + m_arch.GetMachine() == llvm::Triple::mips64 || + m_arch.GetMachine() == llvm::Triple::mips64el || + m_arch.GetMachine() == llvm::Triple::mips || + m_arch.GetMachine() == llvm::Triple::mipsel) + return false; + return true; } -Error -NativeProcessLinux::Resume (const ResumeActionList &resume_actions) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, GetID ()); +Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, + GetID()); - bool software_single_step = !SupportHardwareSingleStepping(); + bool software_single_step = !SupportHardwareSingleStepping(); - if (software_single_step) - { - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not contain NULL threads"); - - const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); - if (action == nullptr) - continue; - - if (action->state == eStateStepping) - { - Error error = SetupSoftwareSingleStepping(static_cast<NativeThreadLinux &>(*thread_sp)); - if (error.Fail()) - return error; - } - } + if (software_single_step) { + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not contain NULL threads"); + + const ResumeAction *const action = + resume_actions.GetActionForThread(thread_sp->GetID(), true); + if (action == nullptr) + continue; + + if (action->state == eStateStepping) { + Error error = SetupSoftwareSingleStepping( + static_cast<NativeThreadLinux &>(*thread_sp)); + if (error.Fail()) + return error; + } } + } - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not contain NULL threads"); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not contain NULL threads"); - const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); + const ResumeAction *const action = + resume_actions.GetActionForThread(thread_sp->GetID(), true); - if (action == nullptr) - { - if (log) - log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64 " tid %" PRIu64, - __FUNCTION__, GetID (), thread_sp->GetID ()); - continue; - } + if (action == nullptr) { + if (log) + log->Printf( + "NativeProcessLinux::%s no action specified for pid %" PRIu64 + " tid %" PRIu64, + __FUNCTION__, GetID(), thread_sp->GetID()); + continue; + } - if (log) - { - log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64 " tid %" PRIu64, - __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); - } + if (log) { + log->Printf("NativeProcessLinux::%s processing resume action state %s " + "for pid %" PRIu64 " tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread_sp->GetID()); + } - switch (action->state) - { - case eStateRunning: - case eStateStepping: - { - // Run the thread, possibly feeding it the signal. - const int signo = action->signal; - ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, signo); - break; - } + switch (action->state) { + case eStateRunning: + case eStateStepping: { + // Run the thread, possibly feeding it the signal. + const int signo = action->signal; + ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, + signo); + break; + } - case eStateSuspended: - case eStateStopped: - lldbassert(0 && "Unexpected state"); + case eStateSuspended: + case eStateStopped: + lldbassert(0 && "Unexpected state"); - default: - return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64, - __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); - } + default: + return Error("NativeProcessLinux::%s (): unexpected state %s specified " + "for pid %" PRIu64 ", tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread_sp->GetID()); } + } - return Error(); + return Error(); } -Error -NativeProcessLinux::Halt () -{ - Error error; +Error NativeProcessLinux::Halt() { + Error error; - if (kill (GetID (), SIGSTOP) != 0) - error.SetErrorToErrno (); + if (kill(GetID(), SIGSTOP) != 0) + error.SetErrorToErrno(); - return error; + return error; } -Error -NativeProcessLinux::Detach () -{ - Error error; +Error NativeProcessLinux::Detach() { + Error error; - // Stop monitoring the inferior. - m_sigchld_handle.reset(); + // Stop monitoring the inferior. + m_sigchld_handle.reset(); - // Tell ptrace to detach from the process. - if (GetID () == LLDB_INVALID_PROCESS_ID) - return error; + // Tell ptrace to detach from the process. + if (GetID() == LLDB_INVALID_PROCESS_ID) + return error; - for (auto thread_sp : m_threads) - { - Error e = Detach(thread_sp->GetID()); - if (e.Fail()) - error = e; // Save the error, but still attempt to detach from other threads. - } + for (auto thread_sp : m_threads) { + Error e = Detach(thread_sp->GetID()); + if (e.Fail()) + error = + e; // Save the error, but still attempt to detach from other threads. + } - return error; + return error; } -Error -NativeProcessLinux::Signal (int signo) -{ - Error error; +Error NativeProcessLinux::Signal(int signo) { + Error error; - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64, - __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID()); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf( + "NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64, + __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID()); - if (kill(GetID(), signo)) - error.SetErrorToErrno(); + if (kill(GetID(), signo)) + error.SetErrorToErrno(); - return error; + return error; } -Error -NativeProcessLinux::Interrupt () -{ - // Pick a running thread (or if none, a not-dead stopped thread) as - // the chosen thread that will be the stop-reason thread. - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); +Error NativeProcessLinux::Interrupt() { + // Pick a running thread (or if none, a not-dead stopped thread) as + // the chosen thread that will be the stop-reason thread. + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - NativeThreadProtocolSP running_thread_sp; - NativeThreadProtocolSP stopped_thread_sp; - - if (log) - log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__); - - for (auto thread_sp : m_threads) - { - // The thread shouldn't be null but lets just cover that here. - if (!thread_sp) - continue; + NativeThreadProtocolSP running_thread_sp; + NativeThreadProtocolSP stopped_thread_sp; - // If we have a running or stepping thread, we'll call that the - // target of the interrupt. - const auto thread_state = thread_sp->GetState (); - if (thread_state == eStateRunning || - thread_state == eStateStepping) - { - running_thread_sp = thread_sp; - break; - } - else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true)) - { - // Remember the first non-dead stopped thread. We'll use that as a backup if there are no running threads. - stopped_thread_sp = thread_sp; - } - } + if (log) + log->Printf( + "NativeProcessLinux::%s selecting running thread for interrupt target", + __FUNCTION__); - if (!running_thread_sp && !stopped_thread_sp) - { - Error error("found no running/stepping or live stopped threads as target for interrupt"); - if (log) - log->Printf ("NativeProcessLinux::%s skipping due to error: %s", __FUNCTION__, error.AsCString ()); + for (auto thread_sp : m_threads) { + // The thread shouldn't be null but lets just cover that here. + if (!thread_sp) + continue; - return error; + // If we have a running or stepping thread, we'll call that the + // target of the interrupt. + const auto thread_state = thread_sp->GetState(); + if (thread_state == eStateRunning || thread_state == eStateStepping) { + running_thread_sp = thread_sp; + break; + } else if (!stopped_thread_sp && StateIsStoppedState(thread_state, true)) { + // Remember the first non-dead stopped thread. We'll use that as a backup + // if there are no running threads. + stopped_thread_sp = thread_sp; } + } - NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp; - + if (!running_thread_sp && !stopped_thread_sp) { + Error error("found no running/stepping or live stopped threads as target " + "for interrupt"); if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64 " chosen for interrupt target", - __FUNCTION__, - GetID (), - running_thread_sp ? "running" : "stopped", - deferred_signal_thread_sp->GetID ()); - - StopRunningThreads(deferred_signal_thread_sp->GetID()); - - return Error(); -} - -Error -NativeProcessLinux::Kill () -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, GetID ()); - - Error error; - - switch (m_state) - { - case StateType::eStateInvalid: - case StateType::eStateExited: - case StateType::eStateCrashed: - case StateType::eStateDetached: - case StateType::eStateUnloaded: - // Nothing to do - the process is already dead. - if (log) - log->Printf ("NativeProcessLinux::%s ignored for PID %" PRIu64 " due to current state: %s", __FUNCTION__, GetID (), StateAsCString (m_state)); - return error; - - case StateType::eStateConnected: - case StateType::eStateAttaching: - case StateType::eStateLaunching: - case StateType::eStateStopped: - case StateType::eStateRunning: - case StateType::eStateStepping: - case StateType::eStateSuspended: - // We can try to kill a process in these states. - break; - } - - if (kill (GetID (), SIGKILL) != 0) - { - error.SetErrorToErrno (); - return error; - } + log->Printf("NativeProcessLinux::%s skipping due to error: %s", + __FUNCTION__, error.AsCString()); return error; -} - -static Error -ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info) -{ - memory_region_info.Clear(); - - StringExtractor line_extractor (maps_line.c_str ()); - - // Format: {address_start_hex}-{address_end_hex} perms offset dev inode pathname - // perms: rwxp (letter is present if set, '-' if not, final character is p=private, s=shared). - - // Parse out the starting address - lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0); - - // Parse out hyphen separating start and end address from range. - if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-')) - return Error ("malformed /proc/{pid}/maps entry, missing dash between address range"); + } - // Parse out the ending address - lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address); + NativeThreadProtocolSP deferred_signal_thread_sp = + running_thread_sp ? running_thread_sp : stopped_thread_sp; - // Parse out the space after the address. - if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' ')) - return Error ("malformed /proc/{pid}/maps entry, missing space after range"); + if (log) + log->Printf("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64 + " chosen for interrupt target", + __FUNCTION__, GetID(), + running_thread_sp ? "running" : "stopped", + deferred_signal_thread_sp->GetID()); - // Save the range. - memory_region_info.GetRange ().SetRangeBase (start_address); - memory_region_info.GetRange ().SetRangeEnd (end_address); + StopRunningThreads(deferred_signal_thread_sp->GetID()); - // Any memory region in /proc/{pid}/maps is by definition mapped into the process. - memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); + return Error(); +} - // Parse out each permission entry. - if (line_extractor.GetBytesLeft () < 4) - return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions"); +Error NativeProcessLinux::Kill() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, + GetID()); - // Handle read permission. - const char read_perm_char = line_extractor.GetChar (); - if (read_perm_char == 'r') - memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes); - else if (read_perm_char == '-') - memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); - else - return Error ("unexpected /proc/{pid}/maps read permission char"); - - // Handle write permission. - const char write_perm_char = line_extractor.GetChar (); - if (write_perm_char == 'w') - memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes); - else if (write_perm_char == '-') - memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); - else - return Error ("unexpected /proc/{pid}/maps write permission char"); - - // Handle execute permission. - const char exec_perm_char = line_extractor.GetChar (); - if (exec_perm_char == 'x') - memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes); - else if (exec_perm_char == '-') - memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); - else - return Error ("unexpected /proc/{pid}/maps exec permission char"); + Error error; - line_extractor.GetChar(); // Read the private bit - line_extractor.SkipSpaces(); // Skip the separator - line_extractor.GetHexMaxU64(false, 0); // Read the offset - line_extractor.GetHexMaxU64(false, 0); // Read the major device number - line_extractor.GetChar(); // Read the device id separator - line_extractor.GetHexMaxU64(false, 0); // Read the major device number - line_extractor.SkipSpaces(); // Skip the separator - line_extractor.GetU64(0, 10); // Read the inode number + switch (m_state) { + case StateType::eStateInvalid: + case StateType::eStateExited: + case StateType::eStateCrashed: + case StateType::eStateDetached: + case StateType::eStateUnloaded: + // Nothing to do - the process is already dead. + if (log) + log->Printf("NativeProcessLinux::%s ignored for PID %" PRIu64 + " due to current state: %s", + __FUNCTION__, GetID(), StateAsCString(m_state)); + return error; - line_extractor.SkipSpaces(); - const char* name = line_extractor.Peek(); - if (name) - memory_region_info.SetName(name); + case StateType::eStateConnected: + case StateType::eStateAttaching: + case StateType::eStateLaunching: + case StateType::eStateStopped: + case StateType::eStateRunning: + case StateType::eStateStepping: + case StateType::eStateSuspended: + // We can try to kill a process in these states. + break; + } + + if (kill(GetID(), SIGKILL) != 0) { + error.SetErrorToErrno(); + return error; + } - return Error (); + return error; } -Error -NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) -{ - // FIXME review that the final memory region returned extends to the end of the virtual address space, - // with no perms if it is not mapped. - - // Use an approach that reads memory regions from /proc/{pid}/maps. - // Assume proc maps entries are in ascending order. - // FIXME assert if we find differently. - - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - Error error; - - if (m_supports_mem_region == LazyBool::eLazyBoolNo) - { - // We're done. - error.SetErrorString ("unsupported"); - return error; - } - - // If our cache is empty, pull the latest. There should always be at least one memory region - // if memory region handling is supported. - if (m_mem_region_cache.empty ()) - { - error = ProcFileReader::ProcessLineByLine (GetID (), "maps", - [&] (const std::string &line) -> bool - { - MemoryRegionInfo info; - const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine (line, info); - if (parse_error.Success ()) - { - m_mem_region_cache.push_back (info); - return true; - } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ()); - return false; - } - }); - - // If we had an error, we'll mark unsupported. - if (error.Fail ()) - { - m_supports_mem_region = LazyBool::eLazyBoolNo; - return error; - } - else if (m_mem_region_cache.empty ()) - { - // No entries after attempting to read them. This shouldn't happen if /proc/{pid}/maps - // is supported. Assume we don't support map entries via procfs. +static Error +ParseMemoryRegionInfoFromProcMapsLine(const std::string &maps_line, + MemoryRegionInfo &memory_region_info) { + memory_region_info.Clear(); + + StringExtractor line_extractor(maps_line.c_str()); + + // Format: {address_start_hex}-{address_end_hex} perms offset dev inode + // pathname + // perms: rwxp (letter is present if set, '-' if not, final character is + // p=private, s=shared). + + // Parse out the starting address + lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0); + + // Parse out hyphen separating start and end address from range. + if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-')) + return Error( + "malformed /proc/{pid}/maps entry, missing dash between address range"); + + // Parse out the ending address + lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address); + + // Parse out the space after the address. + if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' ')) + return Error("malformed /proc/{pid}/maps entry, missing space after range"); + + // Save the range. + memory_region_info.GetRange().SetRangeBase(start_address); + memory_region_info.GetRange().SetRangeEnd(end_address); + + // Any memory region in /proc/{pid}/maps is by definition mapped into the + // process. + memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); + + // Parse out each permission entry. + if (line_extractor.GetBytesLeft() < 4) + return Error("malformed /proc/{pid}/maps entry, missing some portion of " + "permissions"); + + // Handle read permission. + const char read_perm_char = line_extractor.GetChar(); + if (read_perm_char == 'r') + memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes); + else if (read_perm_char == '-') + memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + else + return Error("unexpected /proc/{pid}/maps read permission char"); + + // Handle write permission. + const char write_perm_char = line_extractor.GetChar(); + if (write_perm_char == 'w') + memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes); + else if (write_perm_char == '-') + memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + else + return Error("unexpected /proc/{pid}/maps write permission char"); + + // Handle execute permission. + const char exec_perm_char = line_extractor.GetChar(); + if (exec_perm_char == 'x') + memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes); + else if (exec_perm_char == '-') + memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + else + return Error("unexpected /proc/{pid}/maps exec permission char"); + + line_extractor.GetChar(); // Read the private bit + line_extractor.SkipSpaces(); // Skip the separator + line_extractor.GetHexMaxU64(false, 0); // Read the offset + line_extractor.GetHexMaxU64(false, 0); // Read the major device number + line_extractor.GetChar(); // Read the device id separator + line_extractor.GetHexMaxU64(false, 0); // Read the major device number + line_extractor.SkipSpaces(); // Skip the separator + line_extractor.GetU64(0, 10); // Read the inode number + + line_extractor.SkipSpaces(); + const char *name = line_extractor.Peek(); + if (name) + memory_region_info.SetName(name); + + return Error(); +} + +Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + // FIXME review that the final memory region returned extends to the end of + // the virtual address space, + // with no perms if it is not mapped. + + // Use an approach that reads memory regions from /proc/{pid}/maps. + // Assume proc maps entries are in ascending order. + // FIXME assert if we find differently. + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Error error; + + if (m_supports_mem_region == LazyBool::eLazyBoolNo) { + // We're done. + error.SetErrorString("unsupported"); + return error; + } + + // If our cache is empty, pull the latest. There should always be at least + // one memory region + // if memory region handling is supported. + if (m_mem_region_cache.empty()) { + error = ProcFileReader::ProcessLineByLine( + GetID(), "maps", [&](const std::string &line) -> bool { + MemoryRegionInfo info; + const Error parse_error = + ParseMemoryRegionInfoFromProcMapsLine(line, info); + if (parse_error.Success()) { + m_mem_region_cache.push_back(info); + return true; + } else { if (log) - log->Printf ("NativeProcessLinux::%s failed to find any procfs maps entries, assuming no support for memory region metadata retrieval", __FUNCTION__); - m_supports_mem_region = LazyBool::eLazyBoolNo; - error.SetErrorString ("not supported"); - return error; - } - - if (log) - log->Printf ("NativeProcessLinux::%s read %" PRIu64 " memory region entries from /proc/%" PRIu64 "/maps", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()), GetID ()); - - // We support memory retrieval, remember that. - m_supports_mem_region = LazyBool::eLazyBoolYes; - } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s reusing %" PRIu64 " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); - } - - lldb::addr_t prev_base_address = 0; - - // FIXME start by finding the last region that is <= target address using binary search. Data is sorted. - // There can be a ton of regions on pthreads apps with lots of threads. - for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it) - { - MemoryRegionInfo &proc_entry_info = *it; - - // Sanity check assumption that /proc/{pid}/maps entries are ascending. - assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected"); - prev_base_address = proc_entry_info.GetRange ().GetRangeBase (); - - // If the target address comes before this entry, indicate distance to next region. - if (load_addr < proc_entry_info.GetRange ().GetRangeBase ()) - { - range_info.GetRange ().SetRangeBase (load_addr); - range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr); - range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); - - return error; - } - else if (proc_entry_info.GetRange ().Contains (load_addr)) - { - // The target address is within the memory region we're processing here. - range_info = proc_entry_info; - return error; - } + log->Printf("NativeProcessLinux::%s failed to parse proc maps " + "line '%s': %s", + __FUNCTION__, line.c_str(), error.AsCString()); + return false; + } + }); - // The target memory address comes somewhere after the region we just parsed. + // If we had an error, we'll mark unsupported. + if (error.Fail()) { + m_supports_mem_region = LazyBool::eLazyBoolNo; + return error; + } else if (m_mem_region_cache.empty()) { + // No entries after attempting to read them. This shouldn't happen if + // /proc/{pid}/maps + // is supported. Assume we don't support map entries via procfs. + if (log) + log->Printf("NativeProcessLinux::%s failed to find any procfs maps " + "entries, assuming no support for memory region metadata " + "retrieval", + __FUNCTION__); + m_supports_mem_region = LazyBool::eLazyBoolNo; + error.SetErrorString("not supported"); + return error; } - // If we made it here, we didn't find an entry that contained the given address. Return the - // load_addr as start and the amount of bytes betwwen load address and the end of the memory as - // size. - range_info.GetRange ().SetRangeBase (load_addr); - range_info.GetRange ().SetRangeEnd(LLDB_INVALID_ADDRESS); - range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); - range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); - return error; -} - -void -NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) - log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", __FUNCTION__, newBumpId); - - if (log) - log->Printf ("NativeProcessLinux::%s clearing %" PRIu64 " entries from the cache", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); - m_mem_region_cache.clear (); -} - -Error -NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) -{ - // FIXME implementing this requires the equivalent of - // InferiorCallPOSIX::InferiorCallMmap, which depends on - // functional ThreadPlans working with Native*Protocol. + log->Printf("NativeProcessLinux::%s read %" PRIu64 + " memory region entries from /proc/%" PRIu64 "/maps", + __FUNCTION__, + static_cast<uint64_t>(m_mem_region_cache.size()), GetID()); + + // We support memory retrieval, remember that. + m_supports_mem_region = LazyBool::eLazyBoolYes; + } else { + if (log) + log->Printf("NativeProcessLinux::%s reusing %" PRIu64 + " cached memory region entries", + __FUNCTION__, + static_cast<uint64_t>(m_mem_region_cache.size())); + } + + lldb::addr_t prev_base_address = 0; + + // FIXME start by finding the last region that is <= target address using + // binary search. Data is sorted. + // There can be a ton of regions on pthreads apps with lots of threads. + for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); + ++it) { + MemoryRegionInfo &proc_entry_info = *it; + + // Sanity check assumption that /proc/{pid}/maps entries are ascending. + assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && + "descending /proc/pid/maps entries detected, unexpected"); + prev_base_address = proc_entry_info.GetRange().GetRangeBase(); + + // If the target address comes before this entry, indicate distance to next + // region. + if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetByteSize( + proc_entry_info.GetRange().GetRangeBase() - load_addr); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + + return error; + } else if (proc_entry_info.GetRange().Contains(load_addr)) { + // The target address is within the memory region we're processing here. + range_info = proc_entry_info; + return error; + } + + // The target memory address comes somewhere after the region we just + // parsed. + } + + // If we made it here, we didn't find an entry that contained the given + // address. Return the + // load_addr as start and the amount of bytes betwwen load address and the end + // of the memory as + // size. + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + return error; +} + +void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", + __FUNCTION__, newBumpId); + + if (log) + log->Printf("NativeProcessLinux::%s clearing %" PRIu64 + " entries from the cache", + __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size())); + m_mem_region_cache.clear(); +} + +Error NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) { +// FIXME implementing this requires the equivalent of +// InferiorCallPOSIX::InferiorCallMmap, which depends on +// functional ThreadPlans working with Native*Protocol. #if 1 - return Error ("not implemented yet"); + return Error("not implemented yet"); #else + addr = LLDB_INVALID_ADDRESS; + + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + // TODO implement this directly in NativeProcessLinux + // (and lift to NativeProcessPOSIX if/when that class is + // refactored out). + if (InferiorCallMmap(this, addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { + m_addr_to_mmap_size[addr] = size; + return Error(); + } else { addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - // TODO implement this directly in NativeProcessLinux - // (and lift to NativeProcessPOSIX if/when that class is - // refactored out). - if (InferiorCallMmap(this, addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[addr] = size; - return Error (); - } else { - addr = LLDB_INVALID_ADDRESS; - return Error("unable to allocate %" PRIu64 " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } + return Error("unable to allocate %" PRIu64 + " bytes of memory with permissions %s", + size, GetPermissionsAsCString(permissions)); + } #endif } -Error -NativeProcessLinux::DeallocateMemory (lldb::addr_t addr) -{ - // FIXME see comments in AllocateMemory - required lower-level - // bits not in place yet (ThreadPlans) - return Error ("not implemented"); +Error NativeProcessLinux::DeallocateMemory(lldb::addr_t addr) { + // FIXME see comments in AllocateMemory - required lower-level + // bits not in place yet (ThreadPlans) + return Error("not implemented"); } -lldb::addr_t -NativeProcessLinux::GetSharedLibraryInfoAddress () -{ - // punt on this for now - return LLDB_INVALID_ADDRESS; +lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() { + // punt on this for now + return LLDB_INVALID_ADDRESS; } -size_t -NativeProcessLinux::UpdateThreads () -{ - // The NativeProcessLinux monitoring threads are always up to date - // with respect to thread state and they keep the thread list - // populated properly. All this method needs to do is return the - // thread count. - return m_threads.size (); +size_t NativeProcessLinux::UpdateThreads() { + // The NativeProcessLinux monitoring threads are always up to date + // with respect to thread state and they keep the thread list + // populated properly. All this method needs to do is return the + // thread count. + return m_threads.size(); } -bool -NativeProcessLinux::GetArchitecture (ArchSpec &arch) const -{ - arch = m_arch; - return true; +bool NativeProcessLinux::GetArchitecture(ArchSpec &arch) const { + arch = m_arch; + return true; } -Error -NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size) -{ - // FIXME put this behind a breakpoint protocol class that can be - // set per architecture. Need ARM, MIPS support here. - static const uint8_t g_i386_opcode [] = { 0xCC }; - static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; +Error NativeProcessLinux::GetSoftwareBreakpointPCOffset( + uint32_t &actual_opcode_size) { + // FIXME put this behind a breakpoint protocol class that can be + // set per architecture. Need ARM, MIPS support here. + static const uint8_t g_i386_opcode[] = {0xCC}; + static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; - switch (m_arch.GetMachine ()) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode)); - return Error (); - - case llvm::Triple::systemz: - actual_opcode_size = static_cast<uint32_t> (sizeof(g_s390x_opcode)); - return Error (); - - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::mips: - case llvm::Triple::mipsel: - // On these architectures the PC don't get updated for breakpoint hits - actual_opcode_size = 0; - return Error (); - - default: - assert(false && "CPU type not supported!"); - return Error ("CPU type not supported"); - } -} + switch (m_arch.GetMachine()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode)); + return Error(); -Error -NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) -{ - if (hardware) - return Error ("NativeProcessLinux does not support hardware breakpoints"); - else - return SetSoftwareBreakpoint (addr, size); -} + case llvm::Triple::systemz: + actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode)); + return Error(); -Error -NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, - size_t &actual_opcode_size, - const uint8_t *&trap_opcode_bytes) -{ - // FIXME put this behind a breakpoint protocol class that can be set per - // architecture. Need MIPS support here. - static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; - // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the - // linux kernel does otherwise. - static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; - static const uint8_t g_i386_opcode [] = { 0xCC }; - static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; - static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; - static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; - static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; - - switch (m_arch.GetMachine ()) - { - case llvm::Triple::aarch64: - trap_opcode_bytes = g_aarch64_opcode; - actual_opcode_size = sizeof(g_aarch64_opcode); - return Error (); - - case llvm::Triple::arm: - switch (trap_opcode_size_hint) - { - case 2: - trap_opcode_bytes = g_thumb_breakpoint_opcode; - actual_opcode_size = sizeof(g_thumb_breakpoint_opcode); - return Error (); - case 4: - trap_opcode_bytes = g_arm_breakpoint_opcode; - actual_opcode_size = sizeof(g_arm_breakpoint_opcode); - return Error (); - default: - assert(false && "Unrecognised trap opcode size hint!"); - return Error ("Unrecognised trap opcode size hint!"); - } + case llvm::Triple::arm: + case llvm::Triple::aarch64: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + // On these architectures the PC don't get updated for breakpoint hits + actual_opcode_size = 0; + return Error(); - case llvm::Triple::x86: - case llvm::Triple::x86_64: - trap_opcode_bytes = g_i386_opcode; - actual_opcode_size = sizeof(g_i386_opcode); - return Error (); - - case llvm::Triple::mips: - case llvm::Triple::mips64: - trap_opcode_bytes = g_mips64_opcode; - actual_opcode_size = sizeof(g_mips64_opcode); - return Error (); - - case llvm::Triple::mipsel: - case llvm::Triple::mips64el: - trap_opcode_bytes = g_mips64el_opcode; - actual_opcode_size = sizeof(g_mips64el_opcode); - return Error (); - - case llvm::Triple::systemz: - trap_opcode_bytes = g_s390x_opcode; - actual_opcode_size = sizeof(g_s390x_opcode); - return Error (); + default: + assert(false && "CPU type not supported!"); + return Error("CPU type not supported"); + } +} + +Error NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) { + if (hardware) + return Error("NativeProcessLinux does not support hardware breakpoints"); + else + return SetSoftwareBreakpoint(addr, size); +} + +Error NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( + size_t trap_opcode_size_hint, size_t &actual_opcode_size, + const uint8_t *&trap_opcode_bytes) { + // FIXME put this behind a breakpoint protocol class that can be set per + // architecture. Need MIPS support here. + static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; + // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the + // linux kernel does otherwise. + static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; + static const uint8_t g_i386_opcode[] = {0xCC}; + static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; + static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; + static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; + static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; + + switch (m_arch.GetMachine()) { + case llvm::Triple::aarch64: + trap_opcode_bytes = g_aarch64_opcode; + actual_opcode_size = sizeof(g_aarch64_opcode); + return Error(); + case llvm::Triple::arm: + switch (trap_opcode_size_hint) { + case 2: + trap_opcode_bytes = g_thumb_breakpoint_opcode; + actual_opcode_size = sizeof(g_thumb_breakpoint_opcode); + return Error(); + case 4: + trap_opcode_bytes = g_arm_breakpoint_opcode; + actual_opcode_size = sizeof(g_arm_breakpoint_opcode); + return Error(); default: - assert(false && "CPU type not supported!"); - return Error ("CPU type not supported"); + assert(false && "Unrecognised trap opcode size hint!"); + return Error("Unrecognised trap opcode size hint!"); } + + case llvm::Triple::x86: + case llvm::Triple::x86_64: + trap_opcode_bytes = g_i386_opcode; + actual_opcode_size = sizeof(g_i386_opcode); + return Error(); + + case llvm::Triple::mips: + case llvm::Triple::mips64: + trap_opcode_bytes = g_mips64_opcode; + actual_opcode_size = sizeof(g_mips64_opcode); + return Error(); + + case llvm::Triple::mipsel: + case llvm::Triple::mips64el: + trap_opcode_bytes = g_mips64el_opcode; + actual_opcode_size = sizeof(g_mips64el_opcode); + return Error(); + + case llvm::Triple::systemz: + trap_opcode_bytes = g_s390x_opcode; + actual_opcode_size = sizeof(g_s390x_opcode); + return Error(); + + default: + assert(false && "CPU type not supported!"); + return Error("CPU type not supported"); + } } #if 0 @@ -2012,7 +2009,6 @@ NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info) } #endif - #if 0 ProcessMessage::CrashReason NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info) @@ -2130,640 +2126,628 @@ NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info) } #endif -Error -NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) -{ - if (ProcessVmReadvSupported()) { - // The process_vm_readv path is about 50 times faster than ptrace api. We want to use - // this syscall if it is supported. - - const ::pid_t pid = GetID(); +Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) { + if (ProcessVmReadvSupported()) { + // The process_vm_readv path is about 50 times faster than ptrace api. We + // want to use + // this syscall if it is supported. - struct iovec local_iov, remote_iov; - local_iov.iov_base = buf; - local_iov.iov_len = size; - remote_iov.iov_base = reinterpret_cast<void *>(addr); - remote_iov.iov_len = size; + const ::pid_t pid = GetID(); - bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); - const bool success = bytes_read == size; + struct iovec local_iov, remote_iov; + local_iov.iov_base = buf; + local_iov.iov_len = size; + remote_iov.iov_base = reinterpret_cast<void *>(addr); + remote_iov.iov_len = size; - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessLinux::%s using process_vm_readv to read %zd bytes from inferior address 0x%" PRIx64": %s", - __FUNCTION__, size, addr, success ? "Success" : strerror(errno)); + bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); + const bool success = bytes_read == size; - if (success) - return Error(); - // else - // the call failed for some reason, let's retry the read using ptrace api. + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s using process_vm_readv to read %zd " + "bytes from inferior address 0x%" PRIx64 ": %s", + __FUNCTION__, size, addr, + success ? "Success" : strerror(errno)); + + if (success) + return Error(); + // else + // the call failed for some reason, let's retry the read using ptrace + // api. + } + + unsigned char *dst = static_cast<unsigned char *>(buf); + size_t remainder; + long data; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); + if (log) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && + log->GetMask().Test(POSIX_LOG_MEMORY)) + log->Printf("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, + (void *)addr, buf, size); + + for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { + Error error = NativeProcessLinux::PtraceWrapper( + PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data); + if (error.Fail()) { + if (log) + ProcessPOSIXLog::DecNestLevel(); + return error; } - unsigned char *dst = static_cast<unsigned char*>(buf); - size_t remainder; - long data; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf ("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, (void*)addr, buf, size); + remainder = size - bytes_read; + remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; - for (bytes_read = 0; bytes_read < size; bytes_read += remainder) - { - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, GetID(), (void*)addr, nullptr, 0, &data); - if (error.Fail()) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return error; - } + // Copy the data into our buffer + memcpy(dst, &data, remainder); - remainder = size - bytes_read; - remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; - - // Copy the data into our buffer - memcpy(dst, &data, remainder); - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - { - uintptr_t print_dst = 0; - // Format bytes from data by moving into print_dst for log output - for (unsigned i = 0; i < remainder; ++i) - print_dst |= (((data >> i*8) & 0xFF) << i*8); - log->Printf ("NativeProcessLinux::%s() [0x%" PRIx64 "]:0x%" PRIx64 " (0x%" PRIx64 ")", - __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data)); - } - addr += k_ptrace_word_size; - dst += k_ptrace_word_size; + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) { + uintptr_t print_dst = 0; + // Format bytes from data by moving into print_dst for log output + for (unsigned i = 0; i < remainder; ++i) + print_dst |= (((data >> i * 8) & 0xFF) << i * 8); + log->Printf("NativeProcessLinux::%s() [0x%" PRIx64 "]:0x%" PRIx64 + " (0x%" PRIx64 ")", + __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data)); } + addr += k_ptrace_word_size; + dst += k_ptrace_word_size; + } - if (log) - ProcessPOSIXLog::DecNestLevel(); - return Error(); + if (log) + ProcessPOSIXLog::DecNestLevel(); + return Error(); } -Error -NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) -{ - Error error = ReadMemory(addr, buf, size, bytes_read); - if (error.Fail()) return error; - return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); -} +Error NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, + size_t size, + size_t &bytes_read) { + Error error = ReadMemory(addr, buf, size, bytes_read); + if (error.Fail()) + return error; + return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); +} + +Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, + size_t size, size_t &bytes_written) { + const unsigned char *src = static_cast<const unsigned char *>(buf); + size_t remainder; + Error error; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); + if (log) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && + log->GetMask().Test(POSIX_LOG_MEMORY)) + log->Printf("NativeProcessLinux::%s(0x%" PRIx64 ", %p, %zu)", __FUNCTION__, + addr, buf, size); + + for (bytes_written = 0; bytes_written < size; bytes_written += remainder) { + remainder = size - bytes_written; + remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; + + if (remainder == k_ptrace_word_size) { + unsigned long data = 0; + memcpy(&data, src, k_ptrace_word_size); + + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) + log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, + (void *)addr, *(const unsigned long *)src, data); + + error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), + (void *)addr, (void *)data); + if (error.Fail()) { + if (log) + ProcessPOSIXLog::DecNestLevel(); + return error; + } + } else { + unsigned char buff[8]; + size_t bytes_read; + error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); + if (error.Fail()) { + if (log) + ProcessPOSIXLog::DecNestLevel(); + return error; + } -Error -NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) -{ - const unsigned char *src = static_cast<const unsigned char*>(buf); - size_t remainder; - Error error; + memcpy(buff, src, remainder); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf ("NativeProcessLinux::%s(0x%" PRIx64 ", %p, %zu)", __FUNCTION__, addr, buf, size); - - for (bytes_written = 0; bytes_written < size; bytes_written += remainder) - { - remainder = size - bytes_written; - remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; - - if (remainder == k_ptrace_word_size) - { - unsigned long data = 0; - memcpy(&data, src, k_ptrace_word_size); - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void*)addr, *(const unsigned long*)src, data); - - error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data); - if (error.Fail()) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return error; - } - } - else - { - unsigned char buff[8]; - size_t bytes_read; - error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); - if (error.Fail()) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return error; - } - - memcpy(buff, src, remainder); - - size_t bytes_written_rec; - error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); - if (error.Fail()) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return error; - } - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void*)addr, *(const unsigned long*)src, *(unsigned long*)buff); - } + size_t bytes_written_rec; + error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); + if (error.Fail()) { + if (log) + ProcessPOSIXLog::DecNestLevel(); + return error; + } - addr += k_ptrace_word_size; - src += k_ptrace_word_size; + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) + log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, + (void *)addr, *(const unsigned long *)src, + *(unsigned long *)buff); } - if (log) - ProcessPOSIXLog::DecNestLevel(); - return error; + + addr += k_ptrace_word_size; + src += k_ptrace_word_size; + } + if (log) + ProcessPOSIXLog::DecNestLevel(); + return error; } -Error -NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) -{ - return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); +Error NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) { + return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); } -Error -NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message) -{ - return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); +Error NativeProcessLinux::GetEventMessage(lldb::tid_t tid, + unsigned long *message) { + return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); } -Error -NativeProcessLinux::Detach(lldb::tid_t tid) -{ - if (tid == LLDB_INVALID_THREAD_ID) - return Error(); +Error NativeProcessLinux::Detach(lldb::tid_t tid) { + if (tid == LLDB_INVALID_THREAD_ID) + return Error(); - return PtraceWrapper(PTRACE_DETACH, tid); + return PtraceWrapper(PTRACE_DETACH, tid); } -bool -NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id) -{ - for (auto thread_sp : m_threads) - { - assert (thread_sp && "thread list should not contain NULL threads"); - if (thread_sp->GetID () == thread_id) - { - // We have this thread. - return true; - } +bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not contain NULL threads"); + if (thread_sp->GetID() == thread_id) { + // We have this thread. + return true; } + } - // We don't have this thread. - return false; + // We don't have this thread. + return false; } -bool -NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id) -{ - Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); +bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { + Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread_id); + if (log) + log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, + thread_id); - bool found = false; + bool found = false; - for (auto it = m_threads.begin (); it != m_threads.end (); ++it) - { - if (*it && ((*it)->GetID () == thread_id)) - { - m_threads.erase (it); - found = true; - break; - } + for (auto it = m_threads.begin(); it != m_threads.end(); ++it) { + if (*it && ((*it)->GetID() == thread_id)) { + m_threads.erase(it); + found = true; + break; } + } - SignalIfAllThreadsStopped(); + SignalIfAllThreadsStopped(); - return found; + return found; } -NativeThreadLinuxSP -NativeProcessLinux::AddThread (lldb::tid_t thread_id) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); +NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - { - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " adding thread with tid %" PRIu64, - __FUNCTION__, - GetID (), - thread_id); - } + if (log) { + log->Printf("NativeProcessLinux::%s pid %" PRIu64 + " adding thread with tid %" PRIu64, + __FUNCTION__, GetID(), thread_id); + } - assert (!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists"); + assert(!HasThreadNoLock(thread_id) && + "attempted to add a thread by id that already exists"); - // If this is the first thread, save it as the current thread - if (m_threads.empty ()) - SetCurrentThreadID (thread_id); + // If this is the first thread, save it as the current thread + if (m_threads.empty()) + SetCurrentThreadID(thread_id); - auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id); - m_threads.push_back (thread_sp); - return thread_sp; + auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id); + m_threads.push_back(thread_sp); + return thread_sp; } -Error -NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); +Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - Error error; + Error error; - // Find out the size of a breakpoint (might depend on where we are in the code). - NativeRegisterContextSP context_sp = thread.GetRegisterContext(); - if (!context_sp) - { - error.SetErrorString ("cannot get a NativeRegisterContext for the thread"); - if (log) - log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); - return error; - } - - uint32_t breakpoint_size = 0; - error = GetSoftwareBreakpointPCOffset(breakpoint_size); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeProcessLinux::%s GetBreakpointSize() failed: %s", __FUNCTION__, error.AsCString ()); - return error; - } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32, __FUNCTION__, breakpoint_size); - } - - // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size. - const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation (); - lldb::addr_t breakpoint_addr = initial_pc_addr; - if (breakpoint_size > 0) - { - // Do not allow breakpoint probe to wrap around. - if (breakpoint_addr >= breakpoint_size) - breakpoint_addr -= breakpoint_size; - } - - // Check if we stopped because of a breakpoint. - NativeBreakpointSP breakpoint_sp; - error = m_breakpoint_list.GetBreakpoint (breakpoint_addr, breakpoint_sp); - if (!error.Success () || !breakpoint_sp) - { - // We didn't find one at a software probe location. Nothing to do. - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64, __FUNCTION__, GetID (), breakpoint_addr); - return Error (); - } - - // If the breakpoint is not a software breakpoint, nothing to do. - if (!breakpoint_sp->IsSoftwareBreakpoint ()) - { - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", not software, nothing to adjust", __FUNCTION__, GetID (), breakpoint_addr); - return Error (); - } - - // - // We have a software breakpoint and need to adjust the PC. - // - - // Sanity check. - if (breakpoint_size == 0) - { - // Nothing to do! How did we get here? - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", it is software, but the size is zero, nothing to do (unexpected)", __FUNCTION__, GetID (), breakpoint_addr); - return Error (); - } - - // Change the program counter. + // Find out the size of a breakpoint (might depend on where we are in the + // code). + NativeRegisterContextSP context_sp = thread.GetRegisterContext(); + if (!context_sp) { + error.SetErrorString("cannot get a NativeRegisterContext for the thread"); if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64, __FUNCTION__, GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); - - error = context_sp->SetPC (breakpoint_addr); - if (error.Fail ()) - { - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": failed to set PC: %s", __FUNCTION__, GetID(), thread.GetID(), error.AsCString ()); - return error; - } - + log->Printf("NativeProcessLinux::%s failed: %s", __FUNCTION__, + error.AsCString()); return error; -} + } -Error -NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) -{ - FileSpec module_file_spec(module_path, true); - - bool found = false; - file_spec.Clear(); - ProcFileReader::ProcessLineByLine(GetID(), "maps", - [&] (const std::string &line) - { - SmallVector<StringRef, 16> columns; - StringRef(line).split(columns, " ", -1, false); - if (columns.size() < 6) - return true; // continue searching - - FileSpec this_file_spec(columns[5].str().c_str(), false); - if (this_file_spec.GetFilename() != module_file_spec.GetFilename()) - return true; // continue searching - - file_spec = this_file_spec; - found = true; - return false; // we are done - }); - - if (! found) - return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", - module_file_spec.GetFilename().AsCString(), GetID()); + uint32_t breakpoint_size = 0; + error = GetSoftwareBreakpointPCOffset(breakpoint_size); + if (error.Fail()) { + if (log) + log->Printf("NativeProcessLinux::%s GetBreakpointSize() failed: %s", + __FUNCTION__, error.AsCString()); + return error; + } else { + if (log) + log->Printf("NativeProcessLinux::%s breakpoint size: %" PRIu32, + __FUNCTION__, breakpoint_size); + } + + // First try probing for a breakpoint at a software breakpoint location: PC - + // breakpoint size. + const lldb::addr_t initial_pc_addr = + context_sp->GetPCfromBreakpointLocation(); + lldb::addr_t breakpoint_addr = initial_pc_addr; + if (breakpoint_size > 0) { + // Do not allow breakpoint probe to wrap around. + if (breakpoint_addr >= breakpoint_size) + breakpoint_addr -= breakpoint_size; + } + + // Check if we stopped because of a breakpoint. + NativeBreakpointSP breakpoint_sp; + error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); + if (!error.Success() || !breakpoint_sp) { + // We didn't find one at a software probe location. Nothing to do. + if (log) + log->Printf( + "NativeProcessLinux::%s pid %" PRIu64 + " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64, + __FUNCTION__, GetID(), breakpoint_addr); + return Error(); + } + // If the breakpoint is not a software breakpoint, nothing to do. + if (!breakpoint_sp->IsSoftwareBreakpoint()) { + if (log) + log->Printf("NativeProcessLinux::%s pid %" PRIu64 + " breakpoint found at 0x%" PRIx64 + ", not software, nothing to adjust", + __FUNCTION__, GetID(), breakpoint_addr); return Error(); -} + } -Error -NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) -{ - load_addr = LLDB_INVALID_ADDRESS; - Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps", - [&] (const std::string &line) -> bool - { - StringRef maps_row(line); - - SmallVector<StringRef, 16> maps_columns; - maps_row.split(maps_columns, StringRef(" "), -1, false); - - if (maps_columns.size() < 6) - { - // Return true to continue reading the proc file - return true; - } - - if (maps_columns[5] == file_name) - { - StringExtractor addr_extractor(maps_columns[0].str().c_str()); - load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - - // Return false to stop reading the proc file further - return false; - } - - // Return true to continue reading the proc file - return true; - }); - return error; -} + // + // We have a software breakpoint and need to adjust the PC. + // -NativeThreadLinuxSP -NativeProcessLinux::GetThreadByID(lldb::tid_t tid) -{ - return std::static_pointer_cast<NativeThreadLinux>(NativeProcessProtocol::GetThreadByID(tid)); -} + // Sanity check. + if (breakpoint_size == 0) { + // Nothing to do! How did we get here? + if (log) + log->Printf( + "NativeProcessLinux::%s pid %" PRIu64 + " breakpoint found at 0x%" PRIx64 + ", it is software, but the size is zero, nothing to do (unexpected)", + __FUNCTION__, GetID(), breakpoint_addr); + return Error(); + } -Error -NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo) -{ - Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); + // Change the program counter. + if (log) + log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 + ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64, + __FUNCTION__, GetID(), thread.GetID(), initial_pc_addr, + breakpoint_addr); + error = context_sp->SetPC(breakpoint_addr); + if (error.Fail()) { if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", - __FUNCTION__, thread.GetID()); - - // Before we do the resume below, first check if we have a pending - // stop notification that is currently waiting for - // all threads to stop. This is potentially a buggy situation since - // we're ostensibly waiting for threads to stop before we send out the - // pending notification, and here we are resuming one before we send - // out the pending stop notification. - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && log) - { - log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, thread.GetID(), m_pending_notification_tid); - } + log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 + ": failed to set PC: %s", + __FUNCTION__, GetID(), thread.GetID(), error.AsCString()); + return error; + } - // Request a resume. We expect this to be synchronous and the system - // to reflect it is running after this completes. - switch (state) - { - case eStateRunning: - { - const auto resume_result = thread.Resume(signo); - if (resume_result.Success()) - SetState(eStateRunning, true); - return resume_result; - } - case eStateStepping: - { - const auto step_result = thread.SingleStep(signo); - if (step_result.Success()) - SetState(eStateRunning, true); - return step_result; - } - default: - if (log) - log->Printf("NativeProcessLinux::%s Unhandled state %s.", - __FUNCTION__, StateAsCString(state)); - llvm_unreachable("Unhandled state for resume"); - } + return error; } -//===----------------------------------------------------------------------===// +Error NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) { + FileSpec module_file_spec(module_path, true); -void -NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) -{ - Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); + bool found = false; + file_spec.Clear(); + ProcFileReader::ProcessLineByLine( + GetID(), "maps", [&](const std::string &line) { + SmallVector<StringRef, 16> columns; + StringRef(line).split(columns, " ", -1, false); + if (columns.size() < 6) + return true; // continue searching - if (log) - { - log->Printf("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ")", - __FUNCTION__, triggering_tid); - } - - m_pending_notification_tid = triggering_tid; + FileSpec this_file_spec(columns[5].str().c_str(), false); + if (this_file_spec.GetFilename() != module_file_spec.GetFilename()) + return true; // continue searching - // Request a stop for all the thread stops that need to be stopped - // and are not already known to be stopped. - for (const auto &thread_sp: m_threads) - { - if (StateIsRunningState(thread_sp->GetState())) - static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); - } + file_spec = this_file_spec; + found = true; + return false; // we are done + }); - SignalIfAllThreadsStopped(); + if (!found) + return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", + module_file_spec.GetFilename().AsCString(), GetID()); - if (log) - { - log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__); - } + return Error(); } -void -NativeProcessLinux::SignalIfAllThreadsStopped() -{ - if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) - return; // No pending notification. Nothing to do. +Error NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) { + load_addr = LLDB_INVALID_ADDRESS; + Error error = ProcFileReader::ProcessLineByLine( + GetID(), "maps", [&](const std::string &line) -> bool { + StringRef maps_row(line); - for (const auto &thread_sp: m_threads) - { - if (StateIsRunningState(thread_sp->GetState())) - return; // Some threads are still running. Don't signal yet. - } - - // We have a pending notification and all threads have stopped. - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); + SmallVector<StringRef, 16> maps_columns; + maps_row.split(maps_columns, StringRef(" "), -1, false); - // Clear any temporary breakpoints we used to implement software single stepping. - for (const auto &thread_info: m_threads_stepping_with_breakpoint) - { - Error error = RemoveBreakpoint (thread_info.second); - if (error.Fail()) - if (log) - log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " remove stepping breakpoint: %s", - __FUNCTION__, thread_info.first, error.AsCString()); - } - m_threads_stepping_with_breakpoint.clear(); + if (maps_columns.size() < 6) { + // Return true to continue reading the proc file + return true; + } - // Notify the delegate about the stop - SetCurrentThreadID(m_pending_notification_tid); - SetState(StateType::eStateStopped, true); - m_pending_notification_tid = LLDB_INVALID_THREAD_ID; -} + if (maps_columns[5] == file_name) { + StringExtractor addr_extractor(maps_columns[0].str().c_str()); + load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); -void -NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) -{ - Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); + // Return false to stop reading the proc file further + return false; + } + // Return true to continue reading the proc file + return true; + }); + return error; +} + +NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { + return std::static_pointer_cast<NativeThreadLinux>( + NativeProcessProtocol::GetThreadByID(tid)); +} + +Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, + lldb::StateType state, int signo) { + Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); + + if (log) + log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, + thread.GetID()); + + // Before we do the resume below, first check if we have a pending + // stop notification that is currently waiting for + // all threads to stop. This is potentially a buggy situation since + // we're ostensibly waiting for threads to stop before we send out the + // pending notification, and here we are resuming one before we send + // out the pending stop notification. + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && log) { + log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64 + " per explicit request but we have a pending stop notification " + "(tid %" PRIu64 ") that is actively waiting for this thread to " + "stop. Valid sequence of events?", + __FUNCTION__, thread.GetID(), m_pending_notification_tid); + } + + // Request a resume. We expect this to be synchronous and the system + // to reflect it is running after this completes. + switch (state) { + case eStateRunning: { + const auto resume_result = thread.Resume(signo); + if (resume_result.Success()) + SetState(eStateRunning, true); + return resume_result; + } + case eStateStepping: { + const auto step_result = thread.SingleStep(signo); + if (step_result.Success()) + SetState(eStateRunning, true); + return step_result; + } + default: if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread.GetID()); - - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && StateIsRunningState(thread.GetState())) - { - // We will need to wait for this new thread to stop as well before firing the - // notification. - thread.RequestStop(); - } + log->Printf("NativeProcessLinux::%s Unhandled state %s.", __FUNCTION__, + StateAsCString(state)); + llvm_unreachable("Unhandled state for resume"); + } } -void -NativeProcessLinux::SigchldHandler() -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Process all pending waitpid notifications. - while (true) - { - int status = -1; - ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); +//===----------------------------------------------------------------------===// - if (wait_pid == 0) - break; // We are done. +void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { + Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - if (wait_pid == -1) - { - if (errno == EINTR) - continue; + if (log) { + log->Printf("NativeProcessLinux::%s about to process event: " + "(triggering_tid: %" PRIu64 ")", + __FUNCTION__, triggering_tid); + } - Error error(errno, eErrorTypePOSIX); - if (log) - log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s", - __FUNCTION__, error.AsCString()); - break; - } + m_pending_notification_tid = triggering_tid; - bool exited = false; - int signal = 0; - int exit_status = 0; - const char *status_cstr = nullptr; - if (WIFSTOPPED(status)) - { - signal = WSTOPSIG(status); - status_cstr = "STOPPED"; - } - else if (WIFEXITED(status)) - { - exit_status = WEXITSTATUS(status); - status_cstr = "EXITED"; - exited = true; - } - else if (WIFSIGNALED(status)) - { - signal = WTERMSIG(status); - status_cstr = "SIGNALED"; - if (wait_pid == static_cast< ::pid_t>(GetID())) { - exited = true; - exit_status = -1; - } - } - else - status_cstr = "(\?\?\?)"; + // Request a stop for all the thread stops that need to be stopped + // and are not already known to be stopped. + for (const auto &thread_sp : m_threads) { + if (StateIsRunningState(thread_sp->GetState())) + static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); + } - if (log) - log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)" - "=> pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", - __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status); + SignalIfAllThreadsStopped(); - MonitorCallback (wait_pid, exited, signal, exit_status); - } + if (log) { + log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__); + } } -// Wrapper for ptrace to catch errors and log calls. -// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) -Error -NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result) -{ - Error error; - long int ret; +void NativeProcessLinux::SignalIfAllThreadsStopped() { + if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) + return; // No pending notification. Nothing to do. - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); + for (const auto &thread_sp : m_threads) { + if (StateIsRunningState(thread_sp->GetState())) + return; // Some threads are still running. Don't signal yet. + } - PtraceDisplayBytes(req, data, data_size); + // We have a pending notification and all threads have stopped. + Log *log( + GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); - else - ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); + // Clear any temporary breakpoints we used to implement software single + // stepping. + for (const auto &thread_info : m_threads_stepping_with_breakpoint) { + Error error = RemoveBreakpoint(thread_info.second); + if (error.Fail()) + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 + " remove stepping breakpoint: %s", + __FUNCTION__, thread_info.first, error.AsCString()); + } + m_threads_stepping_with_breakpoint.clear(); + + // Notify the delegate about the stop + SetCurrentThreadID(m_pending_notification_tid); + SetState(StateType::eStateStopped, true); + m_pending_notification_tid = LLDB_INVALID_THREAD_ID; +} + +void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) { + Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); + + if (log) + log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, + thread.GetID()); + + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && + StateIsRunningState(thread.GetState())) { + // We will need to wait for this new thread to stop as well before firing + // the + // notification. + thread.RequestStop(); + } +} + +void NativeProcessLinux::SigchldHandler() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Process all pending waitpid notifications. + while (true) { + int status = -1; + ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); - if (ret == -1) - error.SetErrorToErrno(); + if (wait_pid == 0) + break; // We are done. - if (result) - *result = ret; + if (wait_pid == -1) { + if (errno == EINTR) + continue; + + Error error(errno, eErrorTypePOSIX); + if (log) + log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | " + "__WNOTHREAD | WNOHANG) failed: %s", + __FUNCTION__, error.AsCString()); + break; + } + + bool exited = false; + int signal = 0; + int exit_status = 0; + const char *status_cstr = nullptr; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + status_cstr = "STOPPED"; + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + status_cstr = "EXITED"; + exited = true; + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + status_cstr = "SIGNALED"; + if (wait_pid == static_cast<::pid_t>(GetID())) { + exited = true; + exit_status = -1; + } + } else + status_cstr = "(\?\?\?)"; if (log) - log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, ret); + log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | " + "__WNOTHREAD | WNOHANG)" + "=> pid = %" PRIi32 + ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", + __FUNCTION__, wait_pid, status, status_cstr, signal, + exit_status); - PtraceDisplayBytes(req, data, data_size); + MonitorCallback(wait_pid, exited, signal, exit_status); + } +} - if (log && error.GetError() != 0) - { - const char* str; - switch (error.GetError()) - { - case ESRCH: str = "ESRCH"; break; - case EINVAL: str = "EINVAL"; break; - case EBUSY: str = "EBUSY"; break; - case EPERM: str = "EPERM"; break; - default: str = error.AsCString(); - } - log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); +// Wrapper for ptrace to catch errors and log calls. +// Note that ptrace sets errno on error because -1 can be a valid result (i.e. +// for PTRACE_PEEK*) +Error NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, + void *data, size_t data_size, + long *result) { + Error error; + long int ret; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + + PtraceDisplayBytes(req, data, data_size); + + errno = 0; + if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) + ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), + *(unsigned int *)addr, data); + else + ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), + addr, data); + + if (ret == -1) + error.SetErrorToErrno(); + + if (result) + *result = ret; + + if (log) + log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, + data, data_size, ret); + + PtraceDisplayBytes(req, data, data_size); + + if (log && error.GetError() != 0) { + const char *str; + switch (error.GetError()) { + case ESRCH: + str = "ESRCH"; + break; + case EINVAL: + str = "EINVAL"; + break; + case EBUSY: + str = "EBUSY"; + break; + case EPERM: + str = "EPERM"; + break; + default: + str = error.AsCString(); } + log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); + } - return error; + return error; } diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index 7b1fcd81b4b..fcb13c8b016 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -15,186 +15,151 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" -#include "lldb/lldb-types.h" #include "lldb/Host/Debug.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/lldb-types.h" -#include "lldb/Host/common/NativeProcessProtocol.h" #include "NativeThreadLinux.h" +#include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { - class Error; - class Scalar; +class Error; +class Scalar; namespace process_linux { - /// @class NativeProcessLinux - /// @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 NativeProcessLinux: public NativeProcessProtocol - { - friend Error - NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp); +/// @class NativeProcessLinux +/// @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 NativeProcessLinux : 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); + friend Error NativeProcessProtocol::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp); - public: - // --------------------------------------------------------------------- - // NativeProcessProtocol Interface - // --------------------------------------------------------------------- - Error - Resume (const ResumeActionList &resume_actions) override; +public: + // --------------------------------------------------------------------- + // NativeProcessProtocol Interface + // --------------------------------------------------------------------- + Error Resume(const ResumeActionList &resume_actions) override; - Error - Halt () override; + Error Halt() override; - Error - Detach () override; + Error Detach() override; - Error - Signal (int signo) override; + Error Signal(int signo) override; - Error - Interrupt () override; + Error Interrupt() override; - Error - Kill () override; + Error Kill() override; - Error - GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) 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 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 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 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 AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) override; - Error - DeallocateMemory (lldb::addr_t addr) override; + Error DeallocateMemory(lldb::addr_t addr) override; - lldb::addr_t - GetSharedLibraryInfoAddress () override; + lldb::addr_t GetSharedLibraryInfoAddress() override; - size_t - UpdateThreads () override; + size_t UpdateThreads() override; - bool - GetArchitecture (ArchSpec &arch) const override; + bool GetArchitecture(ArchSpec &arch) const override; - Error - SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override; + Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; - void - DoStopIDBumped (uint32_t newBumpId) override; + void DoStopIDBumped(uint32_t newBumpId) override; - Error - GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override; + Error GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) override; - Error - GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) override; + Error GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) override; - NativeThreadLinuxSP - GetThreadByID(lldb::tid_t id); + NativeThreadLinuxSP GetThreadByID(lldb::tid_t id); - // --------------------------------------------------------------------- - // 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); + // --------------------------------------------------------------------- + // 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 - SupportHardwareSingleStepping() const; + bool SupportHardwareSingleStepping() const; - protected: - // --------------------------------------------------------------------- - // NativeProcessProtocol protected interface - // --------------------------------------------------------------------- - Error - GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) 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; - private: +private: + MainLoop::SignalHandleUP m_sigchld_handle; + ArchSpec m_arch; - MainLoop::SignalHandleUP m_sigchld_handle; - ArchSpec m_arch; + LazyBool m_supports_mem_region; + std::vector<MemoryRegionInfo> m_mem_region_cache; - LazyBool m_supports_mem_region; - std::vector<MemoryRegionInfo> m_mem_region_cache; + lldb::tid_t m_pending_notification_tid; - lldb::tid_t m_pending_notification_tid; + // List of thread ids stepping with a breakpoint with the address of + // the relevan breakpoint + std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint; - // List of thread ids stepping with a breakpoint with the address of - // the relevan breakpoint - std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint; + // --------------------------------------------------------------------- + // Private Instance Methods + // --------------------------------------------------------------------- + NativeProcessLinux(); + Error LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - // --------------------------------------------------------------------- - // Private Instance Methods - // --------------------------------------------------------------------- - NativeProcessLinux (); + /// Attaches to an existing process. Forms the + /// implementation of Process::DoAttach + void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error); - Error - LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); + ::pid_t Attach(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); + static Error SetDefaultPtraceOpts(const lldb::pid_t); - ::pid_t - Attach(lldb::pid_t pid, Error &error); + static void *MonitorThread(void *baton); - static Error - SetDefaultPtraceOpts(const lldb::pid_t); + void MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status); - static void * - MonitorThread(void *baton); + void WaitForNewThread(::pid_t tid); - void - MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status); + void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread); - void - WaitForNewThread(::pid_t tid); + void MonitorTrace(NativeThreadLinux &thread); - void - MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread); + void MonitorBreakpoint(NativeThreadLinux &thread); - void - MonitorTrace(NativeThreadLinux &thread); + void MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index); - void - MonitorBreakpoint(NativeThreadLinux &thread); + void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, + bool exited); - void - MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index); - - void - MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited); - - Error - SetupSoftwareSingleStepping(NativeThreadLinux &thread); + Error SetupSoftwareSingleStepping(NativeThreadLinux &thread); #if 0 static ::ProcessMessage::CrashReason @@ -210,59 +175,49 @@ namespace process_linux { GetCrashReasonForSIGBUS(const siginfo_t *info); #endif - bool - HasThreadNoLock (lldb::tid_t thread_id); - - bool - StopTrackingThread (lldb::tid_t thread_id); + bool HasThreadNoLock(lldb::tid_t thread_id); - NativeThreadLinuxSP - AddThread (lldb::tid_t thread_id); + bool StopTrackingThread(lldb::tid_t thread_id); - Error - GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); + NativeThreadLinuxSP AddThread(lldb::tid_t thread_id); - Error - FixupBreakpointPCAsNeeded(NativeThreadLinux &thread); + Error GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); - /// 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); + Error FixupBreakpointPCAsNeeded(NativeThreadLinux &thread); - /// 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); + /// 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); - void - NotifyThreadDeath (lldb::tid_t tid); + /// 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); - Error - Detach(lldb::tid_t tid); + 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); + // 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(); + // 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(NativeThreadLinux &thread, lldb::StateType state, int signo); + // 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(NativeThreadLinux &thread, lldb::StateType state, + int signo); - void - ThreadWasCreated(NativeThreadLinux &thread); + void ThreadWasCreated(NativeThreadLinux &thread); - void - SigchldHandler(); - }; + void SigchldHandler(); +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp index df0a008ff5f..a59a288c934 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -19,212 +19,195 @@ using namespace lldb_private; using namespace lldb_private::process_linux; -NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p) -{} - -lldb::ByteOrder -NativeRegisterContextLinux::GetByteOrder() const -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return byte_order; - - if (!process_sp->GetByteOrder (byte_order)) - { - // FIXME log here - } - +NativeRegisterContextLinux::NativeRegisterContextLinux( + NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p) + : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, + reg_info_interface_p) {} + +lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; + + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (!process_sp) return byte_order; -} -Error -NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value) -{ - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - return Error("register %" PRIu32 " not found", reg_index); + if (!process_sp->GetByteOrder(byte_order)) { + // FIXME log here + } - return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value); + return byte_order; } -Error -NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue ®_value) -{ - uint32_t reg_to_write = reg_index; - RegisterValue value_to_write = reg_value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - Error error; - - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail ()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } +Error NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, + RegisterValue ®_value) { + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) + return Error("register %" PRIu32 " not found", reg_index); - const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); - assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); - if (!register_to_write_info_p) - return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); + return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, + reg_info->byte_size, reg_value); +} - return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value); +Error NativeRegisterContextLinux::WriteRegisterRaw( + uint32_t reg_index, const RegisterValue ®_value) { + uint32_t reg_to_write = reg_index; + RegisterValue value_to_write = reg_value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + Error error; + + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + error = ReadRegister(full_reg_info, full_value); + if (error.Fail()) + return error; + + lldb::ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = reg_value.GetAsMemoryData( + reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; + } + } + } + + const RegisterInfo *const register_to_write_info_p = + GetRegisterInfoAtIndex(reg_to_write); + assert(register_to_write_info_p && + "register to write does not have valid RegisterInfo"); + if (!register_to_write_info_p) + return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo " + "for write register index %" PRIu32, + __FUNCTION__, reg_to_write); + + return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value); } -Error -NativeRegisterContextLinux::ReadGPR() -{ - void* buf = GetGPRBuffer(); - if (!buf) - return Error("GPR buffer is NULL"); - size_t buf_size = GetGPRSize(); +Error NativeRegisterContextLinux::ReadGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Error("GPR buffer is NULL"); + size_t buf_size = GetGPRSize(); - return DoReadGPR(buf, buf_size); + return DoReadGPR(buf, buf_size); } -Error -NativeRegisterContextLinux::WriteGPR() -{ - void* buf = GetGPRBuffer(); - if (!buf) - return Error("GPR buffer is NULL"); - size_t buf_size = GetGPRSize(); +Error NativeRegisterContextLinux::WriteGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Error("GPR buffer is NULL"); + size_t buf_size = GetGPRSize(); - return DoWriteGPR(buf, buf_size); + return DoWriteGPR(buf, buf_size); } -Error -NativeRegisterContextLinux::ReadFPR() -{ - void* buf = GetFPRBuffer(); - if (!buf) - return Error("FPR buffer is NULL"); - size_t buf_size = GetFPRSize(); +Error NativeRegisterContextLinux::ReadFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + size_t buf_size = GetFPRSize(); - return DoReadFPR(buf, buf_size); + return DoReadFPR(buf, buf_size); } -Error -NativeRegisterContextLinux::WriteFPR() -{ - void* buf = GetFPRBuffer(); - if (!buf) - return Error("FPR buffer is NULL"); - size_t buf_size = GetFPRSize(); +Error NativeRegisterContextLinux::WriteFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + size_t buf_size = GetFPRSize(); - return DoWriteFPR(buf, buf_size); + return DoWriteFPR(buf, buf_size); } -Error -NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), - static_cast<void *>(®set), buf, buf_size); +Error NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, + unsigned int regset) { + return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), + static_cast<void *>(®set), buf, + buf_size); } -Error -NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), - static_cast<void *>(®set), buf, buf_size); +Error NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, + unsigned int regset) { + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), + static_cast<void *>(®set), buf, + buf_size); } -Error -NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); +Error NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset, + const char *reg_name, + uint32_t size, + RegisterValue &value) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); - long data; - Error error = NativeProcessLinux::PtraceWrapper( - PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), nullptr, 0, &data); + long data; + Error error = NativeProcessLinux::PtraceWrapper( + PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), + nullptr, 0, &data); - if (error.Success()) - // First cast to an unsigned of the same size to avoid sign extension. - value.SetUInt64(static_cast<unsigned long>(data)); + if (error.Success()) + // First cast to an unsigned of the same size to avoid sign extension. + value.SetUInt64(static_cast<unsigned long>(data)); - if (log) - log->Printf ("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, reg_name, data); + if (log) + log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, + reg_name, data); - return error; + return error; } -Error -NativeRegisterContextLinux::DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); +Error NativeRegisterContextLinux::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); - void* buf = reinterpret_cast<void *>(value.GetAsUInt64()); + void *buf = reinterpret_cast<void *>(value.GetAsUInt64()); - if (log) - log->Printf ("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, reg_name, buf); + if (log) + log->Printf("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, + reg_name, buf); - return NativeProcessLinux::PtraceWrapper( - PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf); + return NativeProcessLinux::PtraceWrapper( + PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf); } -Error -NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), nullptr, buf, buf_size); +Error NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size) { + return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), + nullptr, buf, buf_size); } -Error -NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), nullptr, buf, buf_size); +Error NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size) { + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), + nullptr, buf, buf_size); } -Error -NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), nullptr, buf, buf_size); +Error NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size) { + return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), + nullptr, buf, buf_size); } -Error -NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), nullptr, buf, buf_size); +Error NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size) { + return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), + nullptr, buf, buf_size); } diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h index 0b0b747984b..a16c65b64a0 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -18,87 +18,72 @@ namespace lldb_private { namespace process_linux { -class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo -{ +class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo { public: - NativeRegisterContextLinux(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p); - - // This function is implemented in the NativeRegisterContextLinux_* subclasses to create a new - // instance of the host specific NativeRegisterContextLinux. The implementations can't collide - // as only one NativeRegisterContextLinux_* variant should be compiled into the final - // executable. - static NativeRegisterContextLinux* - CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p); + + // This function is implemented in the NativeRegisterContextLinux_* subclasses + // to create a new + // instance of the host specific NativeRegisterContextLinux. The + // implementations can't collide + // as only one NativeRegisterContextLinux_* variant should be compiled into + // the final + // executable. + static NativeRegisterContextLinux * + CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); protected: - lldb::ByteOrder - GetByteOrder() const; + lldb::ByteOrder GetByteOrder() const; - virtual Error - ReadRegisterRaw(uint32_t reg_index, RegisterValue& reg_value); + virtual Error ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value); - virtual Error - WriteRegisterRaw(uint32_t reg_index, const RegisterValue& reg_value); + virtual Error WriteRegisterRaw(uint32_t reg_index, + const RegisterValue ®_value); - virtual Error - ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset); + virtual Error ReadRegisterSet(void *buf, size_t buf_size, + unsigned int regset); - virtual Error - WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset); + virtual Error WriteRegisterSet(void *buf, size_t buf_size, + unsigned int regset); - virtual Error - ReadGPR(); + virtual Error ReadGPR(); - virtual Error - WriteGPR(); + virtual Error WriteGPR(); - virtual Error - ReadFPR(); + virtual Error ReadFPR(); - virtual Error - WriteFPR(); + virtual Error WriteFPR(); - virtual void* - GetGPRBuffer() { return nullptr; } + virtual void *GetGPRBuffer() { return nullptr; } - virtual size_t - GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); } + virtual size_t GetGPRSize() { + return GetRegisterInfoInterface().GetGPRSize(); + } - virtual void* - GetFPRBuffer() { return nullptr; } + virtual void *GetFPRBuffer() { return nullptr; } - virtual size_t - GetFPRSize() { return 0; } + virtual size_t GetFPRSize() { return 0; } + // The Do*** functions are executed on the privileged thread and can perform + // ptrace + // operations directly. + virtual Error DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value); - // The Do*** functions are executed on the privileged thread and can perform ptrace - // operations directly. - virtual Error - DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value); + virtual Error DoWriteRegisterValue(uint32_t offset, const char *reg_name, + const RegisterValue &value); - virtual Error - DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value); + virtual Error DoReadGPR(void *buf, size_t buf_size); - virtual Error - DoReadGPR(void *buf, size_t buf_size); + virtual Error DoWriteGPR(void *buf, size_t buf_size); - virtual Error - DoWriteGPR(void *buf, size_t buf_size); + virtual Error DoReadFPR(void *buf, size_t buf_size); - virtual Error - DoReadFPR(void *buf, size_t buf_size); - - virtual Error - DoWriteFPR(void *buf, size_t buf_size); + virtual Error DoWriteFPR(void *buf, size_t buf_size); }; } // namespace process_linux diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 5dfbaff9089..758d5e75aa5 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -22,21 +22,21 @@ #include <elf.h> #include <sys/socket.h> -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) +#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr)) #ifndef PTRACE_GETVFPREGS - #define PTRACE_GETVFPREGS 27 - #define PTRACE_SETVFPREGS 28 +#define PTRACE_GETVFPREGS 27 +#define PTRACE_SETVFPREGS 28 #endif #ifndef PTRACE_GETHBPREGS - #define PTRACE_GETHBPREGS 29 - #define PTRACE_SETHBPREGS 30 +#define PTRACE_GETHBPREGS 29 +#define PTRACE_SETHBPREGS 30 #endif #if !defined(PTRACE_TYPE_ARG3) - #define PTRACE_TYPE_ARG3 void * +#define PTRACE_TYPE_ARG3 void * #endif #if !defined(PTRACE_TYPE_ARG4) - #define PTRACE_TYPE_ARG4 void * +#define PTRACE_TYPE_ARG4 void * #endif using namespace lldb; @@ -44,1084 +44,933 @@ using namespace lldb_private; using namespace lldb_private::process_linux; // arm general purpose registers. -static const uint32_t g_gpr_regnums_arm[] = -{ - gpr_r0_arm, - gpr_r1_arm, - gpr_r2_arm, - gpr_r3_arm, - gpr_r4_arm, - gpr_r5_arm, - gpr_r6_arm, - gpr_r7_arm, - gpr_r8_arm, - gpr_r9_arm, - gpr_r10_arm, - gpr_r11_arm, - gpr_r12_arm, - gpr_sp_arm, - gpr_lr_arm, - gpr_pc_arm, - gpr_cpsr_arm, +static const uint32_t g_gpr_regnums_arm[] = { + gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm, + gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm, + gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm, + gpr_pc_arm, gpr_cpsr_arm, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \ +static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == + k_num_gpr_registers_arm, "g_gpr_regnums_arm has wrong number of register infos"); // arm floating point registers. -static const uint32_t g_fpu_regnums_arm[] = -{ - fpu_s0_arm, - fpu_s1_arm, - fpu_s2_arm, - fpu_s3_arm, - fpu_s4_arm, - fpu_s5_arm, - fpu_s6_arm, - fpu_s7_arm, - fpu_s8_arm, - fpu_s9_arm, - fpu_s10_arm, - fpu_s11_arm, - fpu_s12_arm, - fpu_s13_arm, - fpu_s14_arm, - fpu_s15_arm, - fpu_s16_arm, - fpu_s17_arm, - fpu_s18_arm, - fpu_s19_arm, - fpu_s20_arm, - fpu_s21_arm, - fpu_s22_arm, - fpu_s23_arm, - fpu_s24_arm, - fpu_s25_arm, - fpu_s26_arm, - fpu_s27_arm, - fpu_s28_arm, - fpu_s29_arm, - fpu_s30_arm, - fpu_s31_arm, - fpu_fpscr_arm, - fpu_d0_arm, - fpu_d1_arm, - fpu_d2_arm, - fpu_d3_arm, - fpu_d4_arm, - fpu_d5_arm, - fpu_d6_arm, - fpu_d7_arm, - fpu_d8_arm, - fpu_d9_arm, - fpu_d10_arm, - fpu_d11_arm, - fpu_d12_arm, - fpu_d13_arm, - fpu_d14_arm, - fpu_d15_arm, - fpu_d16_arm, - fpu_d17_arm, - fpu_d18_arm, - fpu_d19_arm, - fpu_d20_arm, - fpu_d21_arm, - fpu_d22_arm, - fpu_d23_arm, - fpu_d24_arm, - fpu_d25_arm, - fpu_d26_arm, - fpu_d27_arm, - fpu_d28_arm, - fpu_d29_arm, - fpu_d30_arm, - fpu_d31_arm, - fpu_q0_arm, - fpu_q1_arm, - fpu_q2_arm, - fpu_q3_arm, - fpu_q4_arm, - fpu_q5_arm, - fpu_q6_arm, - fpu_q7_arm, - fpu_q8_arm, - fpu_q9_arm, - fpu_q10_arm, - fpu_q11_arm, - fpu_q12_arm, - fpu_q13_arm, - fpu_q14_arm, +static const uint32_t g_fpu_regnums_arm[] = { + fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm, + fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm, + fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm, + fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm, + fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm, + fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm, + fpu_s30_arm, fpu_s31_arm, fpu_fpscr_arm, fpu_d0_arm, fpu_d1_arm, + fpu_d2_arm, fpu_d3_arm, fpu_d4_arm, fpu_d5_arm, fpu_d6_arm, + fpu_d7_arm, fpu_d8_arm, fpu_d9_arm, fpu_d10_arm, fpu_d11_arm, + fpu_d12_arm, fpu_d13_arm, fpu_d14_arm, fpu_d15_arm, fpu_d16_arm, + fpu_d17_arm, fpu_d18_arm, fpu_d19_arm, fpu_d20_arm, fpu_d21_arm, + fpu_d22_arm, fpu_d23_arm, fpu_d24_arm, fpu_d25_arm, fpu_d26_arm, + fpu_d27_arm, fpu_d28_arm, fpu_d29_arm, fpu_d30_arm, fpu_d31_arm, + fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm, + fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm, + fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm, fpu_q15_arm, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \ +static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == + k_num_fpr_registers_arm, "g_fpu_regnums_arm has wrong number of register infos"); namespace { - // Number of register sets provided by this context. - enum - { - k_num_register_sets = 2 - }; +// Number of register sets provided by this context. +enum { k_num_register_sets = 2 }; } // Register sets for arm. -static const RegisterSet -g_reg_sets_arm[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm } -}; +static const RegisterSet g_reg_sets_arm[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_arm, + g_gpr_regnums_arm}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_arm, + g_fpu_regnums_arm}}; #if defined(__arm__) -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextLinux_arm(target_arch, native_thread, + concrete_frame_idx); } #endif // defined(__arm__) -NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch)) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - m_reg_info.num_registers = k_num_registers_arm; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; - m_reg_info.last_gpr = k_last_gpr_arm; - m_reg_info.first_fpr = k_first_fpr_arm; - m_reg_info.last_fpr = k_last_fpr_arm; - m_reg_info.first_fpr_v = fpu_s0_arm; - m_reg_info.last_fpr_v = fpu_s31_arm; - m_reg_info.gpr_flags = gpr_cpsr_arm; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - ::memset(&m_fpr, 0, sizeof (m_fpr)); - ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm)); - ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); - - // 16 is just a maximum value, query hardware for actual watchpoint count - m_max_hwp_supported = 16; - m_max_hbp_supported = 16; - m_refresh_hwdebug_info = true; +NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + new RegisterContextLinux_arm(target_arch)) { + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + m_reg_info.num_registers = k_num_registers_arm; + m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; + m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; + m_reg_info.last_gpr = k_last_gpr_arm; + m_reg_info.first_fpr = k_first_fpr_arm; + m_reg_info.last_fpr = k_last_fpr_arm; + m_reg_info.first_fpr_v = fpu_s0_arm; + m_reg_info.last_fpr_v = fpu_s31_arm; + m_reg_info.gpr_flags = gpr_cpsr_arm; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + ::memset(&m_fpr, 0, sizeof(m_fpr)); + ::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm)); + ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); + + // 16 is just a maximum value, query hardware for actual watchpoint count + m_max_hwp_supported = 16; + m_max_hbp_supported = 16; + m_refresh_hwdebug_info = true; +} + +uint32_t NativeRegisterContextLinux_arm::GetRegisterSetCount() const { + return k_num_register_sets; +} + +uint32_t NativeRegisterContextLinux_arm::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + count += g_reg_sets_arm[set_index].num_registers; + return count; } -uint32_t -NativeRegisterContextLinux_arm::GetRegisterSetCount () const -{ - return k_num_register_sets; -} +const RegisterSet * +NativeRegisterContextLinux_arm::GetRegisterSet(uint32_t set_index) const { + if (set_index < k_num_register_sets) + return &g_reg_sets_arm[set_index]; -uint32_t -NativeRegisterContextLinux_arm::GetUserRegisterCount() const -{ - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - count += g_reg_sets_arm[set_index].num_registers; - return count; + return nullptr; } -const RegisterSet * -NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const -{ - if (set_index < k_num_register_sets) - return &g_reg_sets_arm[set_index]; +Error NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + Error error; - return nullptr; -} + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } -Error -NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - Error error; + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (!reg_info) - { - error.SetErrorString ("reg_info NULL"); - return error; + if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + error = ReadRegisterRaw(full_reg, reg_value); - if (IsFPR(reg)) - { - error = ReadFPR(); - if (error.Fail()) - return error; - } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - error = ReadRegisterRaw(full_reg, reg_value); - - if (error.Success ()) - { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; - } + if (error.Success()) { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value + // one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - // Get pointer to m_fpr variable and set the data from it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert (fpr_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) - { - case 2: - reg_value.SetUInt16(*(uint16_t *)src); - break; - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - case 16: - reg_value.SetBytes(src, 16, GetByteOrder()); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); - break; + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (reg_value.GetByteSize() > reg_info->byte_size) + reg_value.SetType(reg_info); } - return error; -} - -Error -NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (!reg_info) - return Error ("reg_info NULL"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index)) - { - // Get pointer to m_fpr variable and set the data to it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert (fpr_offset < sizeof m_fpr); - uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) - { - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); - } - - Error error = WriteFPR(); - if (error.Fail()) - return error; - - return Error (); + } + + // Get pointer to m_fpr variable and set the data from it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr); + uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; + switch (reg_info->byte_size) { + case 2: + reg_value.SetUInt16(*(uint16_t *)src); + break; + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + case 16: + reg_value.SetBytes(src, 16, GetByteOrder()); + break; + default: + assert(false && "Unhandled data size."); + error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, + reg_info->byte_size); + break; + } + + return error; +} + +Error NativeRegisterContextLinux_arm::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); + + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg_index == LLDB_INVALID_REGNUM) + return Error("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : "<unknown register>"); + + if (IsGPR(reg_index)) + return WriteRegisterRaw(reg_index, reg_value); + + if (IsFPR(reg_index)) { + // Get pointer to m_fpr variable and set the data to it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr); + uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; + switch (reg_info->byte_size) { + case 2: + *(uint16_t *)dst = reg_value.GetAsUInt16(); + break; + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled register data size %" PRIu32, + reg_info->byte_size); } - return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); -} - -Error -NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - Error error; + Error error = WriteFPR(); + if (error.Fail()) + return error; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (!data_sp) - return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); + return Error(); + } - error = ReadGPR(); - if (error.Fail()) - return error; + return Error("failed - register wasn't recognized to be a GPR or an FPR, " + "write strategy unknown"); +} - error = ReadFPR(); - if (error.Fail()) - return error; +Error NativeRegisterContextLinux_arm::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; - uint8_t *dst = data_sp->GetBytes (); - if (dst == nullptr) - { - error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE); - return error; - } + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) + return Error("failed to allocate DataBufferHeap instance of size %" PRIu64, + (uint64_t)REG_CONTEXT_SIZE); - ::memcpy (dst, &m_gpr_arm, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); + error = ReadGPR(); + if (error.Fail()) + return error; + error = ReadFPR(); + if (error.Fail()) return error; -} -Error -NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - Error error; + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + (uint64_t)REG_CONTEXT_SIZE); + return error; + } - if (!data_sp) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); - return error; - } + ::memcpy(dst, &m_gpr_arm, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr, sizeof(m_fpr)); - if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize ()); - return error; - } + return error; +} +Error NativeRegisterContextLinux_arm::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; - uint8_t *src = data_sp->GetBytes (); - if (src == nullptr) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } - ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } - error = WriteGPR(); - if (error.Fail()) - return error; + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(&m_gpr_arm, src, GetRegisterInfoInterface().GetGPRSize()); - src += GetRegisterInfoInterface ().GetGPRSize (); - ::memcpy (&m_fpr, src, sizeof(m_fpr)); + error = WriteGPR(); + if (error.Fail()) + return error; - error = WriteFPR(); - if (error.Fail()) - return error; + src += GetRegisterInfoInterface().GetGPRSize(); + ::memcpy(&m_fpr, src, sizeof(m_fpr)); + error = WriteFPR(); + if (error.Fail()) return error; + + return error; } -bool -NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const -{ - return reg <= m_reg_info.last_gpr; // GPR's come first. +bool NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const { + return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool -NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } uint32_t -NativeRegisterContextLinux_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, bp_index = 0; - - // Check if size has a valid hardware breakpoint length. - // Thumb instructions are 2-bytes but we have no way here to determine - // if target address is a thumb or arm instruction. - // TODO: Add support for setting thumb mode hardware breakpoints - if (size != 4 && size != 2) - return LLDB_INVALID_INDEX32; - - // Setup control value - // Make the byte_mask into a valid Byte Address Select mask - control_value = 0xfu << 5; - - // Enable this breakpoint and make it stop in privileged or user mode; - control_value |= 7; - - // Make sure bits 1:0 are clear in our address - // This should be different once we support thumb here. - addr &= ~((lldb::addr_t)3); - - // Iterate over stored hardware breakpoints - // Find a free bp_index or update reference count if duplicate. - bp_index = LLDB_INVALID_INDEX32; - - for (uint32_t i = 0; i < m_max_hbp_supported; i++) - { - if ((m_hbr_regs[i].control & 1) == 0) - { - bp_index = i; // Mark last free slot - } - else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) - { - bp_index = i; // Mark duplicate index - break; // Stop searching here - } + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + uint32_t control_value = 0, bp_index = 0; + + // Check if size has a valid hardware breakpoint length. + // Thumb instructions are 2-bytes but we have no way here to determine + // if target address is a thumb or arm instruction. + // TODO: Add support for setting thumb mode hardware breakpoints + if (size != 4 && size != 2) + return LLDB_INVALID_INDEX32; + + // Setup control value + // Make the byte_mask into a valid Byte Address Select mask + control_value = 0xfu << 5; + + // Enable this breakpoint and make it stop in privileged or user mode; + control_value |= 7; + + // Make sure bits 1:0 are clear in our address + // This should be different once we support thumb here. + addr &= ~((lldb::addr_t)3); + + // Iterate over stored hardware breakpoints + // Find a free bp_index or update reference count if duplicate. + bp_index = LLDB_INVALID_INDEX32; + + for (uint32_t i = 0; i < m_max_hbp_supported; i++) { + if ((m_hbr_regs[i].control & 1) == 0) { + bp_index = i; // Mark last free slot + } else if (m_hbr_regs[i].address == addr && + m_hbr_regs[i].control == control_value) { + bp_index = i; // Mark duplicate index + break; // Stop searching here } + } - if (bp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; + if (bp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; - // Add new or update existing breakpoint - if ((m_hbr_regs[bp_index].control & 1) == 0) - { - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - m_hbr_regs[bp_index].refcount = 1; + // Add new or update existing breakpoint + if ((m_hbr_regs[bp_index].control & 1) == 0) { + m_hbr_regs[bp_index].address = addr; + m_hbr_regs[bp_index].control = control_value; + m_hbr_regs[bp_index].refcount = 1; - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); + // PTRACE call to set corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); - if (error.Fail()) - { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - m_hbr_regs[bp_index].refcount = 0; + if (error.Fail()) { + m_hbr_regs[bp_index].address = 0; + m_hbr_regs[bp_index].control &= ~1; + m_hbr_regs[bp_index].refcount = 0; - return LLDB_INVALID_INDEX32; - } + return LLDB_INVALID_INDEX32; } - else - m_hbr_regs[bp_index].refcount++; + } else + m_hbr_regs[bp_index].refcount++; - return bp_index; + return bp_index; } -bool -NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return false; + if (error.Fail()) + return false; - if (hw_idx >= m_max_hbp_supported) - return false; + if (hw_idx >= m_max_hbp_supported) + return false; - // Update reference count if multiple references. - if (m_hbr_regs[hw_idx].refcount > 1) - { - m_hbr_regs[hw_idx].refcount--; - return true; - } - else if (m_hbr_regs[hw_idx].refcount == 1) - { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; - - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - m_hbr_regs[hw_idx].refcount = 0; - - // PTRACE call to clear corresponding hardware breakpoint register. - WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); - - if (error.Fail()) - { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - m_hbr_regs[hw_idx].refcount = tempRefCount; - - return false; - } - - return true; + // Update reference count if multiple references. + if (m_hbr_regs[hw_idx].refcount > 1) { + m_hbr_regs[hw_idx].refcount--; + return true; + } else if (m_hbr_regs[hw_idx].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; + uint32_t tempControl = m_hbr_regs[hw_idx].control; + uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; + + m_hbr_regs[hw_idx].control &= ~1; + m_hbr_regs[hw_idx].address = 0; + m_hbr_regs[hw_idx].refcount = 0; + + // PTRACE call to clear corresponding hardware breakpoint register. + WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); + + if (error.Fail()) { + m_hbr_regs[hw_idx].control = tempControl; + m_hbr_regs[hw_idx].address = tempAddr; + m_hbr_regs[hw_idx].refcount = tempRefCount; + + return false; } - return false; + return true; + } + + return false; } -uint32_t -NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints () -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return 0; + if (error.Fail()) + return 0; - return m_max_hwp_supported; + return m_max_hwp_supported; } -uint32_t -NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Error error; + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + Error error; - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; - lldb::addr_t real_addr = addr; - - // Check if we are setting watchpoint other than read/write/access - // Also update watchpoint flag to match Arm write-read bit configuration. - switch (watch_flags) - { - case 1: - watch_flags = 2; - break; - case 2: - watch_flags = 1; - break; - case 3: - break; - default: - return LLDB_INVALID_INDEX32; - } + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - // Can't watch zero bytes - // Can't watch more than 4 bytes per WVR/WCR pair + if (error.Fail()) + return LLDB_INVALID_INDEX32; - if (size == 0 || size > 4) - return LLDB_INVALID_INDEX32; + uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; + lldb::addr_t real_addr = addr; - // Check 4-byte alignment for hardware watchpoint target address. - // Below is a hack to recalculate address and size in order to - // make sure we can watch non 4-byte alligned addresses as well. - if (addr & 0x03) - { - uint8_t watch_mask = (addr & 0x03) + size; + // Check if we are setting watchpoint other than read/write/access + // Also update watchpoint flag to match Arm write-read bit configuration. + switch (watch_flags) { + case 1: + watch_flags = 2; + break; + case 2: + watch_flags = 1; + break; + case 3: + break; + default: + return LLDB_INVALID_INDEX32; + } - if (watch_mask > 0x04) - return LLDB_INVALID_INDEX32; - else if (watch_mask <= 0x02) - size = 2; - else if (watch_mask <= 0x04) - size = 4; + // Can't watch zero bytes + // Can't watch more than 4 bytes per WVR/WCR pair - addr = addr & (~0x03); - } + if (size == 0 || size > 4) + return LLDB_INVALID_INDEX32; - // We can only watch up to four bytes that follow a 4 byte aligned address - // per watchpoint register pair, so make sure we can properly encode this. - addr_word_offset = addr % 4; - byte_mask = ((1u << size) - 1u) << addr_word_offset; - - // Check if we need multiple watchpoint register - if (byte_mask > 0xfu) - return LLDB_INVALID_INDEX32; - - // Setup control value - // Make the byte_mask into a valid Byte Address Select mask - control_value = byte_mask << 5; - - //Turn on appropriate watchpoint flags read or write - control_value |= (watch_flags << 3); - - // Enable this watchpoint and make it stop in privileged or user mode; - control_value |= 7; - - // Make sure bits 1:0 are clear in our address - addr &= ~((lldb::addr_t)3); - - // Iterate over stored watchpoints - // Find a free wp_index or update reference count if duplicate. - wp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hwp_supported; i++) - { - if ((m_hwp_regs[i].control & 1) == 0) - { - wp_index = i; // Mark last free slot - } - else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) - { - wp_index = i; // Mark duplicate index - break; // Stop searching here - } - } + // Check 4-byte alignment for hardware watchpoint target address. + // Below is a hack to recalculate address and size in order to + // make sure we can watch non 4-byte alligned addresses as well. + if (addr & 0x03) { + uint8_t watch_mask = (addr & 0x03) + size; - if (wp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Add new or update existing watchpoint - if ((m_hwp_regs[wp_index].control & 1) == 0) - { - // Update watchpoint in local cache - m_hwp_regs[wp_index].real_addr = real_addr; - m_hwp_regs[wp_index].address = addr; - m_hwp_regs[wp_index].control = control_value; - m_hwp_regs[wp_index].refcount = 1; - - // PTRACE call to set corresponding watchpoint register. - error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); - - if (error.Fail()) - { - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].refcount = 0; - - return LLDB_INVALID_INDEX32; - } - } - else - m_hwp_regs[wp_index].refcount++; + if (watch_mask > 0x04) + return LLDB_INVALID_INDEX32; + else if (watch_mask <= 0x02) + size = 2; + else if (watch_mask <= 0x04) + size = 4; - return wp_index; -} + addr = addr & (~0x03); + } -bool -NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + // We can only watch up to four bytes that follow a 4 byte aligned address + // per watchpoint register pair, so make sure we can properly encode this. + addr_word_offset = addr % 4; + byte_mask = ((1u << size) - 1u) << addr_word_offset; - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + // Check if we need multiple watchpoint register + if (byte_mask > 0xfu) + return LLDB_INVALID_INDEX32; - Error error; + // Setup control value + // Make the byte_mask into a valid Byte Address Select mask + control_value = byte_mask << 5; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Turn on appropriate watchpoint flags read or write + control_value |= (watch_flags << 3); - if (error.Fail()) - return false; + // Enable this watchpoint and make it stop in privileged or user mode; + control_value |= 7; - if (wp_index >= m_max_hwp_supported) - return false; + // Make sure bits 1:0 are clear in our address + addr &= ~((lldb::addr_t)3); - // Update reference count if multiple references. - if (m_hwp_regs[wp_index].refcount > 1) - { - m_hwp_regs[wp_index].refcount--; - return true; + // Iterate over stored watchpoints + // Find a free wp_index or update reference count if duplicate. + wp_index = LLDB_INVALID_INDEX32; + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if ((m_hwp_regs[i].control & 1) == 0) { + wp_index = i; // Mark last free slot + } else if (m_hwp_regs[i].address == addr && + m_hwp_regs[i].control == control_value) { + wp_index = i; // Mark duplicate index + break; // Stop searching here } - else if (m_hwp_regs[wp_index].refcount == 1) - { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; - uint32_t tempControl = m_hwp_regs[wp_index].control; - uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].refcount = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); - - if (error.Fail()) - { - m_hwp_regs[wp_index].control = tempControl; - m_hwp_regs[wp_index].address = tempAddr; - m_hwp_regs[wp_index].refcount = tempRefCount; - - return false; - } - - return true; + } + + if (wp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; + + // Add new or update existing watchpoint + if ((m_hwp_regs[wp_index].control & 1) == 0) { + // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; + m_hwp_regs[wp_index].address = addr; + m_hwp_regs[wp_index].control = control_value; + m_hwp_regs[wp_index].refcount = 1; + + // PTRACE call to set corresponding watchpoint register. + error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); + + if (error.Fail()) { + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].control &= ~1; + m_hwp_regs[wp_index].refcount = 0; + + return LLDB_INVALID_INDEX32; } + } else + m_hwp_regs[wp_index].refcount++; - return false; + return wp_index; } -Error -NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints () -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint( + uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return error; + if (error.Fail()) + return false; - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0, tempRefCount = 0; - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) - { - if (m_hwp_regs[i].control & 0x01) - { - // Create a backup we can revert to in case of failure. - tempAddr = m_hwp_regs[i].address; - tempControl = m_hwp_regs[i].control; - tempRefCount = m_hwp_regs[i].refcount; - - // Clear watchpoints in local cache - m_hwp_regs[i].control &= ~1; - m_hwp_regs[i].address = 0; - m_hwp_regs[i].refcount = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); - - if (error.Fail()) - { - m_hwp_regs[i].control = tempControl; - m_hwp_regs[i].address = tempAddr; - m_hwp_regs[i].refcount = tempRefCount; - - return error; - } - } + if (wp_index >= m_max_hwp_supported) + return false; + + // Update reference count if multiple references. + if (m_hwp_regs[wp_index].refcount > 1) { + m_hwp_regs[wp_index].refcount--; + return true; + } else if (m_hwp_regs[wp_index].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; + uint32_t tempControl = m_hwp_regs[wp_index].control; + uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; + + // Update watchpoint in local cache + m_hwp_regs[wp_index].control &= ~1; + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].refcount = 0; + + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); + + if (error.Fail()) { + m_hwp_regs[wp_index].control = tempControl; + m_hwp_regs[wp_index].address = tempAddr; + m_hwp_regs[wp_index].refcount = tempRefCount; + + return false; } - return Error(); -} + return true; + } -uint32_t -NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) - { - case 0x01: - return 1; - case 0x03: - return 2; - case 0x07: - return 3; - case 0x0f: - return 4; - default: - return 0; - } -} -bool -NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) - return true; - else - return false; + return false; } -Error -NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - uint32_t watch_size; - lldb::addr_t watch_addr; + Error error; - for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) - { - watch_size = GetWatchpointSize (wp_index); - watch_addr = m_hwp_regs[wp_index].address; + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) - && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) - { - m_hwp_regs[wp_index].hit_addr = trap_addr; - return Error(); - } - } + if (error.Fail()) + return error; - wp_index = LLDB_INVALID_INDEX32; - return Error(); -} + lldb::addr_t tempAddr = 0; + uint32_t tempControl = 0, tempRefCount = 0; -lldb::addr_t -NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if (m_hwp_regs[i].control & 0x01) { + // Create a backup we can revert to in case of failure. + tempAddr = m_hwp_regs[i].address; + tempControl = m_hwp_regs[i].control; + tempRefCount = m_hwp_regs[i].refcount; + + // Clear watchpoints in local cache + m_hwp_regs[i].control &= ~1; + m_hwp_regs[i].address = 0; + m_hwp_regs[i].refcount = 0; - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; + if (error.Fail()) { + m_hwp_regs[i].control = tempControl; + m_hwp_regs[i].address = tempAddr; + m_hwp_regs[i].refcount = tempRefCount; - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].real_addr; - else - return LLDB_INVALID_ADDRESS; + return error; + } + } + } + + return Error(); } -lldb::addr_t -NativeRegisterContextLinux_arm::GetWatchpointHitAddress (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; + switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) { + case 0x01: + return 1; + case 0x03: + return 2; + case 0x07: + return 3; + case 0x0f: + return 4; + default: + return 0; + } +} +bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].hit_addr; - else - return LLDB_INVALID_ADDRESS; + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + + if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) + return true; + else + return false; } -Error -NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() -{ - Error error; +Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (!m_refresh_hwdebug_info) - { - return Error(); + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + + uint32_t watch_size; + lldb::addr_t watch_addr; + + for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { + watch_size = GetWatchpointSize(wp_index); + watch_addr = m_hwp_regs[wp_index].address; + + if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) && + trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; + return Error(); } + } - unsigned int cap_val; + wp_index = LLDB_INVALID_INDEX32; + return Error(); +} - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int)); +lldb::addr_t +NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (error.Fail()) - return error; + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - m_max_hwp_supported = (cap_val >> 8) & 0xff; - m_max_hbp_supported = cap_val & 0xff; - m_refresh_hwdebug_info = false; + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; - return error; + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; } -Error -NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index) -{ - Error error; +lldb::addr_t +NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - lldb::addr_t *addr_buf; - uint32_t *ctrl_buf; + if (log) + log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - if (hwbType == eDREGTypeWATCH) - { - addr_buf = &m_hwp_regs[hwb_index].address; - ctrl_buf = &m_hwp_regs[hwb_index].control; + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, - m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 1), - addr_buf, sizeof(unsigned int)); + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; + else + return LLDB_INVALID_ADDRESS; +} - if (error.Fail()) - return error; +Error NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() { + Error error; - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, - m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 2), - ctrl_buf, sizeof(unsigned int)); - } - else - { - addr_buf = &m_hwp_regs[hwb_index].address; - ctrl_buf = &m_hwp_regs[hwb_index].control; + if (!m_refresh_hwdebug_info) { + return Error(); + } - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, - m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 1), - addr_buf, sizeof(unsigned int)); + unsigned int cap_val; - if (error.Fail()) - return error; + error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), + nullptr, &cap_val, + sizeof(unsigned int)); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, - m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 2), - ctrl_buf, sizeof(unsigned int)); + if (error.Fail()) + return error; - } + m_max_hwp_supported = (cap_val >> 8) & 0xff; + m_max_hbp_supported = cap_val & 0xff; + m_refresh_hwdebug_info = false; - return error; + return error; } -uint32_t -NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) const -{ - return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; -} +Error NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, + int hwb_index) { + Error error; + + lldb::addr_t *addr_buf; + uint32_t *ctrl_buf; + + if (hwbType == eDREGTypeWATCH) { + addr_buf = &m_hwp_regs[hwb_index].address; + ctrl_buf = &m_hwp_regs[hwb_index].control; + + error = NativeProcessLinux::PtraceWrapper( + PTRACE_SETHBPREGS, m_thread.GetID(), + (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 1), addr_buf, + sizeof(unsigned int)); -Error -NativeRegisterContextLinux_arm::DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) -{ - // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android devices (always return - // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR register set instead. - // This approach is about 4 times slower but the performance overhead is negligible in - // comparision to processing time in lldb-server. - assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); - if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) - return Error("Register isn't fit into the size of the GPR area"); - - Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); if (error.Fail()) - return error; + return error; - value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]); - return Error(); -} + error = NativeProcessLinux::PtraceWrapper( + PTRACE_SETHBPREGS, m_thread.GetID(), + (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf, + sizeof(unsigned int)); + } else { + addr_buf = &m_hwp_regs[hwb_index].address; + ctrl_buf = &m_hwp_regs[hwb_index].control; + + error = NativeProcessLinux::PtraceWrapper( + PTRACE_SETHBPREGS, m_thread.GetID(), + (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 1), addr_buf, + sizeof(unsigned int)); -Error -NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) -{ - // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android devices (always return - // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify - // the requested register and write it back. This approach is about 4 times slower but the - // performance overhead is negligible in comparision to processing time in lldb-server. - assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); - if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) - return Error("Register isn't fit into the size of the GPR area"); - - Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); if (error.Fail()) - return error; + return error; + + error = NativeProcessLinux::PtraceWrapper( + PTRACE_SETHBPREGS, m_thread.GetID(), + (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf, + sizeof(unsigned int)); + } + + return error; +} + +uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; +} + +Error NativeRegisterContextLinux_arm::DoReadRegisterValue( + uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) { + // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android + // devices (always return + // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR + // register set instead. + // This approach is about 4 times slower but the performance overhead is + // negligible in + // comparision to processing time in lldb-server. + assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); + if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) + return Error("Register isn't fit into the size of the GPR area"); + + Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); + if (error.Fail()) + return error; + + value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]); + return Error(); +} + +Error NativeRegisterContextLinux_arm::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android + // devices (always return + // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR + // register set, modify + // the requested register and write it back. This approach is about 4 times + // slower but the + // performance overhead is negligible in comparision to processing time in + // lldb-server. + assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); + if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) + return Error("Register isn't fit into the size of the GPR area"); + + Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); + if (error.Fail()) + return error; - uint32_t reg_value = value.GetAsUInt32(); - // As precaution for an undefined behavior encountered while setting PC we - // will clear thumb bit of new PC if we are already in thumb mode; that is - // CPSR thumb mode bit is set. - if (offset / sizeof(uint32_t) == gpr_pc_arm) - { - // Check if we are already in thumb mode and - // thumb bit of current PC is read out to be zero and - // thumb bit of next PC is read out to be one. - if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && - !(m_gpr_arm[gpr_pc_arm] & 0x01) && - (value.GetAsUInt32() & 0x01)) - { - reg_value &= (~1ull); - } + uint32_t reg_value = value.GetAsUInt32(); + // As precaution for an undefined behavior encountered while setting PC we + // will clear thumb bit of new PC if we are already in thumb mode; that is + // CPSR thumb mode bit is set. + if (offset / sizeof(uint32_t) == gpr_pc_arm) { + // Check if we are already in thumb mode and + // thumb bit of current PC is read out to be zero and + // thumb bit of next PC is read out to be one. + if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && !(m_gpr_arm[gpr_pc_arm] & 0x01) && + (value.GetAsUInt32() & 0x01)) { + reg_value &= (~1ull); } + } - m_gpr_arm[offset / sizeof(uint32_t)] = reg_value; - return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm)); + m_gpr_arm[offset / sizeof(uint32_t)] = reg_value; + return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm)); } -Error -NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size) -{ +Error NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size) { #ifdef __arm__ - return NativeRegisterContextLinux::DoReadGPR(buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; + return NativeRegisterContextLinux::DoReadGPR(buf, buf_size); +#else // __aarch64__ + struct iovec ioVec; + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; - return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS); + return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS); #endif // __arm__ } -Error -NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size) -{ +Error NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size) { #ifdef __arm__ - return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; + return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size); +#else // __aarch64__ + struct iovec ioVec; + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; - return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS); + return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS); #endif // __arm__ } -Error -NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size) -{ +Error NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size) { #ifdef __arm__ - return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, - m_thread.GetID(), - nullptr, - buf, - buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP); + return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, m_thread.GetID(), + nullptr, buf, buf_size); +#else // __aarch64__ + struct iovec ioVec; + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + + return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP); #endif // __arm__ } -Error -NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size) -{ +Error NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size) { #ifdef __arm__ - return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, - m_thread.GetID(), - nullptr, - buf, - buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP); + return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, m_thread.GetID(), + nullptr, buf, buf_size); +#else // __aarch64__ + struct iovec ioVec; + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + + return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP); #endif // __arm__ } diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index 452f13258c2..f979811216d 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -18,181 +18,142 @@ namespace lldb_private { namespace process_linux { - class NativeProcessLinux; +class NativeProcessLinux; - class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux - { - public: - NativeRegisterContextLinux_arm (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); +class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { +public: + NativeRegisterContextLinux_arm(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); - uint32_t - GetRegisterSetCount () const override; + uint32_t GetRegisterSetCount() const override; - const RegisterSet * - GetRegisterSet (uint32_t set_index) const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - uint32_t - GetUserRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; - Error - ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override; + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - Error - WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - Error - ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - Error - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - //------------------------------------------------------------------ - // Hardware breakpoints/watchpoint mangement functions - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Hardware breakpoints/watchpoint mangement functions + //------------------------------------------------------------------ - uint32_t - SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - bool - ClearHardwareBreakpoint (uint32_t hw_idx) override; + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - uint32_t - NumSupportedHardwareWatchpoints () override; + uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t - SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; - bool - ClearHardwareWatchpoint (uint32_t hw_index) override; + bool ClearHardwareWatchpoint(uint32_t hw_index) override; - Error - ClearAllHardwareWatchpoints () override; + Error ClearAllHardwareWatchpoints() override; - Error - GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; - lldb::addr_t - GetWatchpointHitAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - lldb::addr_t - GetWatchpointAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - uint32_t - GetWatchpointSize(uint32_t wp_index); + uint32_t GetWatchpointSize(uint32_t wp_index); - bool - WatchpointIsEnabled(uint32_t wp_index); + bool WatchpointIsEnabled(uint32_t wp_index); - // Debug register type select - enum DREGType - { - eDREGTypeWATCH = 0, - eDREGTypeBREAK - }; + // Debug register type select + enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK }; - protected: - Error - DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) override; +protected: + Error DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value) override; - Error - DoWriteRegisterValue(uint32_t offset, - const char* reg_name, + Error DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override; - Error - DoReadGPR(void *buf, size_t buf_size) override; + Error DoReadGPR(void *buf, size_t buf_size) override; - Error - DoWriteGPR(void *buf, size_t buf_size) override; + Error DoWriteGPR(void *buf, size_t buf_size) override; - Error - DoReadFPR(void *buf, size_t buf_size) override; + Error DoReadFPR(void *buf, size_t buf_size) override; - Error - DoWriteFPR(void *buf, size_t buf_size) override; + Error DoWriteFPR(void *buf, size_t buf_size) override; - void* - GetGPRBuffer() override { return &m_gpr_arm; } + void *GetGPRBuffer() override { return &m_gpr_arm; } - void* - GetFPRBuffer() override { return &m_fpr; } + void *GetFPRBuffer() override { return &m_fpr; } - size_t - GetFPRSize() override { return sizeof(m_fpr); } + size_t GetFPRSize() override { return sizeof(m_fpr); } - private: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; +private: + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; - uint32_t first_fpr_v; - uint32_t last_fpr_v; + uint32_t first_fpr_v; + uint32_t last_fpr_v; - uint32_t gpr_flags; - }; + uint32_t gpr_flags; + }; - struct QReg - { - uint8_t bytes[16]; - }; + struct QReg { + uint8_t bytes[16]; + }; - struct FPU - { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; + struct FPU { + union { + uint32_t s[32]; + uint64_t d[32]; + QReg q[16]; // the 128-bit NEON registers + } floats; + uint32_t fpscr; + }; - uint32_t m_gpr_arm[k_num_gpr_registers_arm]; - RegInfo m_reg_info; - FPU m_fpr; + uint32_t m_gpr_arm[k_num_gpr_registers_arm]; + RegInfo m_reg_info; + FPU m_fpr; - // Debug register info for hardware breakpoints and watchpoints management. - struct DREG - { - lldb::addr_t address; // Breakpoint/watchpoint address value. - lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred. - lldb::addr_t real_addr; // Address value that should cause target to stop. - uint32_t control; // Breakpoint/watchpoint control value. - uint32_t refcount; // Serves as enable/disable and refernce counter. - }; + // Debug register info for hardware breakpoints and watchpoints management. + struct DREG { + lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception + // occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. + uint32_t control; // Breakpoint/watchpoint control value. + uint32_t refcount; // Serves as enable/disable and refernce counter. + }; - struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints - struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints + struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints + struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints - uint32_t m_max_hwp_supported; - uint32_t m_max_hbp_supported; - bool m_refresh_hwdebug_info; + uint32_t m_max_hwp_supported; + uint32_t m_max_hbp_supported; + bool m_refresh_hwdebug_info; - bool - IsGPR(unsigned reg) const; + bool IsGPR(unsigned reg) const; - bool - IsFPR(unsigned reg) const; + bool IsFPR(unsigned reg) const; - Error - ReadHardwareDebugInfo(); + Error ReadHardwareDebugInfo(); - Error - WriteHardwareDebugRegs(int hwbType, int hwb_index); + Error WriteHardwareDebugRegs(int hwbType, int hwb_index); - uint32_t - CalculateFprOffset(const RegisterInfo* reg_info) const; - }; + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 9489f00c1af..83cd1797829 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__arm64__) || defined (__aarch64__) +#if defined(__arm64__) || defined(__aarch64__) #include "NativeRegisterContextLinux_arm.h" #include "NativeRegisterContextLinux_arm64.h" @@ -27,7 +27,8 @@ #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" -// System includes - They have to be included after framework includes because they define some +// System includes - They have to be included after framework includes because +// they define some // macros which collide with variable names in other modules #include <sys/socket.h> // NT_PRSTATUS and NT_FPREGSET definition @@ -42,1051 +43,930 @@ using namespace lldb_private; using namespace lldb_private::process_linux; // ARM64 general purpose registers. -static const uint32_t g_gpr_regnums_arm64[] = -{ - gpr_x0_arm64, - gpr_x1_arm64, - gpr_x2_arm64, - gpr_x3_arm64, - gpr_x4_arm64, - gpr_x5_arm64, - gpr_x6_arm64, - gpr_x7_arm64, - gpr_x8_arm64, - gpr_x9_arm64, - gpr_x10_arm64, - gpr_x11_arm64, - gpr_x12_arm64, - gpr_x13_arm64, - gpr_x14_arm64, - gpr_x15_arm64, - gpr_x16_arm64, - gpr_x17_arm64, - gpr_x18_arm64, - gpr_x19_arm64, - gpr_x20_arm64, - gpr_x21_arm64, - gpr_x22_arm64, - gpr_x23_arm64, - gpr_x24_arm64, - gpr_x25_arm64, - gpr_x26_arm64, - gpr_x27_arm64, - gpr_x28_arm64, - gpr_fp_arm64, - gpr_lr_arm64, - gpr_sp_arm64, - gpr_pc_arm64, - gpr_cpsr_arm64, +static const uint32_t g_gpr_regnums_arm64[] = { + gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64, + gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64, + gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64, + gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64, + gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64, + gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64, + gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64, + gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64, + gpr_pc_arm64, gpr_cpsr_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ +static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - + 1) == k_num_gpr_registers_arm64, "g_gpr_regnums_arm64 has wrong number of register infos"); // ARM64 floating point registers. -static const uint32_t g_fpu_regnums_arm64[] = -{ - fpu_v0_arm64, - fpu_v1_arm64, - fpu_v2_arm64, - fpu_v3_arm64, - fpu_v4_arm64, - fpu_v5_arm64, - fpu_v6_arm64, - fpu_v7_arm64, - fpu_v8_arm64, - fpu_v9_arm64, - fpu_v10_arm64, - fpu_v11_arm64, - fpu_v12_arm64, - fpu_v13_arm64, - fpu_v14_arm64, - fpu_v15_arm64, - fpu_v16_arm64, - fpu_v17_arm64, - fpu_v18_arm64, - fpu_v19_arm64, - fpu_v20_arm64, - fpu_v21_arm64, - fpu_v22_arm64, - fpu_v23_arm64, - fpu_v24_arm64, - fpu_v25_arm64, - fpu_v26_arm64, - fpu_v27_arm64, - fpu_v28_arm64, - fpu_v29_arm64, - fpu_v30_arm64, - fpu_v31_arm64, - fpu_fpsr_arm64, - fpu_fpcr_arm64, +static const uint32_t g_fpu_regnums_arm64[] = { + fpu_v0_arm64, fpu_v1_arm64, fpu_v2_arm64, fpu_v3_arm64, + fpu_v4_arm64, fpu_v5_arm64, fpu_v6_arm64, fpu_v7_arm64, + fpu_v8_arm64, fpu_v9_arm64, fpu_v10_arm64, fpu_v11_arm64, + fpu_v12_arm64, fpu_v13_arm64, fpu_v14_arm64, fpu_v15_arm64, + fpu_v16_arm64, fpu_v17_arm64, fpu_v18_arm64, fpu_v19_arm64, + fpu_v20_arm64, fpu_v21_arm64, fpu_v22_arm64, fpu_v23_arm64, + fpu_v24_arm64, fpu_v25_arm64, fpu_v26_arm64, fpu_v27_arm64, + fpu_v28_arm64, fpu_v29_arm64, fpu_v30_arm64, fpu_v31_arm64, + fpu_fpsr_arm64, fpu_fpcr_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ +static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - + 1) == k_num_fpr_registers_arm64, "g_fpu_regnums_arm64 has wrong number of register infos"); namespace { - // Number of register sets provided by this context. - enum - { - k_num_register_sets = 2 - }; +// Number of register sets provided by this context. +enum { k_num_register_sets = 2 }; } // Register sets for ARM64. -static const RegisterSet -g_reg_sets_arm64[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } -}; - -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); - case llvm::Triple::aarch64: - return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); - default: - if (log) - log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__, - target_arch.GetTriple().getArchName().str().c_str()); - return nullptr; - } +static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64, + g_gpr_regnums_arm64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, + g_fpu_regnums_arm64}}; + +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + return new NativeRegisterContextLinux_arm(target_arch, native_thread, + concrete_frame_idx); + case llvm::Triple::aarch64: + return new NativeRegisterContextLinux_arm64(target_arch, native_thread, + concrete_frame_idx); + default: + if (log) + log->Printf("NativeRegisterContextLinux::%s() have no register context " + "for architecture: %s\n", + __FUNCTION__, + target_arch.GetTriple().getArchName().str().c_str()); + return nullptr; + } +} + +NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + new RegisterContextLinux_arm64(target_arch)) { + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + m_reg_info.num_registers = k_num_registers_arm64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; + m_reg_info.last_gpr = k_last_gpr_arm64; + m_reg_info.first_fpr = k_first_fpr_arm64; + m_reg_info.last_fpr = k_last_fpr_arm64; + m_reg_info.first_fpr_v = fpu_v0_arm64; + m_reg_info.last_fpr_v = fpu_v31_arm64; + m_reg_info.gpr_flags = gpr_cpsr_arm64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + ::memset(&m_fpr, 0, sizeof(m_fpr)); + ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); + ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); + + // 16 is just a maximum value, query hardware for actual watchpoint count + m_max_hwp_supported = 16; + m_max_hbp_supported = 16; + m_refresh_hwdebug_info = true; +} + +uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { + return k_num_register_sets; } -NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - m_reg_info.num_registers = k_num_registers_arm64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; - m_reg_info.last_gpr = k_last_gpr_arm64; - m_reg_info.first_fpr = k_first_fpr_arm64; - m_reg_info.last_fpr = k_last_fpr_arm64; - m_reg_info.first_fpr_v = fpu_v0_arm64; - m_reg_info.last_fpr_v = fpu_v31_arm64; - m_reg_info.gpr_flags = gpr_cpsr_arm64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - ::memset(&m_fpr, 0, sizeof (m_fpr)); - ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); - ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); +const RegisterSet * +NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { + if (set_index < k_num_register_sets) + return &g_reg_sets_arm64[set_index]; - // 16 is just a maximum value, query hardware for actual watchpoint count - m_max_hwp_supported = 16; - m_max_hbp_supported = 16; - m_refresh_hwdebug_info = true; + return nullptr; } -uint32_t -NativeRegisterContextLinux_arm64::GetRegisterSetCount () const -{ - return k_num_register_sets; +uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + count += g_reg_sets_arm64[set_index].num_registers; + return count; } -const RegisterSet * -NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const -{ - if (set_index < k_num_register_sets) - return &g_reg_sets_arm64[set_index]; +Error NativeRegisterContextLinux_arm64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + Error error; - return nullptr; -} - -uint32_t -NativeRegisterContextLinux_arm64::GetUserRegisterCount() const -{ - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - count += g_reg_sets_arm64[set_index].num_registers; - return count; -} + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } -Error -NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - Error error; + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (!reg_info) - { - error.SetErrorString ("reg_info NULL"); - return error; + if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + error = ReadRegisterRaw(full_reg, reg_value); - if (IsFPR(reg)) - { - error = ReadFPR(); - if (error.Fail()) - return error; - } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - error = ReadRegisterRaw(full_reg, reg_value); - - if (error.Success ()) - { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; + if (error.Success()) { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value + // one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); + + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (reg_value.GetByteSize() > reg_info->byte_size) + reg_value.SetType(reg_info); } + return error; + } - // Get pointer to m_fpr variable and set the data from it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert (fpr_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, eByteOrderLittle, error); + // Get pointer to m_fpr variable and set the data from it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr); + uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); - return error; + return error; } -Error -NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (!reg_info) - return Error ("reg_info NULL"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index)) - { - // Get pointer to m_fpr variable and set the data to it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert (fpr_offset < sizeof m_fpr); - uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) - { - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); - } - - Error error = WriteFPR(); - if (error.Fail()) - return error; - - return Error (); - } +Error NativeRegisterContextLinux_arm64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); - return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); -} + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg_index == LLDB_INVALID_REGNUM) + return Error("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : "<unknown register>"); -Error -NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - Error error; + if (IsGPR(reg_index)) + return WriteRegisterRaw(reg_index, reg_value); - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (!data_sp) - return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); + if (IsFPR(reg_index)) { + // Get pointer to m_fpr variable and set the data to it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr); + uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; + switch (reg_info->byte_size) { + case 2: + *(uint16_t *)dst = reg_value.GetAsUInt16(); + break; + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled register data size %" PRIu32, + reg_info->byte_size); + } - error = ReadGPR(); + Error error = WriteFPR(); if (error.Fail()) - return error; + return error; - error = ReadFPR(); - if (error.Fail()) - return error; + return Error(); + } - uint8_t *dst = data_sp->GetBytes (); - if (dst == nullptr) - { - error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); - return error; - } + return Error("failed - register wasn't recognized to be a GPR or an FPR, " + "write strategy unknown"); +} + +Error NativeRegisterContextLinux_arm64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; - ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) + return Error("failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); + error = ReadGPR(); + if (error.Fail()) return error; -} -Error -NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - Error error; + error = ReadFPR(); + if (error.Fail()) + return error; - if (!data_sp) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); - return error; - } + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } - if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); - return error; - } + ::memcpy(dst, &m_gpr_arm64, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr, sizeof(m_fpr)); + return error; +} - uint8_t *src = data_sp->GetBytes (); - if (src == nullptr) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } - ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); +Error NativeRegisterContextLinux_arm64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; - error = WriteGPR(); - if (error.Fail()) - return error; + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } - src += GetRegisterInfoInterface ().GetGPRSize (); - ::memcpy (&m_fpr, src, sizeof(m_fpr)); + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(&m_gpr_arm64, src, GetRegisterInfoInterface().GetGPRSize()); - error = WriteFPR(); - if (error.Fail()) - return error; + error = WriteGPR(); + if (error.Fail()) + return error; + + src += GetRegisterInfoInterface().GetGPRSize(); + ::memcpy(&m_fpr, src, sizeof(m_fpr)); + error = WriteFPR(); + if (error.Fail()) return error; + + return error; } -bool -NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const -{ - return reg <= m_reg_info.last_gpr; // GPR's come first. +bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { + return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool -NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } uint32_t -NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; - - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, bp_index = 0; - - // Check if size has a valid hardware breakpoint length. - if (size != 4) - return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint - - // Check 4-byte alignment for hardware breakpoint target address. - if (addr & 0x03) - return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. - - // Setup control value - control_value = 0; - control_value |= ((1 << size) - 1) << 5; - control_value |= (2 << 1) | 1; - - // Iterate over stored hardware breakpoints - // Find a free bp_index or update reference count if duplicate. - bp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hbp_supported; i++) - { - if ((m_hbr_regs[i].control & 1) == 0) - { - bp_index = i; // Mark last free slot - } - else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) - { - bp_index = i; // Mark duplicate index - break; // Stop searching here - } +NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + + Error error; + + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + uint32_t control_value = 0, bp_index = 0; + + // Check if size has a valid hardware breakpoint length. + if (size != 4) + return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware + // breakpoint + + // Check 4-byte alignment for hardware breakpoint target address. + if (addr & 0x03) + return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. + + // Setup control value + control_value = 0; + control_value |= ((1 << size) - 1) << 5; + control_value |= (2 << 1) | 1; + + // Iterate over stored hardware breakpoints + // Find a free bp_index or update reference count if duplicate. + bp_index = LLDB_INVALID_INDEX32; + for (uint32_t i = 0; i < m_max_hbp_supported; i++) { + if ((m_hbr_regs[i].control & 1) == 0) { + bp_index = i; // Mark last free slot + } else if (m_hbr_regs[i].address == addr && + m_hbr_regs[i].control == control_value) { + bp_index = i; // Mark duplicate index + break; // Stop searching here } + } - if (bp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; + if (bp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; - // Add new or update existing breakpoint - if ((m_hbr_regs[bp_index].control & 1) == 0) - { - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - m_hbr_regs[bp_index].refcount = 1; + // Add new or update existing breakpoint + if ((m_hbr_regs[bp_index].control & 1) == 0) { + m_hbr_regs[bp_index].address = addr; + m_hbr_regs[bp_index].control = control_value; + m_hbr_regs[bp_index].refcount = 1; - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK); + // PTRACE call to set corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK); - if (error.Fail()) - { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - m_hbr_regs[bp_index].refcount = 0; + if (error.Fail()) { + m_hbr_regs[bp_index].address = 0; + m_hbr_regs[bp_index].control &= ~1; + m_hbr_regs[bp_index].refcount = 0; - return LLDB_INVALID_INDEX32; - } + return LLDB_INVALID_INDEX32; } - else - m_hbr_regs[bp_index].refcount++; + } else + m_hbr_regs[bp_index].refcount++; - return bp_index; + return bp_index; } -bool -NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( + uint32_t hw_idx) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return false; + if (error.Fail()) + return false; - if (hw_idx >= m_max_hbp_supported) - return false; + if (hw_idx >= m_max_hbp_supported) + return false; - // Update reference count if multiple references. - if (m_hbr_regs[hw_idx].refcount > 1) - { - m_hbr_regs[hw_idx].refcount--; - return true; - } - else if (m_hbr_regs[hw_idx].refcount == 1) - { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; - - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - m_hbr_regs[hw_idx].refcount = 0; - - // PTRACE call to clear corresponding hardware breakpoint register. - WriteHardwareDebugRegs(eDREGTypeBREAK); - - if (error.Fail()) - { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - m_hbr_regs[hw_idx].refcount = tempRefCount; - - return false; - } - - return true; + // Update reference count if multiple references. + if (m_hbr_regs[hw_idx].refcount > 1) { + m_hbr_regs[hw_idx].refcount--; + return true; + } else if (m_hbr_regs[hw_idx].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; + uint32_t tempControl = m_hbr_regs[hw_idx].control; + uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; + + m_hbr_regs[hw_idx].control &= ~1; + m_hbr_regs[hw_idx].address = 0; + m_hbr_regs[hw_idx].refcount = 0; + + // PTRACE call to clear corresponding hardware breakpoint register. + WriteHardwareDebugRegs(eDREGTypeBREAK); + + if (error.Fail()) { + m_hbr_regs[hw_idx].control = tempControl; + m_hbr_regs[hw_idx].address = tempAddr; + m_hbr_regs[hw_idx].refcount = tempRefCount; + + return false; } - return false; + return true; + } + + return false; } -uint32_t -NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return 0; + if (error.Fail()) + return 0; - return m_max_hwp_supported; + return m_max_hwp_supported; } -uint32_t -NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + Error error; - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, wp_index = 0; - lldb::addr_t real_addr = addr; - - // Check if we are setting watchpoint other than read/write/access - // Also update watchpoint flag to match AArch64 write-read bit configuration. - switch (watch_flags) - { - case 1: - watch_flags = 2; - break; - case 2: - watch_flags = 1; - break; - case 3: - break; - default: - return LLDB_INVALID_INDEX32; - } + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - // Check if size has a valid hardware watchpoint length. - if (size != 1 && size != 2 && size != 4 && size != 8) - return LLDB_INVALID_INDEX32; - - // Check 8-byte alignment for hardware watchpoint target address. - // Below is a hack to recalculate address and size in order to - // make sure we can watch non 8-byte alligned addresses as well. - if (addr & 0x07) - { - uint8_t watch_mask = (addr & 0x07) + size; - - if (watch_mask > 0x08) - return LLDB_INVALID_INDEX32; - else if (watch_mask <= 0x02) - size = 2; - else if (watch_mask <= 0x04) - size = 4; - else - size = 8; - - addr = addr & (~0x07); - } + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + uint32_t control_value = 0, wp_index = 0; + lldb::addr_t real_addr = addr; + + // Check if we are setting watchpoint other than read/write/access + // Also update watchpoint flag to match AArch64 write-read bit configuration. + switch (watch_flags) { + case 1: + watch_flags = 2; + break; + case 2: + watch_flags = 1; + break; + case 3: + break; + default: + return LLDB_INVALID_INDEX32; + } - // Setup control value - control_value = watch_flags << 3; - control_value |= ((1 << size) - 1) << 5; - control_value |= (2 << 1) | 1; - - // Iterate over stored watchpoints - // Find a free wp_index or update reference count if duplicate. - wp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hwp_supported; i++) - { - if ((m_hwp_regs[i].control & 1) == 0) - { - wp_index = i; // Mark last free slot - } - else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) - { - wp_index = i; // Mark duplicate index - break; // Stop searching here - } + // Check if size has a valid hardware watchpoint length. + if (size != 1 && size != 2 && size != 4 && size != 8) + return LLDB_INVALID_INDEX32; + + // Check 8-byte alignment for hardware watchpoint target address. + // Below is a hack to recalculate address and size in order to + // make sure we can watch non 8-byte alligned addresses as well. + if (addr & 0x07) { + uint8_t watch_mask = (addr & 0x07) + size; + + if (watch_mask > 0x08) + return LLDB_INVALID_INDEX32; + else if (watch_mask <= 0x02) + size = 2; + else if (watch_mask <= 0x04) + size = 4; + else + size = 8; + + addr = addr & (~0x07); + } + + // Setup control value + control_value = watch_flags << 3; + control_value |= ((1 << size) - 1) << 5; + control_value |= (2 << 1) | 1; + + // Iterate over stored watchpoints + // Find a free wp_index or update reference count if duplicate. + wp_index = LLDB_INVALID_INDEX32; + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if ((m_hwp_regs[i].control & 1) == 0) { + wp_index = i; // Mark last free slot + } else if (m_hwp_regs[i].address == addr && + m_hwp_regs[i].control == control_value) { + wp_index = i; // Mark duplicate index + break; // Stop searching here } + } + + if (wp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; + + // Add new or update existing watchpoint + if ((m_hwp_regs[wp_index].control & 1) == 0) { + // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; + m_hwp_regs[wp_index].address = addr; + m_hwp_regs[wp_index].control = control_value; + m_hwp_regs[wp_index].refcount = 1; + + // PTRACE call to set corresponding watchpoint register. + error = WriteHardwareDebugRegs(eDREGTypeWATCH); - if (wp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Add new or update existing watchpoint - if ((m_hwp_regs[wp_index].control & 1) == 0) - { - // Update watchpoint in local cache - m_hwp_regs[wp_index].real_addr = real_addr; - m_hwp_regs[wp_index].address = addr; - m_hwp_regs[wp_index].control = control_value; - m_hwp_regs[wp_index].refcount = 1; - - // PTRACE call to set corresponding watchpoint register. - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) - { - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].refcount = 0; - - return LLDB_INVALID_INDEX32; - } + if (error.Fail()) { + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].control &= ~1; + m_hwp_regs[wp_index].refcount = 0; + + return LLDB_INVALID_INDEX32; } - else - m_hwp_regs[wp_index].refcount++; + } else + m_hwp_regs[wp_index].refcount++; - return wp_index; + return wp_index; } -bool -NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( + uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return false; + if (error.Fail()) + return false; - if (wp_index >= m_max_hwp_supported) - return false; + if (wp_index >= m_max_hwp_supported) + return false; - // Update reference count if multiple references. - if (m_hwp_regs[wp_index].refcount > 1) - { - m_hwp_regs[wp_index].refcount--; - return true; - } - else if (m_hwp_regs[wp_index].refcount == 1) - { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; - uint32_t tempControl = m_hwp_regs[wp_index].control; - uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].refcount = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) - { - m_hwp_regs[wp_index].control = tempControl; - m_hwp_regs[wp_index].address = tempAddr; - m_hwp_regs[wp_index].refcount = tempRefCount; - - return false; - } - - return true; + // Update reference count if multiple references. + if (m_hwp_regs[wp_index].refcount > 1) { + m_hwp_regs[wp_index].refcount--; + return true; + } else if (m_hwp_regs[wp_index].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; + uint32_t tempControl = m_hwp_regs[wp_index].control; + uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; + + // Update watchpoint in local cache + m_hwp_regs[wp_index].control &= ~1; + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].refcount = 0; + + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeWATCH); + + if (error.Fail()) { + m_hwp_regs[wp_index].control = tempControl; + m_hwp_regs[wp_index].address = tempAddr; + m_hwp_regs[wp_index].refcount = tempRefCount; + + return false; } - return false; + return true; + } + + return false; } -Error -NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - Error error; + Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo (); + // Read hardware breakpoint and watchpoint information. + error = ReadHardwareDebugInfo(); - if (error.Fail()) - return error; + if (error.Fail()) + return error; + + lldb::addr_t tempAddr = 0; + uint32_t tempControl = 0, tempRefCount = 0; + + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if (m_hwp_regs[i].control & 0x01) { + // Create a backup we can revert to in case of failure. + tempAddr = m_hwp_regs[i].address; + tempControl = m_hwp_regs[i].control; + tempRefCount = m_hwp_regs[i].refcount; - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0, tempRefCount = 0; - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) - { - if (m_hwp_regs[i].control & 0x01) - { - // Create a backup we can revert to in case of failure. - tempAddr = m_hwp_regs[i].address; - tempControl = m_hwp_regs[i].control; - tempRefCount = m_hwp_regs[i].refcount; - - // Clear watchpoints in local cache - m_hwp_regs[i].control &= ~1; - m_hwp_regs[i].address = 0; - m_hwp_regs[i].refcount = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) - { - m_hwp_regs[i].control = tempControl; - m_hwp_regs[i].address = tempAddr; - m_hwp_regs[i].refcount = tempRefCount; - - return error; - } - } + // Clear watchpoints in local cache + m_hwp_regs[i].control &= ~1; + m_hwp_regs[i].address = 0; + m_hwp_regs[i].refcount = 0; + + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeWATCH); + + if (error.Fail()) { + m_hwp_regs[i].control = tempControl; + m_hwp_regs[i].address = tempAddr; + m_hwp_regs[i].refcount = tempRefCount; + + return error; + } } + } - return Error(); + return Error(); } uint32_t -NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) - { - case 0x01: - return 1; - case 0x03: - return 2; - case 0x0f: - return 4; - case 0xff: - return 8; - default: - return 0; - } +NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { + case 0x01: + return 1; + case 0x03: + return 2; + case 0x0f: + return 4; + case 0xff: + return 8; + default: + return 0; + } +} +bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + + if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) + return true; + else + return false; } -bool -NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); +Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) - return true; - else - return false; -} + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); -Error -NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + uint32_t watch_size; + lldb::addr_t watch_addr; - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - uint32_t watch_size; - lldb::addr_t watch_addr; - - for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) - { - watch_size = GetWatchpointSize (wp_index); - watch_addr = m_hwp_regs[wp_index].address; - - if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) - && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) - { - m_hwp_regs[wp_index].hit_addr = trap_addr; - return Error(); - } + for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { + watch_size = GetWatchpointSize(wp_index); + watch_addr = m_hwp_regs[wp_index].address; + + if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) && + trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; + return Error(); } + } - wp_index = LLDB_INVALID_INDEX32; - return Error(); + wp_index = LLDB_INVALID_INDEX32; + return Error(); } lldb::addr_t -NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].real_addr; - else - return LLDB_INVALID_ADDRESS; + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; } lldb::addr_t -NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (uint32_t wp_index) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); +NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].hit_addr; - else - return LLDB_INVALID_ADDRESS; + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; + else + return LLDB_INVALID_ADDRESS; } -Error -NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() -{ - if (!m_refresh_hwdebug_info) - { - return Error(); - } - - ::pid_t tid = m_thread.GetID(); +Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { + if (!m_refresh_hwdebug_info) { + return Error(); + } - int regset = NT_ARM_HW_WATCH; - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - Error error; + ::pid_t tid = m_thread.GetID(); - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); + int regset = NT_ARM_HW_WATCH; + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + Error error; - if (error.Fail()) - return error; + ioVec.iov_base = &dreg_state; + ioVec.iov_len = sizeof(dreg_state); + error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, + &ioVec, ioVec.iov_len); - m_max_hwp_supported = dreg_state.dbg_info & 0xff; + if (error.Fail()) + return error; - regset = NT_ARM_HW_BREAK; - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); + m_max_hwp_supported = dreg_state.dbg_info & 0xff; - if (error.Fail()) - return error; - - m_max_hbp_supported = dreg_state.dbg_info & 0xff; - m_refresh_hwdebug_info = false; + regset = NT_ARM_HW_BREAK; + error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, + &ioVec, ioVec.iov_len); + if (error.Fail()) return error; + + m_max_hbp_supported = dreg_state.dbg_info & 0xff; + m_refresh_hwdebug_info = false; + + return error; } -Error -NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) -{ - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - Error error; - - memset (&dreg_state, 0, sizeof (dreg_state)); - ioVec.iov_base = &dreg_state; - - if (hwbType == eDREGTypeWATCH) - { - hwbType = NT_ARM_HW_WATCH; - ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) - + (sizeof (dreg_state.dbg_regs [0]) * m_max_hwp_supported); - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) - { - dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; - dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; - } +Error NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) { + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + Error error; + + memset(&dreg_state, 0, sizeof(dreg_state)); + ioVec.iov_base = &dreg_state; + + if (hwbType == eDREGTypeWATCH) { + hwbType = NT_ARM_HW_WATCH; + ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + + (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); + + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; + dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; } - else - { - hwbType = NT_ARM_HW_BREAK; - ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) - + (sizeof (dreg_state.dbg_regs [0]) * m_max_hbp_supported); - - for (uint32_t i = 0; i < m_max_hbp_supported; i++) - { - dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; - dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; - } + } else { + hwbType = NT_ARM_HW_BREAK; + ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + + (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); + + for (uint32_t i = 0; i < m_max_hbp_supported; i++) { + dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; + dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; } + } - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &hwbType, &ioVec, ioVec.iov_len); + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), + &hwbType, &ioVec, ioVec.iov_len); } -Error -NativeRegisterContextLinux_arm64::DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) -{ - Error error; - if (offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - error.SetErrorString("invalid offset value"); - return error; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); - if (error.Success()) - { - ArchSpec arch; - if (m_thread.GetProcess()->GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); - } +Error NativeRegisterContextLinux_arm64::DoReadRegisterValue( + uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) { + Error error; + if (offset > sizeof(struct user_pt_regs)) { + uintptr_t offset = offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) { + error.SetErrorString("invalid offset value"); + return error; } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); - if (error.Success()) - { - ArchSpec arch; - if (m_thread.GetProcess()->GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); - } + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + error = NativeProcessLinux::PtraceWrapper( + PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); + if (error.Success()) { + ArchSpec arch; + if (m_thread.GetProcess()->GetArchitecture(arch)) + value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, + arch.GetByteOrder()); + else + error.SetErrorString("failed to get architecture"); } - return error; -} + } else { + elf_gregset_t regs; + int regset = NT_PRSTATUS; + struct iovec ioVec; -Error -NativeRegisterContextLinux_arm64::DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) -{ - Error error; - ::pid_t tid = m_thread.GetID(); - if (offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - error.SetErrorString("invalid offset value"); - return error; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); - - if (error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 16); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); - } + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + error = NativeProcessLinux::PtraceWrapper( + PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); + if (error.Success()) { + ArchSpec arch; + if (m_thread.GetProcess()->GetArchitecture(arch)) + value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, + arch.GetByteOrder()); + else + error.SetErrorString("failed to get architecture"); } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); - if (error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 8); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); - } + } + return error; +} + +Error NativeRegisterContextLinux_arm64::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + Error error; + ::pid_t tid = m_thread.GetID(); + if (offset > sizeof(struct user_pt_regs)) { + uintptr_t offset = offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) { + error.SetErrorString("invalid offset value"); + return error; } - return error; -} + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, + &ioVec, sizeof regs); -Error -NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) -{ + if (error.Success()) { + ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), + 16); + error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, + &ioVec, sizeof regs); + } + } else { + elf_gregset_t regs; int regset = NT_PRSTATUS; struct iovec ioVec; - Error error; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, + &ioVec, sizeof regs); + if (error.Success()) { + ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), + 8); + error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, + &ioVec, sizeof regs); + } + } + return error; +} + +Error NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) { + int regset = NT_PRSTATUS; + struct iovec ioVec; + Error error; + + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), + ®set, &ioVec, buf_size); } -Error -NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) -{ - int regset = NT_PRSTATUS; - struct iovec ioVec; - Error error; +Error NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) { + int regset = NT_PRSTATUS; + struct iovec ioVec; + Error error; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), + ®set, &ioVec, buf_size); } -Error -NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) -{ - int regset = NT_FPREGSET; - struct iovec ioVec; - Error error; +Error NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) { + int regset = NT_FPREGSET; + struct iovec ioVec; + Error error; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), + ®set, &ioVec, buf_size); } -Error -NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) -{ - int regset = NT_FPREGSET; - struct iovec ioVec; - Error error; +Error NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) { + int regset = NT_FPREGSET; + struct iovec ioVec; + Error error; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); + ioVec.iov_base = buf; + ioVec.iov_len = buf_size; + return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), + ®set, &ioVec, buf_size); } -uint32_t -NativeRegisterContextLinux_arm64::CalculateFprOffset(const RegisterInfo* reg_info) const -{ - return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; +uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; } #endif // defined (__arm64__) || defined (__aarch64__) diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 4d9a9902ac3..c46c375acfe 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__arm64__) || defined (__aarch64__) +#if defined(__arm64__) || defined(__aarch64__) #ifndef lldb_NativeRegisterContextLinux_arm64_h #define lldb_NativeRegisterContextLinux_arm64_h @@ -18,180 +18,142 @@ namespace lldb_private { namespace process_linux { - class NativeProcessLinux; +class NativeProcessLinux; - class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux - { - public: - NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); +class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { +public: + NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); - uint32_t - GetRegisterSetCount () const override; + uint32_t GetRegisterSetCount() const override; - uint32_t - GetUserRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; - const RegisterSet * - GetRegisterSet (uint32_t set_index) const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - Error - ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override; + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - Error - WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - Error - ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - Error - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - //------------------------------------------------------------------ - // Hardware breakpoints/watchpoint mangement functions - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // Hardware breakpoints/watchpoint mangement functions + //------------------------------------------------------------------ - uint32_t - SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - bool - ClearHardwareBreakpoint (uint32_t hw_idx) override; + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - uint32_t - NumSupportedHardwareWatchpoints () override; + uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t - SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; - bool - ClearHardwareWatchpoint (uint32_t hw_index) override; + bool ClearHardwareWatchpoint(uint32_t hw_index) override; - Error - ClearAllHardwareWatchpoints () override; + Error ClearAllHardwareWatchpoints() override; - Error - GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; - lldb::addr_t - GetWatchpointHitAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - lldb::addr_t - GetWatchpointAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - uint32_t - GetWatchpointSize(uint32_t wp_index); + uint32_t GetWatchpointSize(uint32_t wp_index); - bool - WatchpointIsEnabled(uint32_t wp_index); + bool WatchpointIsEnabled(uint32_t wp_index); - // Debug register type select - enum DREGType - { - eDREGTypeWATCH = 0, - eDREGTypeBREAK - }; + // Debug register type select + enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK }; - protected: - Error - DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) override; +protected: + Error DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value) override; - Error - DoWriteRegisterValue(uint32_t offset, - const char* reg_name, + Error DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override; - Error - DoReadGPR(void *buf, size_t buf_size) override; + Error DoReadGPR(void *buf, size_t buf_size) override; - Error - DoWriteGPR(void *buf, size_t buf_size) override; + Error DoWriteGPR(void *buf, size_t buf_size) override; - Error - DoReadFPR(void *buf, size_t buf_size) override; + Error DoReadFPR(void *buf, size_t buf_size) override; - Error - DoWriteFPR(void *buf, size_t buf_size) override; + Error DoWriteFPR(void *buf, size_t buf_size) override; - void* - GetGPRBuffer() override { return &m_gpr_arm64; } + void *GetGPRBuffer() override { return &m_gpr_arm64; } - void* - GetFPRBuffer() override { return &m_fpr; } + void *GetFPRBuffer() override { return &m_fpr; } - size_t - GetFPRSize() override { return sizeof(m_fpr); } + size_t GetFPRSize() override { return sizeof(m_fpr); } - private: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; +private: + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; - uint32_t first_fpr_v; - uint32_t last_fpr_v; + uint32_t first_fpr_v; + uint32_t last_fpr_v; - uint32_t gpr_flags; - }; + uint32_t gpr_flags; + }; - // based on RegisterContextDarwin_arm64.h - struct VReg - { - uint8_t bytes[16]; - }; + // based on RegisterContextDarwin_arm64.h + struct VReg { + uint8_t bytes[16]; + }; - // based on RegisterContextDarwin_arm64.h - struct FPU - { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; + // based on RegisterContextDarwin_arm64.h + struct FPU { + VReg v[32]; + uint32_t fpsr; + uint32_t fpcr; + }; - uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose registers. - RegInfo m_reg_info; - FPU m_fpr; // floating-point registers including extended register sets. + uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose + // registers. + RegInfo m_reg_info; + FPU m_fpr; // floating-point registers including extended register sets. - // Debug register info for hardware breakpoints and watchpoints management. - struct DREG - { - lldb::addr_t address; // Breakpoint/watchpoint address value. - lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred. - lldb::addr_t real_addr; // Address value that should cause target to stop. - uint32_t control; // Breakpoint/watchpoint control value. - uint32_t refcount; // Serves as enable/disable and refernce counter. - }; + // Debug register info for hardware breakpoints and watchpoints management. + struct DREG { + lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception + // occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. + uint32_t control; // Breakpoint/watchpoint control value. + uint32_t refcount; // Serves as enable/disable and refernce counter. + }; - struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints - struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints + struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints + struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints - uint32_t m_max_hwp_supported; - uint32_t m_max_hbp_supported; - bool m_refresh_hwdebug_info; + uint32_t m_max_hwp_supported; + uint32_t m_max_hbp_supported; + bool m_refresh_hwdebug_info; - bool - IsGPR(unsigned reg) const; + bool IsGPR(unsigned reg) const; - bool - IsFPR(unsigned reg) const; + bool IsFPR(unsigned reg) const; - Error - ReadHardwareDebugInfo(); + Error ReadHardwareDebugInfo(); - Error - WriteHardwareDebugRegs(int hwbType); + Error WriteHardwareDebugRegs(int hwbType); - uint32_t - CalculateFprOffset(const RegisterInfo* reg_info) const; - }; + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index d5a61722da8..6c79537892b 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__mips__) +#if defined(__mips__) #include "NativeRegisterContextLinux_mips64.h" @@ -15,57 +15,49 @@ // C++ Includes // Other libraries and framework includes +#include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" -#include "lldb/Core/RegisterValue.h" #include "lldb/Core/Log.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Host/HostInfo.h" +#include "lldb/Core/RegisterValue.h" #include "lldb/Host/Host.h" -#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Host/HostInfo.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" #define NT_MIPS_MSA 0x600 #define CONFIG5_FRE (1 << 8) #define SR_FR (1 << 26) #define NUM_REGISTERS 32 -#include <sys/ptrace.h> #include <asm/ptrace.h> +#include <sys/ptrace.h> #ifndef PTRACE_GET_WATCH_REGS -enum pt_watch_style -{ - pt_watch_style_mips32, - pt_watch_style_mips64 -}; -struct mips32_watch_regs -{ - uint32_t watchlo[8]; - uint16_t watchhi[8]; - uint16_t watch_masks[8]; - uint32_t num_valid; +enum pt_watch_style { pt_watch_style_mips32, pt_watch_style_mips64 }; +struct mips32_watch_regs { + uint32_t watchlo[8]; + uint16_t watchhi[8]; + uint16_t watch_masks[8]; + uint32_t num_valid; } __attribute__((aligned(8))); -struct mips64_watch_regs -{ - uint64_t watchlo[8]; - uint16_t watchhi[8]; - uint16_t watch_masks[8]; - uint32_t num_valid; +struct mips64_watch_regs { + uint64_t watchlo[8]; + uint16_t watchhi[8]; + uint16_t watch_masks[8]; + uint32_t num_valid; } __attribute__((aligned(8))); -struct pt_watch_regs -{ - enum pt_watch_style style; - union - { - struct mips32_watch_regs mips32; - struct mips64_watch_regs mips64; - }; +struct pt_watch_regs { + enum pt_watch_style style; + union { + struct mips32_watch_regs mips32; + struct mips64_watch_regs mips64; + }; }; #define PTRACE_GET_WATCH_REGS 0xd0 @@ -76,7 +68,7 @@ struct pt_watch_regs #define R (1 << 1) #define I (1 << 2) -#define IRW (I | R | W) +#define IRW (I | R | W) struct pt_watch_regs default_watch_regs; @@ -87,1227 +79,993 @@ using namespace lldb_private::process_linux; // Private namespace. // ---------------------------------------------------------------------------- -namespace -{ - // mips general purpose registers. - const uint32_t - g_gp_regnums_mips[] = - { - gpr_zero_mips, - gpr_r1_mips, - gpr_r2_mips, - gpr_r3_mips, - gpr_r4_mips, - gpr_r5_mips, - gpr_r6_mips, - gpr_r7_mips, - gpr_r8_mips, - gpr_r9_mips, - gpr_r10_mips, - gpr_r11_mips, - gpr_r12_mips, - gpr_r13_mips, - gpr_r14_mips, - gpr_r15_mips, - gpr_r16_mips, - gpr_r17_mips, - gpr_r18_mips, - gpr_r19_mips, - gpr_r20_mips, - gpr_r21_mips, - gpr_r22_mips, - gpr_r23_mips, - gpr_r24_mips, - gpr_r25_mips, - gpr_r26_mips, - gpr_r27_mips, - gpr_gp_mips, - gpr_sp_mips, - gpr_r30_mips, - gpr_ra_mips, - gpr_sr_mips, - gpr_mullo_mips, - gpr_mulhi_mips, - gpr_badvaddr_mips, - gpr_cause_mips, - gpr_pc_mips, - gpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 == k_num_gpr_registers_mips, - "g_gp_regnums_mips has wrong number of register infos"); - - // mips floating point registers. - const uint32_t - g_fp_regnums_mips[] = - { - fpr_f0_mips, - fpr_f1_mips, - fpr_f2_mips, - fpr_f3_mips, - fpr_f4_mips, - fpr_f5_mips, - fpr_f6_mips, - fpr_f7_mips, - fpr_f8_mips, - fpr_f9_mips, - fpr_f10_mips, - fpr_f11_mips, - fpr_f12_mips, - fpr_f13_mips, - fpr_f14_mips, - fpr_f15_mips, - fpr_f16_mips, - fpr_f17_mips, - fpr_f18_mips, - fpr_f19_mips, - fpr_f20_mips, - fpr_f21_mips, - fpr_f22_mips, - fpr_f23_mips, - fpr_f24_mips, - fpr_f25_mips, - fpr_f26_mips, - fpr_f27_mips, - fpr_f28_mips, - fpr_f29_mips, - fpr_f30_mips, - fpr_f31_mips, - fpr_fcsr_mips, - fpr_fir_mips, - fpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 == k_num_fpr_registers_mips, - "g_fp_regnums_mips has wrong number of register infos"); - - // mips MSA registers. - const uint32_t - g_msa_regnums_mips[] = - { - msa_w0_mips, - msa_w1_mips, - msa_w2_mips, - msa_w3_mips, - msa_w4_mips, - msa_w5_mips, - msa_w6_mips, - msa_w7_mips, - msa_w8_mips, - msa_w9_mips, - msa_w10_mips, - msa_w11_mips, - msa_w12_mips, - msa_w13_mips, - msa_w14_mips, - msa_w15_mips, - msa_w16_mips, - msa_w17_mips, - msa_w18_mips, - msa_w19_mips, - msa_w20_mips, - msa_w21_mips, - msa_w22_mips, - msa_w23_mips, - msa_w24_mips, - msa_w25_mips, - msa_w26_mips, - msa_w27_mips, - msa_w28_mips, - msa_w29_mips, - msa_w30_mips, - msa_w31_mips, - msa_fcsr_mips, - msa_fir_mips, - msa_mcsr_mips, - msa_mir_mips, - msa_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) - 1 == k_num_msa_registers_mips, - "g_msa_regnums_mips has wrong number of register infos"); - - // mips64 general purpose registers. - const uint32_t - g_gp_regnums_mips64[] = - { - gpr_zero_mips64, - gpr_r1_mips64, - gpr_r2_mips64, - gpr_r3_mips64, - gpr_r4_mips64, - gpr_r5_mips64, - gpr_r6_mips64, - gpr_r7_mips64, - gpr_r8_mips64, - gpr_r9_mips64, - gpr_r10_mips64, - gpr_r11_mips64, - gpr_r12_mips64, - gpr_r13_mips64, - gpr_r14_mips64, - gpr_r15_mips64, - gpr_r16_mips64, - gpr_r17_mips64, - gpr_r18_mips64, - gpr_r19_mips64, - gpr_r20_mips64, - gpr_r21_mips64, - gpr_r22_mips64, - gpr_r23_mips64, - gpr_r24_mips64, - gpr_r25_mips64, - gpr_r26_mips64, - gpr_r27_mips64, - gpr_gp_mips64, - gpr_sp_mips64, - gpr_r30_mips64, - gpr_ra_mips64, - gpr_sr_mips64, - gpr_mullo_mips64, - gpr_mulhi_mips64, - gpr_badvaddr_mips64, - gpr_cause_mips64, - gpr_pc_mips64, - gpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) - 1 == k_num_gpr_registers_mips64, - "g_gp_regnums_mips64 has wrong number of register infos"); - - // mips64 floating point registers. - const uint32_t - g_fp_regnums_mips64[] = - { - fpr_f0_mips64, - fpr_f1_mips64, - fpr_f2_mips64, - fpr_f3_mips64, - fpr_f4_mips64, - fpr_f5_mips64, - fpr_f6_mips64, - fpr_f7_mips64, - fpr_f8_mips64, - fpr_f9_mips64, - fpr_f10_mips64, - fpr_f11_mips64, - fpr_f12_mips64, - fpr_f13_mips64, - fpr_f14_mips64, - fpr_f15_mips64, - fpr_f16_mips64, - fpr_f17_mips64, - fpr_f18_mips64, - fpr_f19_mips64, - fpr_f20_mips64, - fpr_f21_mips64, - fpr_f22_mips64, - fpr_f23_mips64, - fpr_f24_mips64, - fpr_f25_mips64, - fpr_f26_mips64, - fpr_f27_mips64, - fpr_f28_mips64, - fpr_f29_mips64, - fpr_f30_mips64, - fpr_f31_mips64, - fpr_fcsr_mips64, - fpr_fir_mips64, - fpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) - 1 == k_num_fpr_registers_mips64, - "g_fp_regnums_mips64 has wrong number of register infos"); - - // mips64 MSA registers. - const uint32_t - g_msa_regnums_mips64[] = - { - msa_w0_mips64, - msa_w1_mips64, - msa_w2_mips64, - msa_w3_mips64, - msa_w4_mips64, - msa_w5_mips64, - msa_w6_mips64, - msa_w7_mips64, - msa_w8_mips64, - msa_w9_mips64, - msa_w10_mips64, - msa_w11_mips64, - msa_w12_mips64, - msa_w13_mips64, - msa_w14_mips64, - msa_w15_mips64, - msa_w16_mips64, - msa_w17_mips64, - msa_w18_mips64, - msa_w19_mips64, - msa_w20_mips64, - msa_w21_mips64, - msa_w22_mips64, - msa_w23_mips64, - msa_w24_mips64, - msa_w25_mips64, - msa_w26_mips64, - msa_w27_mips64, - msa_w28_mips64, - msa_w29_mips64, - msa_w30_mips64, - msa_w31_mips64, - msa_fcsr_mips64, - msa_fir_mips64, - msa_mcsr_mips64, - msa_mir_mips64, - msa_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - - static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) - 1 == k_num_msa_registers_mips64, - "g_msa_regnums_mips64 has wrong number of register infos"); - - // Number of register sets provided by this context. - enum - { - k_num_register_sets = 3 - }; - - // Register sets for mips. - static const RegisterSet - g_reg_sets_mips[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_mips, g_gp_regnums_mips }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_mips, g_fp_regnums_mips }, - { "MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips } - }; - - // Register sets for mips64. - static const RegisterSet - g_reg_sets_mips64[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_mips64, g_gp_regnums_mips64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_mips64, g_fp_regnums_mips64 }, - { "MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64 }, - }; +namespace { +// mips general purpose registers. +const uint32_t g_gp_regnums_mips[] = { + gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips, + gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips, + gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips, + gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips, + gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips, + gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips, + gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips, + gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips, + gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips, + gpr_cause_mips, gpr_pc_mips, gpr_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 == + k_num_gpr_registers_mips, + "g_gp_regnums_mips has wrong number of register infos"); + +// mips floating point registers. +const uint32_t g_fp_regnums_mips[] = { + fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips, + fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips, + fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips, + fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips, + fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips, + fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips, + fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips, + fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips, + fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 == + k_num_fpr_registers_mips, + "g_fp_regnums_mips has wrong number of register infos"); + +// mips MSA registers. +const uint32_t g_msa_regnums_mips[] = { + msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips, + msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips, + msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips, + msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips, + msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips, + msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips, + msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips, + msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips, + msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips, + msa_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) - + 1 == + k_num_msa_registers_mips, + "g_msa_regnums_mips has wrong number of register infos"); + +// mips64 general purpose registers. +const uint32_t g_gp_regnums_mips64[] = { + gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, + gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64, + gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64, + gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, + gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, + gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64, + gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64, + gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, + gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, + gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64, + gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64, + gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, + gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) - + 1 == + k_num_gpr_registers_mips64, + "g_gp_regnums_mips64 has wrong number of register infos"); + +// mips64 floating point registers. +const uint32_t g_fp_regnums_mips64[] = { + fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64, + fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64, + fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64, + fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64, + fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64, + fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64, + fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64, + fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64, + fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) - + 1 == + k_num_fpr_registers_mips64, + "g_fp_regnums_mips64 has wrong number of register infos"); + +// mips64 MSA registers. +const uint32_t g_msa_regnums_mips64[] = { + msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64, + msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64, + msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64, + msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64, + msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64, + msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64, + msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64, + msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64, + msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64, + msa_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) - + 1 == + k_num_msa_registers_mips64, + "g_msa_regnums_mips64 has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_register_sets = 3 }; + +// Register sets for mips. +static const RegisterSet g_reg_sets_mips[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips, + g_gp_regnums_mips}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_mips, + g_fp_regnums_mips}, + {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}}; + +// Register sets for mips64. +static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, + g_gp_regnums_mips64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64, + g_fp_regnums_mips64}, + {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64}, +}; } // end of anonymous namespace -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - return new NativeRegisterContextLinux_mips64(target_arch, native_thread, concrete_frame_idx); +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextLinux_mips64(target_arch, native_thread, + concrete_frame_idx); } -#define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR_linux_mips) + sizeof(MSA_linux_mips)) +#define REG_CONTEXT_SIZE \ + (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR_linux_mips) + \ + sizeof(MSA_linux_mips)) // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_mips64 members. // ---------------------------------------------------------------------------- -static RegisterInfoInterface* -CreateRegisterInfoInterface(const ArchSpec& target_arch) -{ - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) - { - // 32-bit hosts run with a RegisterContextLinux_mips context. - return new RegisterContextLinux_mips(target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); - } - else - { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // mips64 hosts know how to work with 64-bit and 32-bit EXEs using the mips64 register context. - return new RegisterContextLinux_mips64 (target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); - } +static RegisterInfoInterface * +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { + // 32-bit hosts run with a RegisterContextLinux_mips context. + return new RegisterContextLinux_mips( + target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); + } else { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + // mips64 hosts know how to work with 64-bit and 32-bit EXEs using the + // mips64 register context. + return new RegisterContextLinux_mips64( + target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); + } } -NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) -{ - switch (target_arch.GetMachine ()) - { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - m_reg_info.num_registers = k_num_registers_mips; - m_reg_info.num_gpr_registers = k_num_gpr_registers_mips; - m_reg_info.num_fpr_registers = k_num_fpr_registers_mips; - m_reg_info.last_gpr = k_last_gpr_mips; - m_reg_info.first_fpr = k_first_fpr_mips; - m_reg_info.last_fpr = k_last_fpr_mips; - m_reg_info.first_msa = k_first_msa_mips; - m_reg_info.last_msa = k_last_msa_mips; - break; - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - m_reg_info.num_registers = k_num_registers_mips64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64; - m_reg_info.last_gpr = k_last_gpr_mips64; - m_reg_info.first_fpr = k_first_fpr_mips64; - m_reg_info.last_fpr = k_last_fpr_mips64; - m_reg_info.first_msa = k_first_msa_mips64; - m_reg_info.last_msa = k_last_msa_mips64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } +NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + CreateRegisterInfoInterface(target_arch)) { + switch (target_arch.GetMachine()) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + m_reg_info.num_registers = k_num_registers_mips; + m_reg_info.num_gpr_registers = k_num_gpr_registers_mips; + m_reg_info.num_fpr_registers = k_num_fpr_registers_mips; + m_reg_info.last_gpr = k_last_gpr_mips; + m_reg_info.first_fpr = k_first_fpr_mips; + m_reg_info.last_fpr = k_last_fpr_mips; + m_reg_info.first_msa = k_first_msa_mips; + m_reg_info.last_msa = k_last_msa_mips; + break; + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + m_reg_info.num_registers = k_num_registers_mips64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64; + m_reg_info.last_gpr = k_last_gpr_mips64; + m_reg_info.first_fpr = k_first_fpr_mips64; + m_reg_info.last_fpr = k_last_fpr_mips64; + m_reg_info.first_msa = k_first_msa_mips64; + m_reg_info.last_msa = k_last_msa_mips64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Initialize m_iovec to point to the buffer and buffer size + // using the conventions of Berkeley style UIO structures, as required + // by PTRACE extensions. + m_iovec.iov_base = &m_msa; + m_iovec.iov_len = sizeof(MSA_linux_mips); + + // init h/w watchpoint addr map + for (int index = 0; index <= MAX_NUM_WP; index++) + hw_addr_map[index] = LLDB_INVALID_ADDRESS; + + ::memset(&m_gpr, 0, sizeof(GPR_linux_mips)); + ::memset(&m_fpr, 0, sizeof(FPR_linux_mips)); + ::memset(&m_msa, 0, sizeof(MSA_linux_mips)); +} - // Initialize m_iovec to point to the buffer and buffer size - // using the conventions of Berkeley style UIO structures, as required - // by PTRACE extensions. - m_iovec.iov_base = &m_msa; - m_iovec.iov_len = sizeof(MSA_linux_mips); +uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const { + return k_num_register_sets; +} - // init h/w watchpoint addr map - for (int index = 0;index <= MAX_NUM_WP; index++) - hw_addr_map[index] = LLDB_INVALID_ADDRESS; +lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( + lldb::addr_t fail_value) { + Error error; + RegisterValue pc_value; + lldb::addr_t pc = fail_value; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - ::memset(&m_gpr, 0, sizeof(GPR_linux_mips)); - ::memset(&m_fpr, 0, sizeof(FPR_linux_mips)); - ::memset(&m_msa, 0, sizeof(MSA_linux_mips)); -} + if (log) + log->Printf("NativeRegisterContextLinux_mips64::%s Reading PC from " + "breakpoint location", + __FUNCTION__); -uint32_t -NativeRegisterContextLinux_mips64::GetRegisterSetCount () const -{ - return k_num_register_sets; -} + // PC register is at index 34 of the register array + const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64); + + error = ReadRegister(pc_info_p, pc_value); + if (error.Success()) { + pc = pc_value.GetAsUInt64(); + + // CAUSE register is at index 37 of the register array + const RegisterInfo *const cause_info_p = + GetRegisterInfoAtIndex(gpr_cause_mips64); + RegisterValue cause_value; + + ReadRegister(cause_info_p, cause_value); + + uint64_t cause = cause_value.GetAsUInt64(); -lldb::addr_t -NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation (lldb::addr_t fail_value) -{ - Error error; - RegisterValue pc_value; - lldb::addr_t pc = fail_value; - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("NativeRegisterContextLinux_mips64::%s Reading PC from breakpoint location", __FUNCTION__); - - // PC register is at index 34 of the register array - const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex (gpr_pc_mips64); - - error = ReadRegister (pc_info_p, pc_value); - if (error.Success ()) - { - pc = pc_value.GetAsUInt64 (); - - // CAUSE register is at index 37 of the register array - const RegisterInfo *const cause_info_p = GetRegisterInfoAtIndex (gpr_cause_mips64); - RegisterValue cause_value; - - ReadRegister (cause_info_p, cause_value); - - uint64_t cause = cause_value.GetAsUInt64 (); - - if (log) - log->Printf ("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64 " Cause 0x%" PRIx64, __FUNCTION__, pc, cause); - - /* - * The breakpoint might be in a delay slot. In this case PC points - * to the delayed branch instruction rather then the instruction - * in the delay slot. If the CAUSE.BD flag is set then adjust the - * PC based on the size of the branch instruction. - */ - if ((cause & (1 << 31)) != 0) - { - lldb::addr_t branch_delay = 0; - branch_delay = 4; // FIXME - Adjust according to size of branch instruction at PC - pc = pc + branch_delay; - pc_value.SetUInt64 (pc); - WriteRegister (pc_info_p, pc_value); - - if (log) - log->Printf ("NativeRegisterContextLinux_mips64::%s New PC 0x%" PRIx64, __FUNCTION__, pc); - } + log->Printf("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64 + " Cause 0x%" PRIx64, + __FUNCTION__, pc, cause); + + /* + * The breakpoint might be in a delay slot. In this case PC points + * to the delayed branch instruction rather then the instruction + * in the delay slot. If the CAUSE.BD flag is set then adjust the + * PC based on the size of the branch instruction. + */ + if ((cause & (1 << 31)) != 0) { + lldb::addr_t branch_delay = 0; + branch_delay = + 4; // FIXME - Adjust according to size of branch instruction at PC + pc = pc + branch_delay; + pc_value.SetUInt64(pc); + WriteRegister(pc_info_p, pc_value); + + if (log) + log->Printf("NativeRegisterContextLinux_mips64::%s New PC 0x%" PRIx64, + __FUNCTION__, pc); } + } - return pc; + return pc; } const RegisterSet * -NativeRegisterContextLinux_mips64::GetRegisterSet (uint32_t set_index) const -{ - if (set_index >= k_num_register_sets) - return nullptr; - - switch (GetRegisterInfoInterface ().GetTargetArchitecture ().GetMachine ()) - { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return &g_reg_sets_mips64[set_index]; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return &g_reg_sets_mips[set_index]; - default: - assert (false && "Unhandled target architecture."); - return nullptr; - } +NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const { + if (set_index >= k_num_register_sets) + return nullptr; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return &g_reg_sets_mips64[set_index]; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return &g_reg_sets_mips[set_index]; + default: + assert(false && "Unhandled target architecture."); return nullptr; + } + + return nullptr; } lldb_private::Error -NativeRegisterContextLinux_mips64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - Error error; - - if (!reg_info) - { - error.SetErrorString ("reg_info NULL"); - return error; - } +NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + Error error; - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - { - // This is likely an internal register for lldb use only and should not be directly queried. - error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name); - return error; - } + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } - if (IsMSA(reg) && !IsMSAAvailable()) - { - error.SetErrorString ("MSA not available on this processor"); - return error; - } + if (IsMSA(reg) && !IsMSAAvailable()) { + error.SetErrorString("MSA not available on this processor"); + return error; + } - if (IsMSA(reg) || IsFPR(reg)) - { - uint8_t *src; + if (IsMSA(reg) || IsFPR(reg)) { + uint8_t *src; - error = ReadCP1(); + error = ReadCP1(); - if (!error.Success()) - { - error.SetErrorString ("failed to read co-processor 1 register"); - return error; - } + if (!error.Success()) { + error.SetErrorString("failed to read co-processor 1 register"); + return error; + } - if (IsFPR(reg)) - { - assert (reg_info->byte_offset < sizeof(UserArea)); - src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); - } - else - { - assert (reg_info->byte_offset < sizeof(UserArea)); - src = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr)); - } - switch (reg_info->byte_size) - { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - case 16: - reg_value.SetBytes((const void *)src, 16, GetByteOrder()); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); - break; - } + if (IsFPR(reg)) { + assert(reg_info->byte_offset < sizeof(UserArea)); + src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); + } else { + assert(reg_info->byte_offset < sizeof(UserArea)); + src = (uint8_t *)&m_msa + reg_info->byte_offset - + (sizeof(m_gpr) + sizeof(m_fpr)); } - else - { - error = ReadRegisterRaw(reg, reg_value); + switch (reg_info->byte_size) { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + case 16: + reg_value.SetBytes((const void *)src, 16, GetByteOrder()); + break; + default: + assert(false && "Unhandled data size."); + error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, + reg_info->byte_size); + break; } + } else { + error = ReadRegisterRaw(reg, reg_value); + } - return error; + return error; } -lldb_private::Error -NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - Error error; +lldb_private::Error NativeRegisterContextLinux_mips64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + Error error; - assert (reg_info && "reg_info is null"); + assert(reg_info && "reg_info is null"); - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); + if (reg_index == LLDB_INVALID_REGNUM) + return Error("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : "<unknown register>"); - if (IsMSA(reg_index) && !IsMSAAvailable()) - { - error.SetErrorString ("MSA not available on this processor"); - return error; + if (IsMSA(reg_index) && !IsMSAAvailable()) { + error.SetErrorString("MSA not available on this processor"); + return error; + } + + if (IsFPR(reg_index) || IsMSA(reg_index)) { + uint8_t *dst; + uint64_t *src; + + // Initialise the FP and MSA buffers by reading all co-processor 1 registers + ReadCP1(); + + if (IsFPR(reg_index)) { + assert(reg_info->byte_offset < sizeof(UserArea)); + dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); + } else { + assert(reg_info->byte_offset < sizeof(UserArea)); + dst = (uint8_t *)&m_msa + reg_info->byte_offset - + (sizeof(m_gpr) + sizeof(m_fpr)); } - - if (IsFPR(reg_index) || IsMSA(reg_index)) - { - uint8_t *dst; - uint64_t *src; - - // Initialise the FP and MSA buffers by reading all co-processor 1 registers - ReadCP1(); - - if (IsFPR(reg_index)) - { - assert (reg_info->byte_offset < sizeof(UserArea)); - dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); - } - else - { - assert (reg_info->byte_offset < sizeof(UserArea)); - dst = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr)); - } - switch (reg_info->byte_size) - { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - case 16: - src = (uint64_t *)reg_value.GetBytes(); - *(uint64_t *)dst = *src; - *(uint64_t *)(dst + 8) = *(src + 1); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); - break; - } - error = WriteCP1(); - if (!error.Success()) - { - error.SetErrorString ("failed to write co-processor 1 register"); - return error; - } + switch (reg_info->byte_size) { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + case 16: + src = (uint64_t *)reg_value.GetBytes(); + *(uint64_t *)dst = *src; + *(uint64_t *)(dst + 8) = *(src + 1); + break; + default: + assert(false && "Unhandled data size."); + error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, + reg_info->byte_size); + break; } - else - { - error = WriteRegisterRaw(reg_index, reg_value); + error = WriteCP1(); + if (!error.Success()) { + error.SetErrorString("failed to write co-processor 1 register"); + return error; } + } else { + error = WriteRegisterRaw(reg_index, reg_value); + } - return error; + return error; } -Error -NativeRegisterContextLinux_mips64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - Error error; +Error NativeRegisterContextLinux_mips64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (!data_sp) - { - error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - return error; - } + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); + return error; + } - error = ReadGPR(); - if (!error.Success()) - { - error.SetErrorString ("ReadGPR() failed"); - return error; - } + error = ReadGPR(); + if (!error.Success()) { + error.SetErrorString("ReadGPR() failed"); + return error; + } - error = ReadCP1(); - if (!error.Success()) - { - error.SetErrorString ("ReadCP1() failed"); - return error; - } + error = ReadCP1(); + if (!error.Success()) { + error.SetErrorString("ReadCP1() failed"); + return error; + } - uint8_t *dst = data_sp->GetBytes (); - if (dst == nullptr) - { - error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); - return error; - } + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } - ::memcpy (dst, &m_gpr, GetRegisterInfoInterface ().GetGPRSize ()); - dst += GetRegisterInfoInterface ().GetGPRSize (); + ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize()); + dst += GetRegisterInfoInterface().GetGPRSize(); - ::memcpy (dst, &m_fpr, GetFPRSize ()); - dst += GetFPRSize (); + ::memcpy(dst, &m_fpr, GetFPRSize()); + dst += GetFPRSize(); - ::memcpy (dst, &m_msa, sizeof(MSA_linux_mips)); + ::memcpy(dst, &m_msa, sizeof(MSA_linux_mips)); - return error; + return error; } -Error -NativeRegisterContextLinux_mips64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - Error error; - - if (!data_sp) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s invalid data_sp provided", __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); - return error; - } +Error NativeRegisterContextLinux_mips64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_mips64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } - uint8_t *src = data_sp->GetBytes (); - if (src == nullptr) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } - - ::memcpy (&m_gpr, src, GetRegisterInfoInterface ().GetGPRSize ()); - src += GetRegisterInfoInterface ().GetGPRSize (); + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_mips64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_mips64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } - ::memcpy (&m_fpr, src, GetFPRSize ()); - src += GetFPRSize (); + ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize()); + src += GetRegisterInfoInterface().GetGPRSize(); - ::memcpy (&m_msa, src, sizeof(MSA_linux_mips)); + ::memcpy(&m_fpr, src, GetFPRSize()); + src += GetFPRSize(); - error = WriteGPR(); - if (!error.Success()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s WriteGPR() failed", __FUNCTION__); - return error; - } + ::memcpy(&m_msa, src, sizeof(MSA_linux_mips)); - error = WriteCP1(); - if (!error.Success()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s WriteCP1() failed", __FUNCTION__); - return error; - } + error = WriteGPR(); + if (!error.Success()) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_mips64::%s WriteGPR() failed", + __FUNCTION__); + return error; + } + error = WriteCP1(); + if (!error.Success()) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_mips64::%s WriteCP1() failed", + __FUNCTION__); return error; + } + + return error; } -Error -NativeRegisterContextLinux_mips64::ReadCP1() -{ - Error error; +Error NativeRegisterContextLinux_mips64::ReadCP1() { + Error error; - uint8_t *src, *dst; + uint8_t *src, *dst; - lldb::ByteOrder byte_order = GetByteOrder(); + lldb::ByteOrder byte_order = GetByteOrder(); - uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); + uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); - if (IsMSAAvailable()) - { - error = NativeRegisterContextLinux::ReadRegisterSet(&m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); - src = (uint8_t *)&m_msa + (IsBigEndian * 8); - dst = (uint8_t *)&m_fpr; - for ( int i = 0; i < NUM_REGISTERS; i++) - { - // Copy fp values from msa buffer fetched via ptrace - *(uint64_t *) dst = *(uint64_t *) src; - src = src + 16; - dst = dst + 8; - } - m_fpr.fir = m_msa.fir; - m_fpr.fcsr = m_msa.fcsr; - m_fpr.config5 = m_msa.config5; + if (IsMSAAvailable()) { + error = NativeRegisterContextLinux::ReadRegisterSet( + &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); + src = (uint8_t *)&m_msa + (IsBigEndian * 8); + dst = (uint8_t *)&m_fpr; + for (int i = 0; i < NUM_REGISTERS; i++) { + // Copy fp values from msa buffer fetched via ptrace + *(uint64_t *)dst = *(uint64_t *)src; + src = src + 16; + dst = dst + 8; } - else - { - error = NativeRegisterContextLinux::ReadFPR(); + m_fpr.fir = m_msa.fir; + m_fpr.fcsr = m_msa.fcsr; + m_fpr.config5 = m_msa.config5; + } else { + error = NativeRegisterContextLinux::ReadFPR(); + } + + // TODO: Add support for FRE + if (IsFR0()) { + src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); + dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); + for (int i = 0; i < (NUM_REGISTERS / 2); i++) { + // copy odd single from top of neighbouring even double + *(uint32_t *)dst = *(uint32_t *)src; + src = src + 16; + dst = dst + 16; } + } - // TODO: Add support for FRE - if (IsFR0()) - { - src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); - dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); - for (int i = 0; i < (NUM_REGISTERS / 2); i++) - { - // copy odd single from top of neighbouring even double - *(uint32_t *) dst = *(uint32_t *) src; - src = src + 16; - dst = dst + 16; - } - } - - return error; + return error; } -Error -NativeRegisterContextLinux_mips64::WriteCP1() -{ - Error error; - - uint8_t *src, *dst; +Error NativeRegisterContextLinux_mips64::WriteCP1() { + Error error; - lldb::ByteOrder byte_order = GetByteOrder(); + uint8_t *src, *dst; - uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); + lldb::ByteOrder byte_order = GetByteOrder(); - // TODO: Add support for FRE - if (IsFR0()) - { - src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); - dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); - for (int i = 0; i < (NUM_REGISTERS / 2); i++) - { - // copy odd single to top of neighbouring even double - *(uint32_t *) dst = *(uint32_t *) src; - src = src + 16; - dst = dst + 16; - } - } + uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); - if (IsMSAAvailable()) - { - dst = (uint8_t *)&m_msa + (IsBigEndian * 8); - src = (uint8_t *)&m_fpr; - for (int i = 0; i < NUM_REGISTERS; i++) - { - // Copy fp values to msa buffer for ptrace - *(uint64_t *) dst = *(uint64_t *) src; - dst = dst + 16; - src = src + 8; - } - m_msa.fir = m_fpr.fir; - m_msa.fcsr = m_fpr.fcsr; - m_msa.config5 = m_fpr.config5; - error = NativeRegisterContextLinux::WriteRegisterSet(&m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); + // TODO: Add support for FRE + if (IsFR0()) { + src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); + dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); + for (int i = 0; i < (NUM_REGISTERS / 2); i++) { + // copy odd single to top of neighbouring even double + *(uint32_t *)dst = *(uint32_t *)src; + src = src + 16; + dst = dst + 16; } - else - { - error = NativeRegisterContextLinux::WriteFPR(); + } + + if (IsMSAAvailable()) { + dst = (uint8_t *)&m_msa + (IsBigEndian * 8); + src = (uint8_t *)&m_fpr; + for (int i = 0; i < NUM_REGISTERS; i++) { + // Copy fp values to msa buffer for ptrace + *(uint64_t *)dst = *(uint64_t *)src; + dst = dst + 16; + src = src + 8; } - - return error; + m_msa.fir = m_fpr.fir; + m_msa.fcsr = m_fpr.fcsr; + m_msa.config5 = m_fpr.config5; + error = NativeRegisterContextLinux::WriteRegisterSet( + &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); + } else { + error = NativeRegisterContextLinux::WriteFPR(); + } + + return error; } -bool -NativeRegisterContextLinux_mips64::IsFR0() -{ - const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex (gpr_sr_mips64); +bool NativeRegisterContextLinux_mips64::IsFR0() { + const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex(gpr_sr_mips64); - RegisterValue reg_value; - ReadRegister (reg_info_p, reg_value); + RegisterValue reg_value; + ReadRegister(reg_info_p, reg_value); - uint64_t value = reg_value.GetAsUInt64(); + uint64_t value = reg_value.GetAsUInt64(); - return (!(value & SR_FR)); + return (!(value & SR_FR)); } -bool -NativeRegisterContextLinux_mips64::IsFRE() -{ - const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex (gpr_config5_mips64); +bool NativeRegisterContextLinux_mips64::IsFRE() { + const RegisterInfo *const reg_info_p = + GetRegisterInfoAtIndex(gpr_config5_mips64); - RegisterValue reg_value; - ReadRegister (reg_info_p, reg_value); + RegisterValue reg_value; + ReadRegister(reg_info_p, reg_value); - uint64_t config5 = reg_value.GetAsUInt64(); + uint64_t config5 = reg_value.GetAsUInt64(); - return (config5 & CONFIG5_FRE); + return (config5 & CONFIG5_FRE); } -bool -NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const -{ - return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); +bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const { + return (m_reg_info.first_fpr <= reg_index && + reg_index <= m_reg_info.last_fpr); } -static uint32_t -GetWatchHi (struct pt_watch_regs *regs, uint32_t index) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watchhi[index]; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watchhi[index]; - if(log) - log->Printf("Invalid watch register style"); - return 0; +static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + return regs->mips32.watchhi[index]; + else if (regs->style == pt_watch_style_mips64) + return regs->mips64.watchhi[index]; + if (log) + log->Printf("Invalid watch register style"); + return 0; } -static void -SetWatchHi (struct pt_watch_regs *regs, uint32_t index, uint16_t value) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - regs->mips32.watchhi[index] = value; - else if (regs->style == pt_watch_style_mips64) - regs->mips64.watchhi[index] = value; - if(log) - log->Printf("Invalid watch register style"); - return; +static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index, + uint16_t value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + regs->mips32.watchhi[index] = value; + else if (regs->style == pt_watch_style_mips64) + regs->mips64.watchhi[index] = value; + if (log) + log->Printf("Invalid watch register style"); + return; } -static lldb::addr_t -GetWatchLo (struct pt_watch_regs *regs, uint32_t index) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watchlo[index]; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watchlo[index]; - if(log) - log->Printf("Invalid watch register style"); - return LLDB_INVALID_ADDRESS; +static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + return regs->mips32.watchlo[index]; + else if (regs->style == pt_watch_style_mips64) + return regs->mips64.watchlo[index]; + if (log) + log->Printf("Invalid watch register style"); + return LLDB_INVALID_ADDRESS; } -static void -SetWatchLo (struct pt_watch_regs *regs, uint32_t index, uint64_t value) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - regs->mips32.watchlo[index] = (uint32_t) value; - else if (regs->style == pt_watch_style_mips64) - regs->mips64.watchlo[index] = value; - if(log) - log->Printf("Invalid watch register style"); - return; +static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index, + uint64_t value) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + regs->mips32.watchlo[index] = (uint32_t)value; + else if (regs->style == pt_watch_style_mips64) + regs->mips64.watchlo[index] = value; + if (log) + log->Printf("Invalid watch register style"); + return; } -static uint32_t -GetIRWMask (struct pt_watch_regs *regs, uint32_t index) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watch_masks[index] & IRW; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watch_masks[index] & IRW; - if(log) - log->Printf("Invalid watch register style"); - return 0; +static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + return regs->mips32.watch_masks[index] & IRW; + else if (regs->style == pt_watch_style_mips64) + return regs->mips64.watch_masks[index] & IRW; + if (log) + log->Printf("Invalid watch register style"); + return 0; } -static uint32_t -GetRegMask (struct pt_watch_regs *regs, uint32_t index) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watch_masks[index] & ~IRW; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watch_masks[index] & ~IRW; - if(log) - log->Printf("Invalid watch register style"); - return 0; +static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (regs->style == pt_watch_style_mips32) + return regs->mips32.watch_masks[index] & ~IRW; + else if (regs->style == pt_watch_style_mips64) + return regs->mips64.watch_masks[index] & ~IRW; + if (log) + log->Printf("Invalid watch register style"); + return 0; } -static lldb::addr_t -GetRangeMask (lldb::addr_t mask) -{ - lldb::addr_t mask_bit = 1; - while (mask_bit < mask) - { - mask = mask | mask_bit; - mask_bit <<= 1; - } - return mask; +static lldb::addr_t GetRangeMask(lldb::addr_t mask) { + lldb::addr_t mask_bit = 1; + while (mask_bit < mask) { + mask = mask | mask_bit; + mask_bit <<= 1; + } + return mask; } -static int -GetVacantWatchIndex (struct pt_watch_regs *regs, lldb::addr_t addr, uint32_t size, uint32_t irw, uint32_t num_valid) -{ - lldb::addr_t last_byte = addr + size - 1; - lldb::addr_t mask = GetRangeMask (addr ^ last_byte) | IRW; - lldb::addr_t base_addr = addr & ~mask; - - // Check if this address is already watched by previous watch points. - lldb::addr_t lo; - uint16_t hi; - uint32_t vacant_watches = 0; - for (uint32_t index = 0; index < num_valid; index++) - { - lo = GetWatchLo (regs, index); - if (lo != 0 && irw == ((uint32_t) lo & irw)) - { - hi = GetWatchHi (regs, index) | IRW; - lo &= ~(lldb::addr_t) hi; - if (addr >= lo && last_byte <= (lo + hi)) - return index; +static int GetVacantWatchIndex(struct pt_watch_regs *regs, lldb::addr_t addr, + uint32_t size, uint32_t irw, + uint32_t num_valid) { + lldb::addr_t last_byte = addr + size - 1; + lldb::addr_t mask = GetRangeMask(addr ^ last_byte) | IRW; + lldb::addr_t base_addr = addr & ~mask; + + // Check if this address is already watched by previous watch points. + lldb::addr_t lo; + uint16_t hi; + uint32_t vacant_watches = 0; + for (uint32_t index = 0; index < num_valid; index++) { + lo = GetWatchLo(regs, index); + if (lo != 0 && irw == ((uint32_t)lo & irw)) { + hi = GetWatchHi(regs, index) | IRW; + lo &= ~(lldb::addr_t)hi; + if (addr >= lo && last_byte <= (lo + hi)) + return index; + } else + vacant_watches++; + } + + // Now try to find a vacant index + if (vacant_watches > 0) { + vacant_watches = 0; + for (uint32_t index = 0; index < num_valid; index++) { + lo = GetWatchLo(regs, index); + if (lo == 0 && irw == (GetIRWMask(regs, index) & irw)) { + if (mask <= (GetRegMask(regs, index) | IRW)) { + // It fits, we can use it. + SetWatchLo(regs, index, base_addr | irw); + SetWatchHi(regs, index, mask & ~IRW); + return index; + } else { + // It doesn't fit, but has the proper IRW capabilities + vacant_watches++; } - else - vacant_watches++; + } } - // Now try to find a vacant index - if(vacant_watches > 0) - { - vacant_watches = 0; - for (uint32_t index = 0; index < num_valid; index++) - { - lo = GetWatchLo (regs, index); - if (lo == 0 - && irw == (GetIRWMask (regs, index) & irw)) - { - if (mask <= (GetRegMask (regs, index) | IRW)) - { - // It fits, we can use it. - SetWatchLo (regs, index, base_addr | irw); - SetWatchHi (regs, index, mask & ~IRW); - return index; - } - else - { - // It doesn't fit, but has the proper IRW capabilities - vacant_watches++; - } - } - } - - if (vacant_watches > 1) - { - // Split this watchpoint accross several registers - struct pt_watch_regs regs_copy; - regs_copy = *regs; - lldb::addr_t break_addr; - uint32_t segment_size; - for (uint32_t index = 0; index < num_valid; index++) - { - lo = GetWatchLo (®s_copy, index); - hi = GetRegMask (®s_copy, index) | IRW; - if (lo == 0 && irw == (hi & irw)) - { - lo = addr & ~(lldb::addr_t) hi; - break_addr = lo + hi + 1; - if (break_addr >= addr + size) - segment_size = size; - else - segment_size = break_addr - addr; - mask = GetRangeMask (addr ^ (addr + segment_size - 1)); - SetWatchLo (®s_copy, index, (addr & ~mask) | irw); - SetWatchHi (®s_copy, index, mask & ~IRW); - if (break_addr >= addr + size) - { - *regs = regs_copy; - return index; - } - size = addr + size - break_addr; - addr = break_addr; - } - } + if (vacant_watches > 1) { + // Split this watchpoint accross several registers + struct pt_watch_regs regs_copy; + regs_copy = *regs; + lldb::addr_t break_addr; + uint32_t segment_size; + for (uint32_t index = 0; index < num_valid; index++) { + lo = GetWatchLo(®s_copy, index); + hi = GetRegMask(®s_copy, index) | IRW; + if (lo == 0 && irw == (hi & irw)) { + lo = addr & ~(lldb::addr_t)hi; + break_addr = lo + hi + 1; + if (break_addr >= addr + size) + segment_size = size; + else + segment_size = break_addr - addr; + mask = GetRangeMask(addr ^ (addr + segment_size - 1)); + SetWatchLo(®s_copy, index, (addr & ~mask) | irw); + SetWatchHi(®s_copy, index, mask & ~IRW); + if (break_addr >= addr + size) { + *regs = regs_copy; + return index; + } + size = addr + size - break_addr; + addr = break_addr; } + } } - return LLDB_INVALID_INDEX32; + } + return LLDB_INVALID_INDEX32; } -bool -NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const -{ - return (m_reg_info.first_msa <= reg_index && reg_index <= m_reg_info.last_msa); +bool NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const { + return (m_reg_info.first_msa <= reg_index && + reg_index <= m_reg_info.last_msa); } -bool -NativeRegisterContextLinux_mips64::IsMSAAvailable() -{ - MSA_linux_mips msa_buf; - unsigned int regset = NT_MIPS_MSA; +bool NativeRegisterContextLinux_mips64::IsMSAAvailable() { + MSA_linux_mips msa_buf; + unsigned int regset = NT_MIPS_MSA; - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, Host::GetCurrentProcessID(), static_cast<void *>(®set), &msa_buf, sizeof(MSA_linux_mips)); + Error error = NativeProcessLinux::PtraceWrapper( + PTRACE_GETREGSET, Host::GetCurrentProcessID(), + static_cast<void *>(®set), &msa_buf, sizeof(MSA_linux_mips)); - if (error.Success() && msa_buf.mir) - { - return true; - } + if (error.Success() && msa_buf.mir) { + return true; + } - return false; + return false; } -Error -NativeRegisterContextLinux_mips64::IsWatchpointHit (uint32_t wp_index, bool &is_hit) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); - - // reading the current state of watch regs - struct pt_watch_regs watch_readback; - Error error = DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback)); - - if (GetWatchHi (&watch_readback, wp_index) & (IRW)) - { - // clear hit flag in watchhi - SetWatchHi (&watch_readback, wp_index, (GetWatchHi (&watch_readback, wp_index) & ~(IRW))); - DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback)); - - is_hit = true; - return error; - } - is_hit = false; +Error NativeRegisterContextLinux_mips64::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + // reading the current state of watch regs + struct pt_watch_regs watch_readback; + Error error = DoReadWatchPointRegisterValue( + m_thread.GetID(), static_cast<void *>(&watch_readback)); + + if (GetWatchHi(&watch_readback, wp_index) & (IRW)) { + // clear hit flag in watchhi + SetWatchHi(&watch_readback, wp_index, + (GetWatchHi(&watch_readback, wp_index) & ~(IRW))); + DoWriteWatchPointRegisterValue(m_thread.GetID(), + static_cast<void *>(&watch_readback)); + + is_hit = true; return error; + } + is_hit = false; + return error; } -Error -NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) { - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) - { - bool is_hit; - Error error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) { - wp_index = LLDB_INVALID_INDEX32; - } else if (is_hit) { - return error; - } +Error NativeRegisterContextLinux_mips64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + } else if (is_hit) { + return error; } - wp_index = LLDB_INVALID_INDEX32; - return Error(); + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); } -Error -NativeRegisterContextLinux_mips64::IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) -{ - is_vacant = false; - return Error("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointVacant not implemented"); +Error NativeRegisterContextLinux_mips64::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + is_vacant = false; + return Error("MIPS TODO: " + "NativeRegisterContextLinux_mips64::IsWatchpointVacant not " + "implemented"); } -bool -NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; - - struct pt_watch_regs regs; - // First reading the current state of watch regs - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(®s)); - - if (regs.style == pt_watch_style_mips32) - { - regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index]; - regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index]; - regs.mips32.watch_masks[wp_index] = default_watch_regs.mips32.watch_masks[wp_index]; - } - else // pt_watch_style_mips64 - { - regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index]; - regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index]; - regs.mips64.watch_masks[wp_index] = default_watch_regs.mips64.watch_masks[wp_index]; - } - - Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - if(!error.Fail()) - { - hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS; - return true; - } +bool NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint( + uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) return false; + + struct pt_watch_regs regs; + // First reading the current state of watch regs + DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); + + if (regs.style == pt_watch_style_mips32) { + regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index]; + regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index]; + regs.mips32.watch_masks[wp_index] = + default_watch_regs.mips32.watch_masks[wp_index]; + } else // pt_watch_style_mips64 + { + regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index]; + regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index]; + regs.mips64.watch_masks[wp_index] = + default_watch_regs.mips64.watch_masks[wp_index]; + } + + Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(), + static_cast<void *>(®s)); + if (!error.Fail()) { + hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS; + return true; + } + return false; } -Error -NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() -{ - return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs)); +Error NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() { + return DoWriteWatchPointRegisterValue( + m_thread.GetID(), static_cast<void *>(&default_watch_regs)); } -Error -NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex ( - lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) -{ - Error error; - error.SetErrorString ("MIPS TODO: NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex not implemented"); - return error; +Error NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex( + lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { + Error error; + error.SetErrorString("MIPS TODO: " + "NativeRegisterContextLinux_mips64::" + "SetHardwareWatchpointWithIndex not implemented"); + return error; } -uint32_t -NativeRegisterContextLinux_mips64::SetHardwareWatchpoint ( - lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - struct pt_watch_regs regs; +uint32_t NativeRegisterContextLinux_mips64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + struct pt_watch_regs regs; - // First reading the current state of watch regs - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); + // First reading the current state of watch regs + DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - // Try if a new watch point fits in this state - int index = GetVacantWatchIndex (®s, addr, size, watch_flags, NumSupportedHardwareWatchpoints()); + // Try if a new watch point fits in this state + int index = GetVacantWatchIndex(®s, addr, size, watch_flags, + NumSupportedHardwareWatchpoints()); - // New watchpoint doesn't fit - if (index == LLDB_INVALID_INDEX32) + // New watchpoint doesn't fit + if (index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; + // It fits, so we go ahead with updating the state of watch regs + DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - // It fits, so we go ahead with updating the state of watch regs - DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - - // Storing exact address - hw_addr_map[index] = addr; - return index; + // Storing exact address + hw_addr_map[index] = addr; + return index; } lldb::addr_t -NativeRegisterContextLinux_mips64::GetWatchpointAddress (uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; +NativeRegisterContextLinux_mips64::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; - return hw_addr_map[wp_index]; + return hw_addr_map[wp_index]; } -struct EmulatorBaton -{ - lldb::addr_t m_watch_hit_addr; - NativeProcessLinux* m_process; - NativeRegisterContext* m_reg_context; - - EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) : - m_watch_hit_addr(LLDB_INVALID_ADDRESS), - m_process(process), - m_reg_context(reg_context) - {} +struct EmulatorBaton { + lldb::addr_t m_watch_hit_addr; + NativeProcessLinux *m_process; + NativeRegisterContext *m_reg_context; + + EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) + : m_watch_hit_addr(LLDB_INVALID_ADDRESS), m_process(process), + m_reg_context(reg_context) {} }; -static size_t -ReadMemoryCallback (EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, lldb::addr_t addr, - void *dst, size_t length) -{ - size_t bytes_read; - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); - emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); - return bytes_read; +static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, void *dst, size_t length) { + size_t bytes_read; + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); + return bytes_read; } -static size_t -WriteMemoryCallback (EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, const void *dst, size_t length) -{ - return length; +static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, const void *dst, + size_t length) { + return length; } -static bool -ReadRegisterCallback (EmulateInstruction *instruction, void *baton, - const RegisterInfo *reg_info, RegisterValue ®_value) -{ - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); +static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( - lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]); + const RegisterInfo *full_reg_info = + emulator_baton->m_reg_context->GetRegisterInfo( + lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]); - Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); - if (error.Success()) - return true; + Error error = + emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + if (error.Success()) + return true; - return false; + return false; } -static bool -WriteRegisterCallback (EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) - { - EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); - emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64 (); - } +static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64(); + } - return true; + return true; } /* @@ -1319,123 +1077,121 @@ WriteRegisterCallback (EmulateInstruction *instruction, void *baton, * it can decide to stop or continue the thread. */ lldb::addr_t -NativeRegisterContextLinux_mips64::GetWatchpointHitAddress (uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; +NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; - lldb_private::ArchSpec arch; - arch = GetRegisterInfoInterface().GetTargetArchitecture(); - std::unique_ptr<EmulateInstruction> emulator_ap( - EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny, nullptr)); - - if (emulator_ap == nullptr) - return LLDB_INVALID_ADDRESS; - - EmulatorBaton baton(static_cast<NativeProcessLinux*>(m_thread.GetProcess().get()), this); - emulator_ap->SetBaton (&baton); - emulator_ap->SetReadMemCallback (&ReadMemoryCallback); - emulator_ap->SetReadRegCallback (&ReadRegisterCallback); - emulator_ap->SetWriteMemCallback (&WriteMemoryCallback); - emulator_ap->SetWriteRegCallback (&WriteRegisterCallback); - - if (!emulator_ap->ReadInstruction()) - return LLDB_INVALID_ADDRESS; - - if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone)) - return baton.m_watch_hit_addr; + lldb_private::ArchSpec arch; + arch = GetRegisterInfoInterface().GetTargetArchitecture(); + std::unique_ptr<EmulateInstruction> emulator_ap( + EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny, + nullptr)); + + if (emulator_ap == nullptr) + return LLDB_INVALID_ADDRESS; + EmulatorBaton baton( + static_cast<NativeProcessLinux *>(m_thread.GetProcess().get()), this); + emulator_ap->SetBaton(&baton); + emulator_ap->SetReadMemCallback(&ReadMemoryCallback); + emulator_ap->SetReadRegCallback(&ReadRegisterCallback); + emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); + emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); + + if (!emulator_ap->ReadInstruction()) return LLDB_INVALID_ADDRESS; + + if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone)) + return baton.m_watch_hit_addr; + + return LLDB_INVALID_ADDRESS; } -uint32_t -NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints () -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - struct pt_watch_regs regs; - static int num_valid = 0; - if (!num_valid) - { - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - default_watch_regs = regs; // Keeping default watch regs values for future use - switch (regs.style) - { - case pt_watch_style_mips32: - num_valid = regs.mips32.num_valid; // Using num_valid as cache - return num_valid; - case pt_watch_style_mips64: - num_valid = regs.mips64.num_valid; - return num_valid; - default: - if(log) - log->Printf("NativeRegisterContextLinux_mips64::%s Error: Unrecognized watch register style", __FUNCTION__); - } - return 0; +uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + struct pt_watch_regs regs; + static int num_valid = 0; + if (!num_valid) { + DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); + default_watch_regs = + regs; // Keeping default watch regs values for future use + switch (regs.style) { + case pt_watch_style_mips32: + num_valid = regs.mips32.num_valid; // Using num_valid as cache + return num_valid; + case pt_watch_style_mips64: + num_valid = regs.mips64.num_valid; + return num_valid; + default: + if (log) + log->Printf("NativeRegisterContextLinux_mips64::%s Error: Unrecognized " + "watch register style", + __FUNCTION__); } - return num_valid; + return 0; + } + return num_valid; } -Error -NativeRegisterContextLinux_mips64::DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) -{ - GPR_linux_mips regs; - ::memset(®s, 0, sizeof(GPR_linux_mips)); - - // Clear all bits in RegisterValue before writing actual value read from ptrace to avoid garbage value in 32-bit MSB - value.SetBytes((void *)(((unsigned char *)®s) + offset), 8, GetByteOrder()); - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); - if (error.Success()) - { - lldb_private::ArchSpec arch; - if (m_thread.GetProcess()->GetArchitecture(arch)) - { - void* target_address = ((uint8_t*)®s) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips); - uint32_t target_size; - if ((::strcmp(reg_name, "sr") == 0) || (::strcmp(reg_name, "cause") == 0) || (::strcmp(reg_name, "config5") == 0)) - target_size = 4; - else - target_size = arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8; - value.SetBytes(target_address, target_size, arch.GetByteOrder()); - } - else - error.SetErrorString("failed to get architecture"); - } - return error; +Error NativeRegisterContextLinux_mips64::DoReadRegisterValue( + uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) { + GPR_linux_mips regs; + ::memset(®s, 0, sizeof(GPR_linux_mips)); + + // Clear all bits in RegisterValue before writing actual value read from + // ptrace to avoid garbage value in 32-bit MSB + value.SetBytes((void *)(((unsigned char *)®s) + offset), 8, + GetByteOrder()); + Error error = NativeProcessLinux::PtraceWrapper( + PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + if (error.Success()) { + lldb_private::ArchSpec arch; + if (m_thread.GetProcess()->GetArchitecture(arch)) { + void *target_address = ((uint8_t *)®s) + offset + + 4 * (arch.GetMachine() == llvm::Triple::mips); + uint32_t target_size; + if ((::strcmp(reg_name, "sr") == 0) || + (::strcmp(reg_name, "cause") == 0) || + (::strcmp(reg_name, "config5") == 0)) + target_size = 4; + else + target_size = + arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8; + value.SetBytes(target_address, target_size, arch.GetByteOrder()); + } else + error.SetErrorString("failed to get architecture"); + } + return error; } -Error -NativeRegisterContextLinux_mips64::DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) -{ - GPR_linux_mips regs; - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); - if (error.Success()) - { - lldb_private::ArchSpec arch; - if (m_thread.GetProcess()->GetArchitecture(arch)) - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); - } - else - error.SetErrorString("failed to get architecture"); - } - return error; +Error NativeRegisterContextLinux_mips64::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + GPR_linux_mips regs; + Error error = NativeProcessLinux::PtraceWrapper( + PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + if (error.Success()) { + lldb_private::ArchSpec arch; + if (m_thread.GetProcess()->GetArchitecture(arch)) { + ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), + arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8); + error = NativeProcessLinux::PtraceWrapper( + PTRACE_SETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + } else + error.SetErrorString("failed to get architecture"); + } + return error; } -Error -NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback) -{ - return NativeProcessLinux::PtraceWrapper( PTRACE_GET_WATCH_REGS, m_thread.GetID(), watch_readback); +Error NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue( + lldb::tid_t tid, void *watch_readback) { + return NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS, + m_thread.GetID(), watch_readback); } -Error -NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue(lldb::tid_t tid, void* watch_reg_value) -{ - return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS, m_thread.GetID(), watch_reg_value); +Error NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue( + lldb::tid_t tid, void *watch_reg_value) { + return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS, + m_thread.GetID(), watch_reg_value); } #endif // defined (__mips__) diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h index 9368645116e..ef17942c04f 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__mips__) +#if defined(__mips__) #ifndef lldb_NativeRegisterContextLinux_mips64_h #define lldb_NativeRegisterContextLinux_mips64_h @@ -21,143 +21,111 @@ namespace lldb_private { namespace process_linux { - class NativeProcessLinux; +class NativeProcessLinux; - class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux - { - public: - NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); +class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { +public: + NativeRegisterContextLinux_mips64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); - uint32_t - GetRegisterSetCount () const override; + uint32_t GetRegisterSetCount() const override; - lldb::addr_t - GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override; + lldb::addr_t GetPCfromBreakpointLocation( + lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override; - lldb::addr_t - GetWatchpointHitAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - const RegisterSet * - GetRegisterSet (uint32_t set_index) const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - Error - ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override; + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - Error - WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - Error - ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - Error - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - Error - ReadCP1(); + Error ReadCP1(); - Error - WriteCP1(); + Error WriteCP1(); - Error - IsWatchpointHit (uint32_t wp_index, bool &is_hit) override; + Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - Error - GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; - Error - IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) override; + Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - bool - ClearHardwareWatchpoint (uint32_t wp_index) override; + bool ClearHardwareWatchpoint(uint32_t wp_index) override; - Error - ClearAllHardwareWatchpoints () override; + Error ClearAllHardwareWatchpoints() override; - Error - SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size, - uint32_t watch_flags, uint32_t wp_index); + Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, + uint32_t watch_flags, uint32_t wp_index); - uint32_t - SetHardwareWatchpoint (lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; - lldb::addr_t - GetWatchpointAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - uint32_t - NumSupportedHardwareWatchpoints () override; + uint32_t NumSupportedHardwareWatchpoints() override; - static bool - IsMSAAvailable(); + static bool IsMSAAvailable(); - protected: - Error - DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) override; +protected: + Error DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value) override; - Error - DoWriteRegisterValue(uint32_t offset, - const char* reg_name, + Error DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override; - Error - DoReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback); + Error DoReadWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback); - Error - DoWriteWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback); + Error DoWriteWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback); - bool - IsFR0(); + bool IsFR0(); - bool - IsFRE(); + bool IsFRE(); - bool - IsFPR(uint32_t reg_index) const; + bool IsFPR(uint32_t reg_index) const; - bool - IsMSA(uint32_t reg_index) const; + bool IsMSA(uint32_t reg_index) const; - void* - GetGPRBuffer() override { return &m_gpr; } + void *GetGPRBuffer() override { return &m_gpr; } - void* - GetFPRBuffer() override { return &m_fpr; } + void *GetFPRBuffer() override { return &m_fpr; } - size_t - GetFPRSize() override { return sizeof(FPR_linux_mips); } + size_t GetFPRSize() override { return sizeof(FPR_linux_mips); } - private: - // Info about register ranges. - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; +private: + // Info about register ranges. + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - uint32_t first_msa; - uint32_t last_msa; - }; + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + uint32_t first_msa; + uint32_t last_msa; + }; - RegInfo m_reg_info; + RegInfo m_reg_info; - GPR_linux_mips m_gpr; + GPR_linux_mips m_gpr; - FPR_linux_mips m_fpr; + FPR_linux_mips m_fpr; - MSA_linux_mips m_msa; + MSA_linux_mips m_msa; - lldb::addr_t hw_addr_map[MAX_NUM_WP]; + lldb::addr_t hw_addr_map[MAX_NUM_WP]; - IOVEC_mips m_iovec; - }; + IOVEC_mips m_iovec; +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp index b09ad400d90..7ec4dc551fa 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -30,99 +30,62 @@ using namespace lldb_private::process_linux; // Private namespace. // ---------------------------------------------------------------------------- -namespace -{ - // s390x 64-bit general purpose registers. - static const uint32_t g_gpr_regnums_s390x[] = - { - lldb_r0_s390x, - lldb_r1_s390x, - lldb_r2_s390x, - lldb_r3_s390x, - lldb_r4_s390x, - lldb_r5_s390x, - lldb_r6_s390x, - lldb_r7_s390x, - lldb_r8_s390x, - lldb_r9_s390x, - lldb_r10_s390x, - lldb_r11_s390x, - lldb_r12_s390x, - lldb_r13_s390x, - lldb_r14_s390x, - lldb_r15_s390x, - lldb_acr0_s390x, - lldb_acr1_s390x, - lldb_acr2_s390x, - lldb_acr3_s390x, - lldb_acr4_s390x, - lldb_acr5_s390x, - lldb_acr6_s390x, - lldb_acr7_s390x, - lldb_acr8_s390x, - lldb_acr9_s390x, - lldb_acr10_s390x, - lldb_acr11_s390x, - lldb_acr12_s390x, - lldb_acr13_s390x, - lldb_acr14_s390x, - lldb_acr15_s390x, - lldb_pswm_s390x, - lldb_pswa_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x, - "g_gpr_regnums_s390x has wrong number of register infos"); - - // s390x 64-bit floating point registers. - static const uint32_t g_fpu_regnums_s390x[] = - { - lldb_f0_s390x, - lldb_f1_s390x, - lldb_f2_s390x, - lldb_f3_s390x, - lldb_f4_s390x, - lldb_f5_s390x, - lldb_f6_s390x, - lldb_f7_s390x, - lldb_f8_s390x, - lldb_f9_s390x, - lldb_f10_s390x, - lldb_f11_s390x, - lldb_f12_s390x, - lldb_f13_s390x, - lldb_f14_s390x, - lldb_f15_s390x, - lldb_fpc_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x, - "g_fpu_regnums_s390x has wrong number of register infos"); - - // s390x Linux operating-system information. - static const uint32_t g_linux_regnums_s390x[] = - { - lldb_orig_r2_s390x, - lldb_last_break_s390x, - lldb_system_call_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_linux_regnums_s390x) / sizeof(g_linux_regnums_s390x[0])) - 1 == k_num_linux_registers_s390x, - "g_linux_regnums_s390x has wrong number of register infos"); - - // Number of register sets provided by this context. - enum - { - k_num_register_sets = 3 - }; - - // Register sets for s390x 64-bit. - static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x }, - { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x }, - { "Linux Operating System Data", "linux", k_num_linux_registers_s390x, g_linux_regnums_s390x }, - }; +namespace { +// s390x 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_s390x[] = { + lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x, + lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x, + lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x, + lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x, + lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x, + lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x, + lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x, + lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x, + lldb_pswm_s390x, lldb_pswa_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - + 1 == + k_num_gpr_registers_s390x, + "g_gpr_regnums_s390x has wrong number of register infos"); + +// s390x 64-bit floating point registers. +static const uint32_t g_fpu_regnums_s390x[] = { + lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x, + lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x, + lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x, + lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x, + lldb_fpc_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - + 1 == + k_num_fpr_registers_s390x, + "g_fpu_regnums_s390x has wrong number of register infos"); + +// s390x Linux operating-system information. +static const uint32_t g_linux_regnums_s390x[] = { + lldb_orig_r2_s390x, lldb_last_break_s390x, lldb_system_call_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_linux_regnums_s390x) / + sizeof(g_linux_regnums_s390x[0])) - + 1 == + k_num_linux_registers_s390x, + "g_linux_regnums_s390x has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_register_sets = 3 }; + +// Register sets for s390x 64-bit. +static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x, + g_gpr_regnums_s390x}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x, + g_fpu_regnums_s390x}, + {"Linux Operating System Data", "linux", k_num_linux_registers_s390x, + g_linux_regnums_s390x}, +}; } #define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4) @@ -131,15 +94,15 @@ namespace // Required ptrace defines. // ---------------------------------------------------------------------------- -#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ NativeRegisterContextLinux * -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx); +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextLinux_s390x(target_arch, native_thread, + concrete_frame_idx); } // ---------------------------------------------------------------------------- @@ -147,570 +110,527 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec // ---------------------------------------------------------------------------- static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) -{ - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - return new RegisterContextLinux_s390x(target_arch); -} - -NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) -{ - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: - m_reg_info.num_registers = k_num_registers_s390x; - m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; - m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; - m_reg_info.last_gpr = k_last_gpr_s390x; - m_reg_info.first_fpr = k_first_fpr_s390x; - m_reg_info.last_fpr = k_last_fpr_s390x; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Clear out the watchpoint state. - m_watchpoint_addr = LLDB_INVALID_ADDRESS; +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + return new RegisterContextLinux_s390x(target_arch); +} + +NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + CreateRegisterInfoInterface(target_arch)) { + // Set up data about ranges of valid registers. + switch (target_arch.GetMachine()) { + case llvm::Triple::systemz: + m_reg_info.num_registers = k_num_registers_s390x; + m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; + m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; + m_reg_info.last_gpr = k_last_gpr_s390x; + m_reg_info.first_fpr = k_first_fpr_s390x; + m_reg_info.last_fpr = k_last_fpr_s390x; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Clear out the watchpoint state. + m_watchpoint_addr = LLDB_INVALID_ADDRESS; +} + +uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount() const { + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + if (IsRegisterSetAvailable(set_index)) + ++sets; + } + + return sets; +} + +uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + const RegisterSet *set = GetRegisterSet(set_index); + if (set) + count += set->num_registers; + } + return count; } -uint32_t -NativeRegisterContextLinux_s390x::GetRegisterSetCount() const -{ - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - if (IsRegisterSetAvailable(set_index)) - ++sets; - } +const RegisterSet * +NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const { + if (!IsRegisterSetAvailable(set_index)) + return nullptr; - return sets; -} + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::systemz: + return &g_reg_sets_s390x[set_index]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } -uint32_t -NativeRegisterContextLinux_s390x::GetUserRegisterCount() const -{ - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - const RegisterSet *set = GetRegisterSet(set_index); - if (set) - count += set->num_registers; - } - return count; + return nullptr; } -const RegisterSet * -NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const -{ - if (!IsRegisterSetAvailable(set_index)) - return nullptr; - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) - { - case llvm::Triple::systemz: - return &g_reg_sets_s390x[set_index]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable( + uint32_t set_index) const { + return set_index < k_num_register_sets; +} - return nullptr; +bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const { + // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR + // register area. + return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; } -bool -NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(uint32_t set_index) const -{ - return set_index < k_num_register_sets; -} - -bool -NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const -{ - // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR register area. - return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; -} - -bool -NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const -{ - return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); -} - -Error -NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!reg_info) - return Error("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Error("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name); - - if (IsGPR(reg)) - { - s390_regs regs; - Error error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) - { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Error(); - } +bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const { + return (m_reg_info.first_fpr <= reg_index && + reg_index <= m_reg_info.last_fpr); +} - if (IsFPR(reg)) - { - s390_fp_regs fp_regs; - Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within FPR, not the whole user area. - uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) - { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Error(); - } +Error NativeRegisterContextLinux_s390x::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); - if (reg == lldb_last_break_s390x) - { - uint64_t last_break; - Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); - if (error.Fail()) - return error; + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot " + "read directly", + reg_info->name); - reg_value.SetUInt64(last_break); - return Error(); + if (IsGPR(reg)) { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return Error(); + } - if (reg == lldb_system_call_s390x) - { - uint32_t system_call; - Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - if (error.Fail()) - return error; - - reg_value.SetUInt32(system_call); - return Error(); + if (IsFPR(reg)) { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); + if (error.Fail()) + return error; + + // byte_offset is just the offset within FPR, not the whole user area. + uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return Error(); + } - return Error("failed - register wasn't recognized"); -} - -Error -NativeRegisterContextLinux_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (!reg_info) - return Error("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Error("register \"%s\" is an internal-only lldb register, cannot write directly", reg_info->name); - - if (IsGPR(reg)) - { - s390_regs regs; - Error error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) - { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteGPR(®s, sizeof(regs)); - } + if (reg == lldb_last_break_s390x) { + uint64_t last_break; + Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); + if (error.Fail()) + return error; - if (IsFPR(reg)) - { - s390_fp_regs fp_regs; - Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within fp_regs, not the whole user area. - uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) - { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteFPR(&fp_regs, sizeof(fp_regs)); - } + reg_value.SetUInt64(last_break); + return Error(); + } - if (reg == lldb_last_break_s390x) - { - return Error("The last break address is read-only"); - } + if (reg == lldb_system_call_s390x) { + uint32_t system_call; + Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + if (error.Fail()) + return error; - if (reg == lldb_system_call_s390x) - { - uint32_t system_call = reg_value.GetAsUInt32(); - return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - } + reg_value.SetUInt32(system_call); + return Error(); + } - return Error("failed - register wasn't recognized"); + return Error("failed - register wasn't recognized"); } -Error -NativeRegisterContextLinux_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - Error error; +Error NativeRegisterContextLinux_s390x::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) - { - error.SetErrorStringWithFormat("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - return error; - } + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot " + "write directly", + reg_info->name); - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) - { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", - REG_CONTEXT_SIZE); - return error; + if (IsGPR(reg)) { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return DoWriteGPR(®s, sizeof(regs)); + } - error = DoReadGPR(dst, sizeof(s390_regs)); - dst += sizeof(s390_regs); + if (IsFPR(reg)) { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); if (error.Fail()) - return error; + return error; + + // byte_offset is just the offset within fp_regs, not the whole user area. + uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return DoWriteFPR(&fp_regs, sizeof(fp_regs)); + } - error = DoReadFPR(dst, sizeof(s390_fp_regs)); - dst += sizeof(s390_fp_regs); - if (error.Fail()) - return error; + if (reg == lldb_last_break_s390x) { + return Error("The last break address is read-only"); + } + + if (reg == lldb_system_call_s390x) { + uint32_t system_call = reg_value.GetAsUInt32(); + return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + } - // Ignore errors if the regset is unsupported (happens on older kernels). - DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); - dst += 4; + return Error("failed - register wasn't recognized"); +} - // To enable inferior function calls while the process is stopped in - // an interrupted system call, we need to clear the system call flag. - // It will be restored to its original value by WriteAllRegisterValues. - // Again we ignore error if the regset is unsupported. - uint32_t system_call = 0; - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); +Error NativeRegisterContextLinux_s390x::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); return error; -} + } -Error -NativeRegisterContextLinux_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - Error error; + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } - if (!data_sp) - { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s invalid data_sp provided", __FUNCTION__); - return error; - } + error = DoReadGPR(dst, sizeof(s390_regs)); + dst += sizeof(s390_regs); + if (error.Fail()) + return error; - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched data size, expected %" PRIu64 - ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } + error = DoReadFPR(dst, sizeof(s390_fp_regs)); + dst += sizeof(s390_fp_regs); + if (error.Fail()) + return error; - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) - { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } + // Ignore errors if the regset is unsupported (happens on older kernels). + DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); + dst += 4; - error = DoWriteGPR(src, sizeof(s390_regs)); - src += sizeof(s390_regs); - if (error.Fail()) - return error; + // To enable inferior function calls while the process is stopped in + // an interrupted system call, we need to clear the system call flag. + // It will be restored to its original value by WriteAllRegisterValues. + // Again we ignore error if the regset is unsupported. + uint32_t system_call = 0; + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - error = DoWriteFPR(src, sizeof(s390_fp_regs)); - src += sizeof(s390_fp_regs); - if (error.Fail()) - return error; + return error; +} - // Ignore errors if the regset is unsupported (happens on older kernels). - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); - src += 4; +Error NativeRegisterContextLinux_s390x::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s invalid data_sp provided", + __FUNCTION__); return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + + error = DoWriteGPR(src, sizeof(s390_regs)); + src += sizeof(s390_regs); + if (error.Fail()) + return error; + + error = DoWriteFPR(src, sizeof(s390_fp_regs)); + src += sizeof(s390_fp_regs); + if (error.Fail()) + return error; + + // Ignore errors if the regset is unsupported (happens on older kernels). + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); + src += 4; + + return error; } -Error -NativeRegisterContextLinux_s390x::DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) -{ - return Error("DoReadRegisterValue unsupported"); +Error NativeRegisterContextLinux_s390x::DoReadRegisterValue( + uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) { + return Error("DoReadRegisterValue unsupported"); } -Error -NativeRegisterContextLinux_s390x::DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value) -{ - return Error("DoWriteRegisterValue unsupported"); +Error NativeRegisterContextLinux_s390x::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + return Error("DoWriteRegisterValue unsupported"); } -Error -NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, size_t buf_size) -{ - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; +Error NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, + size_t buf_size) { + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; - return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, m_thread.GetID(), &parea); + return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, + m_thread.GetID(), &parea); } -Error -NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, const void *buf, size_t buf_size) -{ - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; +Error NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, + const void *buf, + size_t buf_size) { + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; - return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, m_thread.GetID(), &parea); + return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, + m_thread.GetID(), &parea); } -Error -NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_regs)); - return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_regs)); + return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_regs)); - return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_regs)); + return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_fp_regs)); - return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_fp_regs)); + return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_fp_regs)); - return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_fp_regs)); + return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size) -{ - struct iovec iov; - iov.iov_base = buf; - iov.iov_len = buf_size; +Error NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, + void *buf, + size_t buf_size) { + struct iovec iov; + iov.iov_base = buf; + iov.iov_len = buf_size; - return ReadRegisterSet(&iov, buf_size, regset); + return ReadRegisterSet(&iov, buf_size, regset); } -Error -NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size) -{ - struct iovec iov; - iov.iov_base = const_cast<void *>(buf); - iov.iov_len = buf_size; +Error NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, + const void *buf, + size_t buf_size) { + struct iovec iov; + iov.iov_base = const_cast<void *>(buf); + iov.iov_len = buf_size; - return WriteRegisterSet(&iov, buf_size, regset); + return WriteRegisterSet(&iov, buf_size, regset); } -Error -NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, bool &is_hit) -{ - per_lowcore_bits per_lowcore; +Error NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + per_lowcore_bits per_lowcore; - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); - - if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) - { - is_hit = false; - return Error(); - } - - Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); - if (error.Fail()) - { - is_hit = false; - return error; - } - - is_hit = (per_lowcore.perc_storage_alteration == 1 && per_lowcore.perc_store_real_address == 0); - - if (is_hit) - { - // Do not report this watchpoint again. - memset(&per_lowcore, 0, sizeof(per_lowcore)); - PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); - } + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) { + is_hit = false; return Error(); -} + } -Error -NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) - { - bool is_hit; - Error error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) - { - wp_index = LLDB_INVALID_INDEX32; - return error; - } - else if (is_hit) - { - return error; - } + Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), + &per_lowcore, sizeof(per_lowcore)); + if (error.Fail()) { + is_hit = false; + return error; + } + + is_hit = (per_lowcore.perc_storage_alteration == 1 && + per_lowcore.perc_store_real_address == 0); + + if (is_hit) { + // Do not report this watchpoint again. + memset(&per_lowcore, 0, sizeof(per_lowcore)); + PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, + sizeof(per_lowcore)); + } + + return Error(); +} + +Error NativeRegisterContextLinux_s390x::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; } - wp_index = LLDB_INVALID_INDEX32; - return Error(); + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); } -Error -NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); +Error NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); - is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; + is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; - return Error(); + return Error(); } -bool -NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(uint32_t wp_index) -{ - per_struct per_info; +bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint( + uint32_t wp_index) { + per_struct per_info; - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; - Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return false; + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return false; - per_info.control_regs.bits.em_storage_alteration = 0; - per_info.control_regs.bits.storage_alt_space_ctl = 0; - per_info.starting_addr = 0; - per_info.ending_addr = 0; + per_info.control_regs.bits.em_storage_alteration = 0; + per_info.control_regs.bits.storage_alt_space_ctl = 0; + per_info.starting_addr = 0; + per_info.ending_addr = 0; - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return false; + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return false; - m_watchpoint_addr = LLDB_INVALID_ADDRESS; - return true; + m_watchpoint_addr = LLDB_INVALID_ADDRESS; + return true; } -Error -NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() -{ - if (ClearHardwareWatchpoint(0)) - return Error(); - return Error("Clearing all hardware watchpoints failed."); +Error NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() { + if (ClearHardwareWatchpoint(0)) + return Error(); + return Error("Clearing all hardware watchpoints failed."); } -uint32_t -NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - per_struct per_info; +uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + per_struct per_info; - if (watch_flags != 0x1) - return LLDB_INVALID_INDEX32; + if (watch_flags != 0x1) + return LLDB_INVALID_INDEX32; - if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) - return LLDB_INVALID_INDEX32; + if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) + return LLDB_INVALID_INDEX32; - Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; - per_info.control_regs.bits.em_storage_alteration = 1; - per_info.control_regs.bits.storage_alt_space_ctl = 1; - per_info.starting_addr = addr; - per_info.ending_addr = addr + size - 1; + per_info.control_regs.bits.em_storage_alteration = 1; + per_info.control_regs.bits.storage_alt_space_ctl = 1; + per_info.starting_addr = addr; + per_info.ending_addr = addr + size - 1; - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; - m_watchpoint_addr = addr; - return 0; + m_watchpoint_addr = addr; + return 0; } lldb::addr_t -NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - return m_watchpoint_addr; +NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + return m_watchpoint_addr; } -uint32_t -NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() -{ - return 1; +uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() { + return 1; } #endif // defined(__s390x__) && defined(__linux__) diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h index 8cd4ab7f124..4bd737767fa 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h @@ -16,121 +16,96 @@ #include "Plugins/Process/Utility/RegisterContext_s390x.h" #include "Plugins/Process/Utility/lldb-s390x-register-enums.h" -namespace lldb_private -{ -namespace process_linux -{ +namespace lldb_private { +namespace process_linux { class NativeProcessLinux; -class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux -{ +class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); - uint32_t - GetRegisterSetCount() const override; + uint32_t GetRegisterSetCount() const override; - const RegisterSet * - GetRegisterSet(uint32_t set_index) const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - uint32_t - GetUserRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; - Error - ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - Error - WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - Error - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - Error - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - Error - IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; + Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - Error - GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; - Error - IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; + Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - bool - ClearHardwareWatchpoint(uint32_t wp_index) override; + bool ClearHardwareWatchpoint(uint32_t wp_index) override; - Error - ClearAllHardwareWatchpoints() override; + Error ClearAllHardwareWatchpoints() override; - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; - lldb::addr_t - GetWatchpointAddress(uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - uint32_t - NumSupportedHardwareWatchpoints() override; + uint32_t NumSupportedHardwareWatchpoints() override; protected: - Error - DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) override; + Error DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value) override; - Error - DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override; + Error DoWriteRegisterValue(uint32_t offset, const char *reg_name, + const RegisterValue &value) override; - Error - DoReadGPR(void *buf, size_t buf_size) override; + Error DoReadGPR(void *buf, size_t buf_size) override; - Error - DoWriteGPR(void *buf, size_t buf_size) override; + Error DoWriteGPR(void *buf, size_t buf_size) override; - Error - DoReadFPR(void *buf, size_t buf_size) override; + Error DoReadFPR(void *buf, size_t buf_size) override; - Error - DoWriteFPR(void *buf, size_t buf_size) override; + Error DoWriteFPR(void *buf, size_t buf_size) override; private: - // Info about register ranges. - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; + // Info about register ranges. + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - }; + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + }; - // Private member variables. - RegInfo m_reg_info; - lldb::addr_t m_watchpoint_addr; + // Private member variables. + RegInfo m_reg_info; + lldb::addr_t m_watchpoint_addr; - // Private member methods. - bool - IsRegisterSetAvailable(uint32_t set_index) const; + // Private member methods. + bool IsRegisterSetAvailable(uint32_t set_index) const; - bool - IsGPR(uint32_t reg_index) const; + bool IsGPR(uint32_t reg_index) const; - bool - IsFPR(uint32_t reg_index) const; + bool IsFPR(uint32_t reg_index) const; - Error - PeekUserArea(uint32_t offset, void *buf, size_t buf_size); + Error PeekUserArea(uint32_t offset, void *buf, size_t buf_size); - Error - PokeUserArea(uint32_t offset, const void *buf, size_t buf_size); + Error PokeUserArea(uint32_t offset, const void *buf, size_t buf_size); - Error - DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size); + Error DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size); - Error - DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size); + Error DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size); }; } // namespace process_linux diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 2080d2ede37..369a8033a62 100755 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -11,9 +11,9 @@ #include "NativeRegisterContextLinux_x86_64.h" -#include "lldb/Core/Log.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/HostInfo.h" @@ -27,297 +27,158 @@ using namespace lldb_private::process_linux; // Private namespace. // ---------------------------------------------------------------------------- -namespace -{ - // x86 32-bit general purpose registers. - const uint32_t - g_gpr_regnums_i386[] = - { - lldb_eax_i386, - lldb_ebx_i386, - lldb_ecx_i386, - lldb_edx_i386, - lldb_edi_i386, - lldb_esi_i386, - lldb_ebp_i386, - lldb_esp_i386, - lldb_eip_i386, - lldb_eflags_i386, - lldb_cs_i386, - lldb_fs_i386, - lldb_gs_i386, - lldb_ss_i386, - lldb_ds_i386, - lldb_es_i386, - lldb_ax_i386, - lldb_bx_i386, - lldb_cx_i386, - lldb_dx_i386, - lldb_di_i386, - lldb_si_i386, - lldb_bp_i386, - lldb_sp_i386, - lldb_ah_i386, - lldb_bh_i386, - lldb_ch_i386, - lldb_dh_i386, - lldb_al_i386, - lldb_bl_i386, - lldb_cl_i386, - lldb_dl_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386, - "g_gpr_regnums_i386 has wrong number of register infos"); - - // x86 32-bit floating point registers. - const uint32_t - g_fpu_regnums_i386[] = - { - lldb_fctrl_i386, - lldb_fstat_i386, - lldb_ftag_i386, - lldb_fop_i386, - lldb_fiseg_i386, - lldb_fioff_i386, - lldb_foseg_i386, - lldb_fooff_i386, - lldb_mxcsr_i386, - lldb_mxcsrmask_i386, - lldb_st0_i386, - lldb_st1_i386, - lldb_st2_i386, - lldb_st3_i386, - lldb_st4_i386, - lldb_st5_i386, - lldb_st6_i386, - lldb_st7_i386, - lldb_mm0_i386, - lldb_mm1_i386, - lldb_mm2_i386, - lldb_mm3_i386, - lldb_mm4_i386, - lldb_mm5_i386, - lldb_mm6_i386, - lldb_mm7_i386, - lldb_xmm0_i386, - lldb_xmm1_i386, - lldb_xmm2_i386, - lldb_xmm3_i386, - lldb_xmm4_i386, - lldb_xmm5_i386, - lldb_xmm6_i386, - lldb_xmm7_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386, - "g_fpu_regnums_i386 has wrong number of register infos"); - - // x86 32-bit AVX registers. - const uint32_t - g_avx_regnums_i386[] = - { - lldb_ymm0_i386, - lldb_ymm1_i386, - lldb_ymm2_i386, - lldb_ymm3_i386, - lldb_ymm4_i386, - lldb_ymm5_i386, - lldb_ymm6_i386, - lldb_ymm7_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386, - " g_avx_regnums_i386 has wrong number of register infos"); - - // x86 64-bit general purpose registers. - static const - uint32_t g_gpr_regnums_x86_64[] = - { - lldb_rax_x86_64, - lldb_rbx_x86_64, - lldb_rcx_x86_64, - lldb_rdx_x86_64, - lldb_rdi_x86_64, - lldb_rsi_x86_64, - lldb_rbp_x86_64, - lldb_rsp_x86_64, - lldb_r8_x86_64, - lldb_r9_x86_64, - lldb_r10_x86_64, - lldb_r11_x86_64, - lldb_r12_x86_64, - lldb_r13_x86_64, - lldb_r14_x86_64, - lldb_r15_x86_64, - lldb_rip_x86_64, - lldb_rflags_x86_64, - lldb_cs_x86_64, - lldb_fs_x86_64, - lldb_gs_x86_64, - lldb_ss_x86_64, - lldb_ds_x86_64, - lldb_es_x86_64, - lldb_eax_x86_64, - lldb_ebx_x86_64, - lldb_ecx_x86_64, - lldb_edx_x86_64, - lldb_edi_x86_64, - lldb_esi_x86_64, - lldb_ebp_x86_64, - lldb_esp_x86_64, - lldb_r8d_x86_64, // Low 32 bits or r8 - lldb_r9d_x86_64, // Low 32 bits or r9 - lldb_r10d_x86_64, // Low 32 bits or r10 - lldb_r11d_x86_64, // Low 32 bits or r11 - lldb_r12d_x86_64, // Low 32 bits or r12 - lldb_r13d_x86_64, // Low 32 bits or r13 - lldb_r14d_x86_64, // Low 32 bits or r14 - lldb_r15d_x86_64, // Low 32 bits or r15 - lldb_ax_x86_64, - lldb_bx_x86_64, - lldb_cx_x86_64, - lldb_dx_x86_64, - lldb_di_x86_64, - lldb_si_x86_64, - lldb_bp_x86_64, - lldb_sp_x86_64, - lldb_r8w_x86_64, // Low 16 bits or r8 - lldb_r9w_x86_64, // Low 16 bits or r9 - lldb_r10w_x86_64, // Low 16 bits or r10 - lldb_r11w_x86_64, // Low 16 bits or r11 - lldb_r12w_x86_64, // Low 16 bits or r12 - lldb_r13w_x86_64, // Low 16 bits or r13 - lldb_r14w_x86_64, // Low 16 bits or r14 - lldb_r15w_x86_64, // Low 16 bits or r15 - lldb_ah_x86_64, - lldb_bh_x86_64, - lldb_ch_x86_64, - lldb_dh_x86_64, - lldb_al_x86_64, - lldb_bl_x86_64, - lldb_cl_x86_64, - lldb_dl_x86_64, - lldb_dil_x86_64, - lldb_sil_x86_64, - lldb_bpl_x86_64, - lldb_spl_x86_64, - lldb_r8l_x86_64, // Low 8 bits or r8 - lldb_r9l_x86_64, // Low 8 bits or r9 - lldb_r10l_x86_64, // Low 8 bits or r10 - lldb_r11l_x86_64, // Low 8 bits or r11 - lldb_r12l_x86_64, // Low 8 bits or r12 - lldb_r13l_x86_64, // Low 8 bits or r13 - lldb_r14l_x86_64, // Low 8 bits or r14 - lldb_r15l_x86_64, // Low 8 bits or r15 - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64, - "g_gpr_regnums_x86_64 has wrong number of register infos"); - - // x86 64-bit floating point registers. - static const uint32_t - g_fpu_regnums_x86_64[] = - { - lldb_fctrl_x86_64, - lldb_fstat_x86_64, - lldb_ftag_x86_64, - lldb_fop_x86_64, - lldb_fiseg_x86_64, - lldb_fioff_x86_64, - lldb_foseg_x86_64, - lldb_fooff_x86_64, - lldb_mxcsr_x86_64, - lldb_mxcsrmask_x86_64, - lldb_st0_x86_64, - lldb_st1_x86_64, - lldb_st2_x86_64, - lldb_st3_x86_64, - lldb_st4_x86_64, - lldb_st5_x86_64, - lldb_st6_x86_64, - lldb_st7_x86_64, - lldb_mm0_x86_64, - lldb_mm1_x86_64, - lldb_mm2_x86_64, - lldb_mm3_x86_64, - lldb_mm4_x86_64, - lldb_mm5_x86_64, - lldb_mm6_x86_64, - lldb_mm7_x86_64, - lldb_xmm0_x86_64, - lldb_xmm1_x86_64, - lldb_xmm2_x86_64, - lldb_xmm3_x86_64, - lldb_xmm4_x86_64, - lldb_xmm5_x86_64, - lldb_xmm6_x86_64, - lldb_xmm7_x86_64, - lldb_xmm8_x86_64, - lldb_xmm9_x86_64, - lldb_xmm10_x86_64, - lldb_xmm11_x86_64, - lldb_xmm12_x86_64, - lldb_xmm13_x86_64, - lldb_xmm14_x86_64, - lldb_xmm15_x86_64, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64, - "g_fpu_regnums_x86_64 has wrong number of register infos"); - - // x86 64-bit AVX registers. - static const uint32_t - g_avx_regnums_x86_64[] = - { - lldb_ymm0_x86_64, - lldb_ymm1_x86_64, - lldb_ymm2_x86_64, - lldb_ymm3_x86_64, - lldb_ymm4_x86_64, - lldb_ymm5_x86_64, - lldb_ymm6_x86_64, - lldb_ymm7_x86_64, - lldb_ymm8_x86_64, - lldb_ymm9_x86_64, - lldb_ymm10_x86_64, - lldb_ymm11_x86_64, - lldb_ymm12_x86_64, - lldb_ymm13_x86_64, - lldb_ymm14_x86_64, - lldb_ymm15_x86_64, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64, - "g_avx_regnums_x86_64 has wrong number of register infos"); - - // Number of register sets provided by this context. - enum - { - k_num_extended_register_sets = 1, - k_num_register_sets = 3 - }; - - // Register sets for x86 32-bit. - static const RegisterSet - g_reg_sets_i386[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 } - }; - - // Register sets for x86 64-bit. - static const RegisterSet - g_reg_sets_x86_64[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 } - }; +namespace { +// x86 32-bit general purpose registers. +const uint32_t g_gpr_regnums_i386[] = { + lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, + lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, + lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, + lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386, + lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386, + lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386, + lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386, + lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - + 1 == + k_num_gpr_registers_i386, + "g_gpr_regnums_i386 has wrong number of register infos"); + +// x86 32-bit floating point registers. +const uint32_t g_fpu_regnums_i386[] = { + lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, + lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, + lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, + lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386, + lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386, + lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386, + lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, + lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, + lldb_xmm6_i386, lldb_xmm7_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - + 1 == + k_num_fpr_registers_i386, + "g_fpu_regnums_i386 has wrong number of register infos"); + +// x86 32-bit AVX registers. +const uint32_t g_avx_regnums_i386[] = { + lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, + lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - + 1 == + k_num_avx_registers_i386, + " g_avx_regnums_i386 has wrong number of register infos"); + +// x86 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_x86_64[] = { + lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, + lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, + lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, + lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, + lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, + lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, + lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, + lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits or r8 + lldb_r9d_x86_64, // Low 32 bits or r9 + lldb_r10d_x86_64, // Low 32 bits or r10 + lldb_r11d_x86_64, // Low 32 bits or r11 + lldb_r12d_x86_64, // Low 32 bits or r12 + lldb_r13d_x86_64, // Low 32 bits or r13 + lldb_r14d_x86_64, // Low 32 bits or r14 + lldb_r15d_x86_64, // Low 32 bits or r15 + lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, + lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits or r8 + lldb_r9w_x86_64, // Low 16 bits or r9 + lldb_r10w_x86_64, // Low 16 bits or r10 + lldb_r11w_x86_64, // Low 16 bits or r11 + lldb_r12w_x86_64, // Low 16 bits or r12 + lldb_r13w_x86_64, // Low 16 bits or r13 + lldb_r14w_x86_64, // Low 16 bits or r14 + lldb_r15w_x86_64, // Low 16 bits or r15 + lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, + lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, + lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits or r8 + lldb_r9l_x86_64, // Low 8 bits or r9 + lldb_r10l_x86_64, // Low 8 bits or r10 + lldb_r11l_x86_64, // Low 8 bits or r11 + lldb_r12l_x86_64, // Low 8 bits or r12 + lldb_r13l_x86_64, // Low 8 bits or r13 + lldb_r14l_x86_64, // Low 8 bits or r14 + lldb_r15l_x86_64, // Low 8 bits or r15 + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - + 1 == + k_num_gpr_registers_x86_64, + "g_gpr_regnums_x86_64 has wrong number of register infos"); + +// x86 64-bit floating point registers. +static const uint32_t g_fpu_regnums_x86_64[] = { + lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, + lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, + lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64, + lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64, + lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64, + lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64, + lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64, + lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64, + lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64, + lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64, + lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64, + lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64, + lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64, + lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - + 1 == + k_num_fpr_registers_x86_64, + "g_fpu_regnums_x86_64 has wrong number of register infos"); + +// x86 64-bit AVX registers. +static const uint32_t g_avx_regnums_x86_64[] = { + lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, + lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, + lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, + lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - + 1 == + k_num_avx_registers_x86_64, + "g_avx_regnums_x86_64 has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_extended_register_sets = 1, k_num_register_sets = 3 }; + +// Register sets for x86 32-bit. +static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, + g_gpr_regnums_i386}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, + g_fpu_regnums_i386}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, + g_avx_regnums_i386}}; + +// Register sets for x86 64-bit. +static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, + g_gpr_regnums_x86_64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, + g_fpu_regnums_x86_64}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, + g_avx_regnums_x86_64}}; } -#define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR)) +#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR)) // ---------------------------------------------------------------------------- // Required ptrace defines. @@ -331,909 +192,890 @@ namespace #define NT_PRXFPREG 0x46e62b7f #endif -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx); +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, + concrete_frame_idx); } // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_x86_64 members. // ---------------------------------------------------------------------------- -static RegisterInfoInterface* -CreateRegisterInfoInterface(const ArchSpec& target_arch) -{ - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) - { - // 32-bit hosts run with a RegisterContextLinux_i386 context. - return new RegisterContextLinux_i386(target_arch); - } - else - { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context. - return new RegisterContextLinux_x86_64 (target_arch); - } +static RegisterInfoInterface * +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { + // 32-bit hosts run with a RegisterContextLinux_i386 context. + return new RegisterContextLinux_i386(target_arch); + } else { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the + // x86_64 register context. + return new RegisterContextLinux_x86_64(target_arch); + } } -NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), - m_fpr_type (eFPRTypeNotValid), - m_fpr (), - m_iovec (), - m_ymm_set (), - m_reg_info (), - m_gpr_x86_64 () -{ - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine ()) - { - case llvm::Triple::x86: - m_reg_info.num_registers = k_num_registers_i386; - m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; - m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; - m_reg_info.num_avx_registers = k_num_avx_registers_i386; - m_reg_info.last_gpr = k_last_gpr_i386; - m_reg_info.first_fpr = k_first_fpr_i386; - m_reg_info.last_fpr = k_last_fpr_i386; - m_reg_info.first_st = lldb_st0_i386; - m_reg_info.last_st = lldb_st7_i386; - m_reg_info.first_mm = lldb_mm0_i386; - m_reg_info.last_mm = lldb_mm7_i386; - m_reg_info.first_xmm = lldb_xmm0_i386; - m_reg_info.last_xmm = lldb_xmm7_i386; - m_reg_info.first_ymm = lldb_ymm0_i386; - m_reg_info.last_ymm = lldb_ymm7_i386; - m_reg_info.first_dr = lldb_dr0_i386; - m_reg_info.gpr_flags = lldb_eflags_i386; - break; - case llvm::Triple::x86_64: - m_reg_info.num_registers = k_num_registers_x86_64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; - m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; - m_reg_info.last_gpr = k_last_gpr_x86_64; - m_reg_info.first_fpr = k_first_fpr_x86_64; - m_reg_info.last_fpr = k_last_fpr_x86_64; - m_reg_info.first_st = lldb_st0_x86_64; - m_reg_info.last_st = lldb_st7_x86_64; - m_reg_info.first_mm = lldb_mm0_x86_64; - m_reg_info.last_mm = lldb_mm7_x86_64; - m_reg_info.first_xmm = lldb_xmm0_x86_64; - m_reg_info.last_xmm = lldb_xmm15_x86_64; - m_reg_info.first_ymm = lldb_ymm0_x86_64; - m_reg_info.last_ymm = lldb_ymm15_x86_64; - m_reg_info.first_dr = lldb_dr0_x86_64; - m_reg_info.gpr_flags = lldb_rflags_x86_64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Initialize m_iovec to point to the buffer and buffer size - // using the conventions of Berkeley style UIO structures, as required - // by PTRACE extensions. - m_iovec.iov_base = &m_fpr.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); - - // Clear out the FPR state. - ::memset(&m_fpr, 0, sizeof(FPR)); - - // Store byte offset of fctrl (i.e. first register of FPR) - const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); - m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; +NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + CreateRegisterInfoInterface(target_arch)), + m_fpr_type(eFPRTypeNotValid), m_fpr(), m_iovec(), m_ymm_set(), + m_reg_info(), m_gpr_x86_64() { + // Set up data about ranges of valid registers. + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + m_reg_info.num_registers = k_num_registers_i386; + m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; + m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; + m_reg_info.num_avx_registers = k_num_avx_registers_i386; + m_reg_info.last_gpr = k_last_gpr_i386; + m_reg_info.first_fpr = k_first_fpr_i386; + m_reg_info.last_fpr = k_last_fpr_i386; + m_reg_info.first_st = lldb_st0_i386; + m_reg_info.last_st = lldb_st7_i386; + m_reg_info.first_mm = lldb_mm0_i386; + m_reg_info.last_mm = lldb_mm7_i386; + m_reg_info.first_xmm = lldb_xmm0_i386; + m_reg_info.last_xmm = lldb_xmm7_i386; + m_reg_info.first_ymm = lldb_ymm0_i386; + m_reg_info.last_ymm = lldb_ymm7_i386; + m_reg_info.first_dr = lldb_dr0_i386; + m_reg_info.gpr_flags = lldb_eflags_i386; + break; + case llvm::Triple::x86_64: + m_reg_info.num_registers = k_num_registers_x86_64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; + m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; + m_reg_info.last_gpr = k_last_gpr_x86_64; + m_reg_info.first_fpr = k_first_fpr_x86_64; + m_reg_info.last_fpr = k_last_fpr_x86_64; + m_reg_info.first_st = lldb_st0_x86_64; + m_reg_info.last_st = lldb_st7_x86_64; + m_reg_info.first_mm = lldb_mm0_x86_64; + m_reg_info.last_mm = lldb_mm7_x86_64; + m_reg_info.first_xmm = lldb_xmm0_x86_64; + m_reg_info.last_xmm = lldb_xmm15_x86_64; + m_reg_info.first_ymm = lldb_ymm0_x86_64; + m_reg_info.last_ymm = lldb_ymm15_x86_64; + m_reg_info.first_dr = lldb_dr0_x86_64; + m_reg_info.gpr_flags = lldb_rflags_x86_64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Initialize m_iovec to point to the buffer and buffer size + // using the conventions of Berkeley style UIO structures, as required + // by PTRACE extensions. + m_iovec.iov_base = &m_fpr.xstate.xsave; + m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); + + // Clear out the FPR state. + ::memset(&m_fpr, 0, sizeof(FPR)); + + // Store byte offset of fctrl (i.e. first register of FPR) + const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); + m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; } // CONSIDER after local and llgs debugging are merged, register set support can // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. -uint32_t -NativeRegisterContextLinux_x86_64::GetRegisterSetCount () const -{ - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - if (IsRegisterSetAvailable (set_index)) - ++sets; - } - - return sets; +uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const { + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + if (IsRegisterSetAvailable(set_index)) + ++sets; + } + + return sets; } -uint32_t -NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const -{ - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - const RegisterSet* set = GetRegisterSet(set_index); - if (set) - count += set->num_registers; - } - return count; +uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + const RegisterSet *set = GetRegisterSet(set_index); + if (set) + count += set->num_registers; + } + return count; } const RegisterSet * -NativeRegisterContextLinux_x86_64::GetRegisterSet (uint32_t set_index) const -{ - if (!IsRegisterSetAvailable (set_index)) - return nullptr; - - switch (GetRegisterInfoInterface ().GetTargetArchitecture ().GetMachine ()) - { - case llvm::Triple::x86: - return &g_reg_sets_i386[set_index]; - case llvm::Triple::x86_64: - return &g_reg_sets_x86_64[set_index]; - default: - assert (false && "Unhandled target architecture."); - return nullptr; - } +NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const { + if (!IsRegisterSetAvailable(set_index)) + return nullptr; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + return &g_reg_sets_i386[set_index]; + case llvm::Triple::x86_64: + return &g_reg_sets_x86_64[set_index]; + default: + assert(false && "Unhandled target architecture."); return nullptr; -} + } -Error -NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - Error error; + return nullptr; +} - if (!reg_info) - { - error.SetErrorString ("reg_info NULL"); - return error; - } +Error NativeRegisterContextLinux_x86_64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + Error error; - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - { - // This is likely an internal register for lldb use only and should not be directly queried. - error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name); - return error; - } + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } - if (IsFPR(reg, GetFPRType())) - { - error = ReadFPR(); - if (error.Fail()) - return error; + if (IsFPR(reg, GetFPRType())) { + error = ReadFPR(); + if (error.Fail()) + return error; + } else { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; } - else - { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - error = ReadRegisterRaw(full_reg, reg_value); + error = ReadRegisterRaw(full_reg, reg_value); - if (error.Success ()) - { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); + if (error.Success()) { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value + // one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; + // If our return byte size was greater than the return value reg size, + // then + // use the type specified by reg_info rather than the uint64_t default + if (reg_value.GetByteSize() > reg_info->byte_size) + reg_value.SetType(reg_info); } - - if (reg_info->encoding == lldb::eEncodingVector) - { - lldb::ByteOrder byte_order = GetByteOrder(); - - if (byte_order != lldb::eByteOrderInvalid) - { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - reg_value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) - { - // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes - if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order)) - reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order); - else - { - error.SetErrorString ("failed to copy ymm register value"); - return error; - } - } - - if (reg_value.GetType() != RegisterValue::eTypeBytes) - error.SetErrorString ("write failed - type was expected to be RegisterValue::eTypeBytes"); - - return error; + return error; + } + + if (reg_info->encoding == lldb::eEncodingVector) { + lldb::ByteOrder byte_order = GetByteOrder(); + + if (byte_order != lldb::eByteOrderInvalid) { + if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) + reg_value.SetBytes( + m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) + reg_value.SetBytes( + m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) + reg_value.SetBytes( + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { + // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes + if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order)) + reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + reg_info->byte_size, byte_order); + else { + error.SetErrorString("failed to copy ymm register value"); + return error; } + } - error.SetErrorString ("byte order is invalid"); - return error; - } + if (reg_value.GetType() != RegisterValue::eTypeBytes) + error.SetErrorString( + "write failed - type was expected to be RegisterValue::eTypeBytes"); - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. - - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} - // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu - // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) - assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) - { - case 1: - reg_value.SetUInt8(*(uint8_t *)src); - break; - case 2: - reg_value.SetUInt16(*(uint16_t *)src); - break; - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); - break; + return error; } + error.SetErrorString("byte order is invalid"); return error; + } + + // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + + // Byte offsets of all registers are calculated wrt 'UserArea' structure. + // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} + // and stores them in 'm_fpr' (of type FPR structure). To extract values of + // fpu + // registers, m_fpr should be read at byte offsets calculated wrt to FPR + // structure. + + // Since, FPR structure is also one of the member of UserArea structure. + // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - + // byte_offset(fctrl wrt UserArea) + assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); + uint8_t *src = + (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; + switch (reg_info->byte_size) { + case 1: + reg_value.SetUInt8(*(uint8_t *)src); + break; + case 2: + reg_value.SetUInt16(*(uint16_t *)src); + break; + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, + reg_info->byte_size); + break; + } + + return error; } -Error -NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - assert (reg_info && "reg_info is null"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index, GetFPRType())) - { - if (reg_info->encoding == lldb::eEncodingVector) - { - if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) - ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) - ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) - ::memcpy (m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_ymm && reg_index <= m_reg_info.last_ymm) - { - if (GetFPRType() != eFPRTypeXSAVE) - return Error ("target processor does not support AVX"); - - // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes - ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) - return Error ("CopyYMMtoXSTATE() failed"); - } - } - else - { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. - - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu - // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers should - // be written in m_fpr at byte offsets calculated wrt FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) - assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) - { - case 1: - *(uint8_t *)dst = reg_value.GetAsUInt8(); - break; - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); - } - } +Error NativeRegisterContextLinux_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + assert(reg_info && "reg_info is null"); + + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg_index == LLDB_INVALID_REGNUM) + return Error("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : "<unknown register>"); + + if (IsGPR(reg_index)) + return WriteRegisterRaw(reg_index, reg_value); + + if (IsFPR(reg_index, GetFPRType())) { + if (reg_info->encoding == lldb::eEncodingVector) { + if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) + ::memcpy( + m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); + + if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) + ::memcpy( + m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); + + if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) + ::memcpy( + m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); + + if (reg_index >= m_reg_info.first_ymm && + reg_index <= m_reg_info.last_ymm) { + if (GetFPRType() != eFPRTypeXSAVE) + return Error("target processor does not support AVX"); + + // Store ymm register content, and split into the register halves in + // xmm.bytes and ymmh.bytes + ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, + reg_value.GetBytes(), reg_value.GetByteSize()); + if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) + return Error("CopyYMMtoXSTATE() failed"); + } + } else { + // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + + // Byte offsets of all registers are calculated wrt 'UserArea' structure. + // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only + // fpu + // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers + // should + // be written in m_fpr at byte offsets calculated wrt FPR structure. + + // Since, FPR structure is also one of the member of UserArea structure. + // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - + // byte_offset(fctrl wrt UserArea) + assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < + sizeof(m_fpr)); + uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - + m_fctrl_offset_in_userarea; + switch (reg_info->byte_size) { + case 1: + *(uint8_t *)dst = reg_value.GetAsUInt8(); + break; + case 2: + *(uint16_t *)dst = reg_value.GetAsUInt16(); + break; + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled register data size %" PRIu32, + reg_info->byte_size); + } + } - Error error = WriteFPR(); - if (error.Fail()) - return error; + Error error = WriteFPR(); + if (error.Fail()) + return error; - if (IsAVX(reg_index)) - { - if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) - return Error ("CopyYMMtoXSTATE() failed"); - } - return Error (); + if (IsAVX(reg_index)) { + if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) + return Error("CopyYMMtoXSTATE() failed"); } - return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); + return Error(); + } + return Error("failed - register wasn't recognized to be a GPR or an FPR, " + "write strategy unknown"); } -Error -NativeRegisterContextLinux_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - Error error; +Error NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (!data_sp) - { - error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - return error; - } + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); + return error; + } - error = ReadGPR(); - if (error.Fail()) - return error; + error = ReadGPR(); + if (error.Fail()) + return error; - error = ReadFPR(); - if (error.Fail()) - return error; + error = ReadFPR(); + if (error.Fail()) + return error; - uint8_t *dst = data_sp->GetBytes (); - if (dst == nullptr) - { - error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } + + ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); + dst += GetRegisterInfoInterface().GetGPRSize(); + if (GetFPRType() == eFPRTypeFXSAVE) + ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + else if (GetFPRType() == eFPRTypeXSAVE) { + lldb::ByteOrder byte_order = GetByteOrder(); + + // Assemble the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; + ++reg) { + if (!CopyXSTATEtoYMM(reg, byte_order)) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " + "CopyXSTATEtoYMM() failed for reg num " + "%" PRIu32, + __FUNCTION__, reg); return error; + } } - ::memcpy (dst, &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()); - dst += GetRegisterInfoInterface ().GetGPRSize (); - if (GetFPRType () == eFPRTypeFXSAVE) - ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); - else if (GetFPRType () == eFPRTypeXSAVE) - { - lldb::ByteOrder byte_order = GetByteOrder (); - - // Assemble the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg) - { - if (!CopyXSTATEtoYMM (reg, byte_order)) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyXSTATEtoYMM() failed for reg num %" PRIu32, __FUNCTION__, reg); - return error; - } - } - - // Copy the extended register state including the assembled ymm registers. - ::memcpy (dst, &m_fpr, sizeof (m_fpr)); - } - else - { - assert (false && "how do we save the floating point registers?"); - error.SetErrorString ("unsure how to save the floating point registers"); - } - /** The following code is specific to Linux x86 based architectures, - * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to - * -1 to solve the bug 23659, such a setting prevents the automatic - * decrement of the instruction pointer which was causing the SIGILL - * exception. - * **/ - - RegisterValue value((uint64_t) -1); - const RegisterInfo *reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); - if (reg_info == nullptr) - reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); - - if (reg_info != nullptr) - return DoWriteRegisterValue(reg_info->byte_offset,reg_info->name,value); - - return error; + // Copy the extended register state including the assembled ymm registers. + ::memcpy(dst, &m_fpr, sizeof(m_fpr)); + } else { + assert(false && "how do we save the floating point registers?"); + error.SetErrorString("unsure how to save the floating point registers"); + } + /** The following code is specific to Linux x86 based architectures, + * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to + * -1 to solve the bug 23659, such a setting prevents the automatic + * decrement of the instruction pointer which was causing the SIGILL + * exception. + * **/ + + RegisterValue value((uint64_t)-1); + const RegisterInfo *reg_info = + GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); + if (reg_info == nullptr) + reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); + + if (reg_info != nullptr) + return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value); + + return error; } -Error -NativeRegisterContextLinux_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - Error error; - - if (!data_sp) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); - return error; - } +Error NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; - if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); - return error; - } + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); - uint8_t *src = data_sp->GetBytes (); - if (src == nullptr) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } - ::memcpy (&m_gpr_x86_64, src, GetRegisterInfoInterface ().GetGPRSize ()); + error = WriteGPR(); + if (error.Fail()) + return error; - error = WriteGPR(); - if (error.Fail()) - return error; + src += GetRegisterInfoInterface().GetGPRSize(); + if (GetFPRType() == eFPRTypeFXSAVE) + ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + else if (GetFPRType() == eFPRTypeXSAVE) + ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); - src += GetRegisterInfoInterface ().GetGPRSize (); - if (GetFPRType () == eFPRTypeFXSAVE) - ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); - else if (GetFPRType () == eFPRTypeXSAVE) - ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + error = WriteFPR(); + if (error.Fail()) + return error; - error = WriteFPR(); - if (error.Fail()) + if (GetFPRType() == eFPRTypeXSAVE) { + lldb::ByteOrder byte_order = GetByteOrder(); + + // Parse the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; + ++reg) { + if (!CopyYMMtoXSTATE(reg, byte_order)) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " + "CopyYMMtoXSTATE() failed for reg num " + "%" PRIu32, + __FUNCTION__, reg); return error; - - if (GetFPRType() == eFPRTypeXSAVE) - { - lldb::ByteOrder byte_order = GetByteOrder(); - - // Parse the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg) - { - if (!CopyYMMtoXSTATE (reg, byte_order)) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyYMMtoXSTATE() failed for reg num %" PRIu32, __FUNCTION__, reg); - return error; - } - } + } } + } - return error; + return error; } -bool -NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable (uint32_t set_index) const -{ - // Note: Extended register sets are assumed to be at the end of g_reg_sets. - uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets; +bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable( + uint32_t set_index) const { + // Note: Extended register sets are assumed to be at the end of g_reg_sets. + uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets; - if (GetFPRType () == eFPRTypeXSAVE) - { - // AVX is the first extended register set. - ++num_sets; - } - return (set_index < num_sets); + if (GetFPRType() == eFPRTypeXSAVE) { + // AVX is the first extended register set. + ++num_sets; + } + return (set_index < num_sets); } -bool -NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const -{ - // GPRs come first. - return reg_index <= m_reg_info.last_gpr; +bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const { + // GPRs come first. + return reg_index <= m_reg_info.last_gpr; } NativeRegisterContextLinux_x86_64::FPRType -NativeRegisterContextLinux_x86_64::GetFPRType () const -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (m_fpr_type == eFPRTypeNotValid) - { - // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx. - - // Try and see if AVX register retrieval works. - m_fpr_type = eFPRTypeXSAVE; - if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail()) - { - // Fall back to general floating point with no AVX support. - m_fpr_type = eFPRTypeFXSAVE; - - // Check if FXSAVE area can be read. - if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail()) - { - if (log) - log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs failed to read XSAVE/FXSAVE area", __FUNCTION__); - } - } +NativeRegisterContextLinux_x86_64::GetFPRType() const { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (m_fpr_type == eFPRTypeNotValid) { + // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx. + + // Try and see if AVX register retrieval works. + m_fpr_type = eFPRTypeXSAVE; + if (const_cast<NativeRegisterContextLinux_x86_64 *>(this) + ->ReadFPR() + .Fail()) { + // Fall back to general floating point with no AVX support. + m_fpr_type = eFPRTypeFXSAVE; + + // Check if FXSAVE area can be read. + if (const_cast<NativeRegisterContextLinux_x86_64 *>(this) + ->ReadFPR() + .Fail()) { + if (log) + log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs " + "failed to read XSAVE/FXSAVE area", + __FUNCTION__); + } } - return m_fpr_type; + } + return m_fpr_type; } -bool -NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const -{ - return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); +bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const { + return (m_reg_info.first_fpr <= reg_index && + reg_index <= m_reg_info.last_fpr); } -bool -NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, FPRType fpr_type) const -{ - bool generic_fpr = IsFPR(reg_index); +bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, + FPRType fpr_type) const { + bool generic_fpr = IsFPR(reg_index); - if (fpr_type == eFPRTypeXSAVE) - return generic_fpr || IsAVX(reg_index); - return generic_fpr; + if (fpr_type == eFPRTypeXSAVE) + return generic_fpr || IsAVX(reg_index); + return generic_fpr; } -Error -NativeRegisterContextLinux_x86_64::WriteFPR() -{ - const FPRType fpr_type = GetFPRType (); - const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture(); - switch (fpr_type) - { - case FPRType::eFPRTypeFXSAVE: - // For 32-bit inferiors on x86_32/x86_64 architectures, - // FXSAVE area can be written using PTRACE_SETREGSET ptrace api - // For 64-bit inferiors on x86_64 architectures, - // FXSAVE area can be written using PTRACE_SETFPREGS ptrace api - switch (target_arch.GetMachine ()) - { - case llvm::Triple::x86: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG); - case llvm::Triple::x86_64: - return NativeRegisterContextLinux::WriteFPR(); - default: - assert(false && "Unhandled target architecture."); - break; - } - case FPRType::eFPRTypeXSAVE: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); +Error NativeRegisterContextLinux_x86_64::WriteFPR() { + const FPRType fpr_type = GetFPRType(); + const lldb_private::ArchSpec &target_arch = + GetRegisterInfoInterface().GetTargetArchitecture(); + switch (fpr_type) { + case FPRType::eFPRTypeFXSAVE: + // For 32-bit inferiors on x86_32/x86_64 architectures, + // FXSAVE area can be written using PTRACE_SETREGSET ptrace api + // For 64-bit inferiors on x86_64 architectures, + // FXSAVE area can be written using PTRACE_SETFPREGS ptrace api + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), + NT_PRXFPREG); + case llvm::Triple::x86_64: + return NativeRegisterContextLinux::WriteFPR(); default: - return Error("Unrecognized FPR type"); + assert(false && "Unhandled target architecture."); + break; } + case FPRType::eFPRTypeXSAVE: + return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), + NT_X86_XSTATE); + default: + return Error("Unrecognized FPR type"); + } } -bool -NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const -{ - return (m_reg_info.first_ymm <= reg_index && reg_index <= m_reg_info.last_ymm); +bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const { + return (m_reg_info.first_ymm <= reg_index && + reg_index <= m_reg_info.last_ymm); } -bool -NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order) -{ - if (!IsAVX (reg_index)) - return false; - - if (byte_order == lldb::eByteOrderLittle) - { - ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, - sizeof (XMMReg)); - ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg), - m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, - sizeof (YMMHReg)); - return true; - } - - if (byte_order == lldb::eByteOrderBig) - { - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg), - m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, - sizeof (XMMReg)); - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, - sizeof (YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order - +bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( + uint32_t reg_index, lldb::ByteOrder byte_order) { + if (!IsAVX(reg_index)) + return false; + + if (byte_order == lldb::eByteOrderLittle) { + ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + + sizeof(XMMReg), + m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + + if (byte_order == lldb::eByteOrderBig) { + ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + + sizeof(XMMReg), + m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order } -bool -NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order) -{ - if (!IsAVX(reg)) - return false; - - if (byte_order == lldb::eByteOrderLittle) - { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(YMMHReg)); - return true; - } - - if (byte_order == lldb::eByteOrderBig) - { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order +bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( + uint32_t reg, lldb::ByteOrder byte_order) { + if (!IsAVX(reg)) + return false; + + if (byte_order == lldb::eByteOrderLittle) { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(YMMHReg)); + return true; + } + + if (byte_order == lldb::eByteOrderBig) { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order } -void* -NativeRegisterContextLinux_x86_64::GetFPRBuffer() -{ - const FPRType fpr_type = GetFPRType (); - switch (fpr_type) - { - case FPRType::eFPRTypeFXSAVE: - return &m_fpr.xstate.fxsave; - case FPRType::eFPRTypeXSAVE: - return &m_iovec; - default: - return nullptr; - } +void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { + const FPRType fpr_type = GetFPRType(); + switch (fpr_type) { + case FPRType::eFPRTypeFXSAVE: + return &m_fpr.xstate.fxsave; + case FPRType::eFPRTypeXSAVE: + return &m_iovec; + default: + return nullptr; + } } -size_t -NativeRegisterContextLinux_x86_64::GetFPRSize() -{ - const FPRType fpr_type = GetFPRType (); - switch (fpr_type) - { - case FPRType::eFPRTypeFXSAVE: - return sizeof(m_fpr.xstate.fxsave); - case FPRType::eFPRTypeXSAVE: - return sizeof(m_iovec); - default: - return 0; - } +size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { + const FPRType fpr_type = GetFPRType(); + switch (fpr_type) { + case FPRType::eFPRTypeFXSAVE: + return sizeof(m_fpr.xstate.fxsave); + case FPRType::eFPRTypeXSAVE: + return sizeof(m_iovec); + default: + return 0; + } } -Error -NativeRegisterContextLinux_x86_64::ReadFPR () -{ - const FPRType fpr_type = GetFPRType (); - const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture(); - switch (fpr_type) - { - case FPRType::eFPRTypeFXSAVE: - // For 32-bit inferiors on x86_32/x86_64 architectures, - // FXSAVE area can be read using PTRACE_GETREGSET ptrace api - // For 64-bit inferiors on x86_64 architectures, - // FXSAVE area can be read using PTRACE_GETFPREGS ptrace api - switch (target_arch.GetMachine ()) - { - case llvm::Triple::x86: - return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG); - case llvm::Triple::x86_64: - return NativeRegisterContextLinux::ReadFPR(); - default: - assert(false && "Unhandled target architecture."); - break; - } - case FPRType::eFPRTypeXSAVE: - return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); +Error NativeRegisterContextLinux_x86_64::ReadFPR() { + const FPRType fpr_type = GetFPRType(); + const lldb_private::ArchSpec &target_arch = + GetRegisterInfoInterface().GetTargetArchitecture(); + switch (fpr_type) { + case FPRType::eFPRTypeFXSAVE: + // For 32-bit inferiors on x86_32/x86_64 architectures, + // FXSAVE area can be read using PTRACE_GETREGSET ptrace api + // For 64-bit inferiors on x86_64 architectures, + // FXSAVE area can be read using PTRACE_GETFPREGS ptrace api + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG); + case llvm::Triple::x86_64: + return NativeRegisterContextLinux::ReadFPR(); default: - return Error("Unrecognized FPR type"); + assert(false && "Unhandled target architecture."); + break; } + case FPRType::eFPRTypeXSAVE: + return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + default: + return Error("Unrecognized FPR type"); + } } -Error -NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); +Error NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); - RegisterValue reg_value; - Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) - { - is_hit = false; - return error; - } + RegisterValue reg_value; + Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); + if (error.Fail()) { + is_hit = false; + return error; + } - uint64_t status_bits = reg_value.GetAsUInt64(); + uint64_t status_bits = reg_value.GetAsUInt64(); - is_hit = status_bits & (1 << wp_index); + is_hit = status_bits & (1 << wp_index); - return error; + return error; } -Error -NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) { - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) - { - bool is_hit; - Error error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) { - wp_index = LLDB_INVALID_INDEX32; - return error; - } else if (is_hit) { - return error; - } +Error NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; } - wp_index = LLDB_INVALID_INDEX32; - return Error(); + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); } -Error -NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error ("Watchpoint index out of range"); +Error NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); - RegisterValue reg_value; - Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) - { - is_vacant = false; - return error; - } + RegisterValue reg_value; + Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); + if (error.Fail()) { + is_vacant = false; + return error; + } - uint64_t control_bits = reg_value.GetAsUInt64(); + uint64_t control_bits = reg_value.GetAsUInt64(); - is_vacant = !(control_bits & (1 << (2 * wp_index))); + is_vacant = !(control_bits & (1 << (2 * wp_index))); - return error; + return error; } -Error -NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex( - lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { +Error NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex( + lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error ("Watchpoint index out of range"); + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); - // Read only watchpoints aren't supported on x86_64. Fall back to read/write waitchpoints instead. - // TODO: Add logic to detect when a write happens and ignore that watchpoint hit. - if (watch_flags == 0x2) - watch_flags = 0x3; + // Read only watchpoints aren't supported on x86_64. Fall back to read/write + // waitchpoints instead. + // TODO: Add logic to detect when a write happens and ignore that watchpoint + // hit. + if (watch_flags == 0x2) + watch_flags = 0x3; - if (watch_flags != 0x1 && watch_flags != 0x3) - return Error ("Invalid read/write bits for watchpoint"); + if (watch_flags != 0x1 && watch_flags != 0x3) + return Error("Invalid read/write bits for watchpoint"); - if (size != 1 && size != 2 && size != 4 && size != 8) - return Error ("Invalid size for watchpoint"); + if (size != 1 && size != 2 && size != 4 && size != 8) + return Error("Invalid size for watchpoint"); - bool is_vacant; - Error error = IsWatchpointVacant (wp_index, is_vacant); - if (error.Fail()) return error; - if (!is_vacant) return Error("Watchpoint index not vacant"); - - RegisterValue reg_value; - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) return error; + bool is_vacant; + Error error = IsWatchpointVacant(wp_index, is_vacant); + if (error.Fail()) + return error; + if (!is_vacant) + return Error("Watchpoint index not vacant"); - // for watchpoints 0, 1, 2, or 3, respectively, - // set bits 1, 3, 5, or 7 - uint64_t enable_bit = 1 << (2 * wp_index); + RegisterValue reg_value; + error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); + if (error.Fail()) + return error; - // set bits 16-17, 20-21, 24-25, or 28-29 - // with 0b01 for write, and 0b11 for read/write - uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); + // for watchpoints 0, 1, 2, or 3, respectively, + // set bits 1, 3, 5, or 7 + uint64_t enable_bit = 1 << (2 * wp_index); - // set bits 18-19, 22-23, 26-27, or 30-31 - // with 0b00, 0b01, 0b10, or 0b11 - // for 1, 2, 8 (if supported), or 4 bytes, respectively - uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); + // set bits 16-17, 20-21, 24-25, or 28-29 + // with 0b01 for write, and 0b11 for read/write + uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); - uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + // set bits 18-19, 22-23, 26-27, or 30-31 + // with 0b00, 0b01, 0b10, or 0b11 + // for 1, 2, 8 (if supported), or 4 bytes, respectively + uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); - control_bits |= enable_bit | rw_bits | size_bits; + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr)); - if (error.Fail()) return error; + control_bits |= enable_bit | rw_bits | size_bits; - error = WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); - if (error.Fail()) return error; + error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr)); + if (error.Fail()) + return error; - error.Clear(); + error = + WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); + if (error.Fail()) return error; + + error.Clear(); + return error; } -bool -NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; - - RegisterValue reg_value; - - // for watchpoints 0, 1, 2, or 3, respectively, - // clear bits 0, 1, 2, or 3 of the debug status register (DR6) - Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) return false; - uint64_t bit_mask = 1 << wp_index; - uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); - if (error.Fail()) return false; - - // for watchpoints 0, 1, 2, or 3, respectively, - // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} - // of the debug control register (DR7) - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) return false; - bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success(); +bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint( + uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; + + RegisterValue reg_value; + + // for watchpoints 0, 1, 2, or 3, respectively, + // clear bits 0, 1, 2, or 3 of the debug status register (DR6) + Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); + if (error.Fail()) + return false; + uint64_t bit_mask = 1 << wp_index; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); + if (error.Fail()) + return false; + + // for watchpoints 0, 1, 2, or 3, respectively, + // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} + // of the debug control register (DR7) + error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); + if (error.Fail()) + return false; + bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)) + .Success(); } -Error -NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() -{ - RegisterValue reg_value; - - // clear bits {0-4} of the debug status register (DR6) - Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) return error; - uint64_t bit_mask = 0xF; - uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); - if (error.Fail()) return error; - - // clear bits {0-7,16-31} of the debug control register (DR7) - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) return error; - bit_mask = 0xFF | (0xFFFF << 16); - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); +Error NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() { + RegisterValue reg_value; + + // clear bits {0-4} of the debug status register (DR6) + Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); + if (error.Fail()) + return error; + uint64_t bit_mask = 0xF; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); + if (error.Fail()) + return error; + + // clear bits {0-7,16-31} of the debug control register (DR7) + error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); + if (error.Fail()) + return error; + bit_mask = 0xFF | (0xFFFF << 16); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); } -uint32_t -NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) - { - bool is_vacant; - Error error = IsWatchpointVacant(wp_index, is_vacant); - if (is_vacant) - { - error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); - if (error.Success()) - return wp_index; - } - if (error.Fail() && log) - { - log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s", - __FUNCTION__, error.AsCString()); - } +uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { + bool is_vacant; + Error error = IsWatchpointVacant(wp_index, is_vacant); + if (is_vacant) { + error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); + if (error.Success()) + return wp_index; + } + if (error.Fail() && log) { + log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); } - return LLDB_INVALID_INDEX32; + } + return LLDB_INVALID_INDEX32; } lldb::addr_t -NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - RegisterValue reg_value; - if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail()) - return LLDB_INVALID_ADDRESS; - return reg_value.GetAsUInt64(); +NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + RegisterValue reg_value; + if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail()) + return LLDB_INVALID_ADDRESS; + return reg_value.GetAsUInt64(); } -uint32_t -NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints () -{ - // Available debug address registers: dr0, dr1, dr2, dr3 - return 4; +uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3 + return 4; } #endif // defined(__i386__) || defined(__x86_64__) diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h index b04be4bb768..2378c771c62 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -19,149 +19,116 @@ namespace lldb_private { namespace process_linux { - class NativeProcessLinux; +class NativeProcessLinux; - class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux - { - public: - NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); +class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { +public: + NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); - uint32_t - GetRegisterSetCount () const override; + uint32_t GetRegisterSetCount() const override; - const RegisterSet * - GetRegisterSet (uint32_t set_index) const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - uint32_t - GetUserRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; - Error - ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override; + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - Error - WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - Error - ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - Error - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - Error - IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; + Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - Error - GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; - Error - IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; + Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - bool - ClearHardwareWatchpoint(uint32_t wp_index) override; + bool ClearHardwareWatchpoint(uint32_t wp_index) override; - Error - ClearAllHardwareWatchpoints () override; + Error ClearAllHardwareWatchpoints() override; - Error - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, - uint32_t watch_flags, uint32_t wp_index); + Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, + uint32_t watch_flags, uint32_t wp_index); - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; - lldb::addr_t - GetWatchpointAddress(uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - uint32_t - NumSupportedHardwareWatchpoints() override; + uint32_t NumSupportedHardwareWatchpoints() override; - protected: - void* - GetGPRBuffer() override { return &m_gpr_x86_64; } +protected: + void *GetGPRBuffer() override { return &m_gpr_x86_64; } - void* - GetFPRBuffer() override; + void *GetFPRBuffer() override; - size_t - GetFPRSize() override; + size_t GetFPRSize() override; - Error - ReadFPR() override; + Error ReadFPR() override; - Error - WriteFPR() override; + Error WriteFPR() override; - private: +private: + // Private member types. + enum FPRType { eFPRTypeNotValid = 0, eFPRTypeFXSAVE, eFPRTypeXSAVE }; - // Private member types. - enum FPRType - { - eFPRTypeNotValid = 0, - eFPRTypeFXSAVE, - eFPRTypeXSAVE - }; + // Info about register ranges. + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + uint32_t num_avx_registers; - // Info about register ranges. - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - uint32_t num_avx_registers; + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; + uint32_t first_st; + uint32_t last_st; + uint32_t first_mm; + uint32_t last_mm; + uint32_t first_xmm; + uint32_t last_xmm; + uint32_t first_ymm; + uint32_t last_ymm; - uint32_t first_st; - uint32_t last_st; - uint32_t first_mm; - uint32_t last_mm; - uint32_t first_xmm; - uint32_t last_xmm; - uint32_t first_ymm; - uint32_t last_ymm; + uint32_t first_dr; + uint32_t gpr_flags; + }; - uint32_t first_dr; - uint32_t gpr_flags; - }; + // Private member variables. + mutable FPRType m_fpr_type; + FPR m_fpr; + IOVEC m_iovec; + YMM m_ymm_set; + RegInfo m_reg_info; + uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; + uint32_t m_fctrl_offset_in_userarea; - // Private member variables. - mutable FPRType m_fpr_type; - FPR m_fpr; - IOVEC m_iovec; - YMM m_ymm_set; - RegInfo m_reg_info; - uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; - uint32_t m_fctrl_offset_in_userarea; + // Private member methods. + bool IsRegisterSetAvailable(uint32_t set_index) const; - // Private member methods. - bool IsRegisterSetAvailable (uint32_t set_index) const; + bool IsGPR(uint32_t reg_index) const; - bool - IsGPR(uint32_t reg_index) const; + FPRType GetFPRType() const; - FPRType - GetFPRType () const; + bool IsFPR(uint32_t reg_index) const; - bool - IsFPR(uint32_t reg_index) const; + bool IsFPR(uint32_t reg_index, FPRType fpr_type) const; - bool - IsFPR(uint32_t reg_index, FPRType fpr_type) const; + bool CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order); - bool - CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order); + bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); - bool - CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); - - bool - IsAVX (uint32_t reg_index) const; - }; + bool IsAVX(uint32_t reg_index) const; +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp index 6509022b6c6..ebe80da81c4 100644 --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -29,481 +29,454 @@ #include <sys/syscall.h> // Try to define a macro to encapsulate the tgkill syscall -#define tgkill(pid, tid, sig) \ - syscall(__NR_tgkill, static_cast< ::pid_t>(pid), static_cast< ::pid_t>(tid), sig) +#define tgkill(pid, tid, sig) \ + syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \ + sig) using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; -namespace -{ - void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header) - { - switch (stop_info.reason) - { - case eStopReasonNone: - log.Printf ("%s: %s no stop reason", __FUNCTION__, header); - return; - case eStopReasonTrace: - log.Printf ("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); - return; - case eStopReasonBreakpoint: - log.Printf ("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); - return; - case eStopReasonWatchpoint: - log.Printf ("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); - return; - case eStopReasonSignal: - log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); - return; - case eStopReasonException: - log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type); - return; - case eStopReasonExec: - log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); - return; - case eStopReasonPlanComplete: - log.Printf ("%s: %s plan complete", __FUNCTION__, header); - return; - case eStopReasonThreadExiting: - log.Printf ("%s: %s thread exiting", __FUNCTION__, header); - return; - case eStopReasonInstrumentation: - log.Printf ("%s: %s instrumentation", __FUNCTION__, header); - return; - default: - log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason)); - } - } +namespace { +void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info, + const char *const header) { + switch (stop_info.reason) { + case eStopReasonNone: + log.Printf("%s: %s no stop reason", __FUNCTION__, header); + return; + case eStopReasonTrace: + log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, + stop_info.details.signal.signo); + return; + case eStopReasonBreakpoint: + log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, + header, stop_info.details.signal.signo); + return; + case eStopReasonWatchpoint: + log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, + header, stop_info.details.signal.signo); + return; + case eStopReasonSignal: + log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, + stop_info.details.signal.signo); + return; + case eStopReasonException: + log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, + stop_info.details.exception.type); + return; + case eStopReasonExec: + log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, + stop_info.details.signal.signo); + return; + case eStopReasonPlanComplete: + log.Printf("%s: %s plan complete", __FUNCTION__, header); + return; + case eStopReasonThreadExiting: + log.Printf("%s: %s thread exiting", __FUNCTION__, header); + return; + case eStopReasonInstrumentation: + log.Printf("%s: %s instrumentation", __FUNCTION__, header); + return; + default: + log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, + static_cast<uint32_t>(stop_info.reason)); + } } - -NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) : - NativeThreadProtocol (process, tid), - m_state (StateType::eStateInvalid), - m_stop_info (), - m_reg_context_sp (), - m_stop_description () -{ } -std::string -NativeThreadLinux::GetName() -{ - NativeProcessProtocolSP process_sp = m_process_wp.lock (); - if (!process_sp) - return "<unknown: no process>"; - - // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ()); - llvm::SmallString<32> thread_name; - HostNativeThread::GetName(GetID(), thread_name); - return thread_name.c_str(); +NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process, + lldb::tid_t tid) + : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), + m_stop_info(), m_reg_context_sp(), m_stop_description() {} + +std::string NativeThreadLinux::GetName() { + NativeProcessProtocolSP process_sp = m_process_wp.lock(); + if (!process_sp) + return "<unknown: no process>"; + + // const NativeProcessLinux *const process = + // reinterpret_cast<NativeProcessLinux*> (process_sp->get ()); + llvm::SmallString<32> thread_name; + HostNativeThread::GetName(GetID(), thread_name); + return thread_name.c_str(); } -lldb::StateType -NativeThreadLinux::GetState () -{ - return m_state; -} +lldb::StateType NativeThreadLinux::GetState() { return m_state; } + +bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info, + std::string &description) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + description.clear(); + + switch (m_state) { + case eStateStopped: + case eStateCrashed: + case eStateExited: + case eStateSuspended: + case eStateUnloaded: + if (log) + LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:"); + stop_info = m_stop_info; + description = m_stop_description; + if (log) + LogThreadStopInfo(*log, stop_info, "returned stop_info:"); + return true; -bool -NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - - description.clear(); - - switch (m_state) - { - case eStateStopped: - case eStateCrashed: - case eStateExited: - case eStateSuspended: - case eStateUnloaded: - if (log) - LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:"); - stop_info = m_stop_info; - description = m_stop_description; - if (log) - LogThreadStopInfo (*log, stop_info, "returned stop_info:"); - - return true; - - case eStateInvalid: - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - if (log) - { - log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason", - __FUNCTION__, GetID (), StateAsCString (m_state)); - } - return false; + case eStateInvalid: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + if (log) { + log->Printf("NativeThreadLinux::%s tid %" PRIu64 + " in state %s cannot answer stop reason", + __FUNCTION__, GetID(), StateAsCString(m_state)); } - llvm_unreachable("unhandled StateType!"); + return false; + } + llvm_unreachable("unhandled StateType!"); } -NativeRegisterContextSP -NativeThreadLinux::GetRegisterContext () -{ - // Return the register context if we already created it. - if (m_reg_context_sp) - return m_reg_context_sp; +NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() { + // Return the register context if we already created it. + if (m_reg_context_sp) + return m_reg_context_sp; - NativeProcessProtocolSP m_process_sp = m_process_wp.lock (); - if (!m_process_sp) - return NativeRegisterContextSP (); + NativeProcessProtocolSP m_process_sp = m_process_wp.lock(); + if (!m_process_sp) + return NativeRegisterContextSP(); - ArchSpec target_arch; - if (!m_process_sp->GetArchitecture (target_arch)) - return NativeRegisterContextSP (); + ArchSpec target_arch; + if (!m_process_sp->GetArchitecture(target_arch)) + return NativeRegisterContextSP(); - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch, - *this, - concrete_frame_idx)); + const uint32_t concrete_frame_idx = 0; + m_reg_context_sp.reset( + NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + target_arch, *this, concrete_frame_idx)); - return m_reg_context_sp; + return m_reg_context_sp; } -Error -NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) -{ - if (!hardware) - return Error ("not implemented"); - if (m_state == eStateLaunching) - return Error (); - Error error = RemoveWatchpoint(addr); - if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext (); - uint32_t wp_index = - reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags); - if (wp_index == LLDB_INVALID_INDEX32) - return Error ("Setting hardware watchpoint failed."); - m_watchpoint_index_map.insert({addr, wp_index}); - return Error (); +Error NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, bool hardware) { + if (!hardware) + return Error("not implemented"); + if (m_state == eStateLaunching) + return Error(); + Error error = RemoveWatchpoint(addr); + if (error.Fail()) + return error; + NativeRegisterContextSP reg_ctx = GetRegisterContext(); + uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + if (wp_index == LLDB_INVALID_INDEX32) + return Error("Setting hardware watchpoint failed."); + m_watchpoint_index_map.insert({addr, wp_index}); + return Error(); } -Error -NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr) -{ - auto wp = m_watchpoint_index_map.find(addr); - if (wp == m_watchpoint_index_map.end()) - return Error (); - uint32_t wp_index = wp->second; - m_watchpoint_index_map.erase(wp); - if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) - return Error (); - return Error ("Clearing hardware watchpoint failed."); +Error NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) { + auto wp = m_watchpoint_index_map.find(addr); + if (wp == m_watchpoint_index_map.end()) + return Error(); + uint32_t wp_index = wp->second; + m_watchpoint_index_map.erase(wp); + if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + return Error(); + return Error("Clearing hardware watchpoint failed."); } -Error -NativeThreadLinux::Resume(uint32_t signo) -{ - const StateType new_state = StateType::eStateRunning; - MaybeLogStateChange (new_state); - m_state = new_state; - - m_stop_info.reason = StopReason::eStopReasonNone; - m_stop_description.clear(); - - // If watchpoints have been set, but none on this thread, - // then this is a new thread. So set all existing watchpoints. - if (m_watchpoint_index_map.empty()) - { - NativeProcessLinux &process = GetProcess(); - - const auto &watchpoint_map = process.GetWatchpointMap(); - GetRegisterContext()->ClearAllHardwareWatchpoints(); - for (const auto &pair : watchpoint_map) - { - const auto &wp = pair.second; - SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); - } - } +Error NativeThreadLinux::Resume(uint32_t signo) { + const StateType new_state = StateType::eStateRunning; + MaybeLogStateChange(new_state); + m_state = new_state; - intptr_t data = 0; + m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_description.clear(); - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; + // If watchpoints have been set, but none on this thread, + // then this is a new thread. So set all existing watchpoints. + if (m_watchpoint_index_map.empty()) { + NativeProcessLinux &process = GetProcess(); - return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, reinterpret_cast<void *>(data)); -} + const auto &watchpoint_map = process.GetWatchpointMap(); + GetRegisterContext()->ClearAllHardwareWatchpoints(); + for (const auto &pair : watchpoint_map) { + const auto &wp = pair.second; + SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); + } + } -void -NativeThreadLinux::MaybePrepareSingleStepWorkaround() -{ - if (!SingleStepWorkaroundNeeded()) - return; + intptr_t data = 0; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; - if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) - { - // This should really not fail. But, just in case... - if (log) - { - Error error(errno, eErrorTypePOSIX); - log->Printf("NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, - m_tid, error.AsCString()); - } - return; - } + return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, + reinterpret_cast<void *>(data)); +} - cpu_set_t set; - CPU_ZERO(&set); - CPU_SET(0, &set); - if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 && log) - { - // This may fail in very locked down systems, if the thread is not allowed to run on - // cpu 0. If that happens, only thing we can do is it log it and continue... - Error error(errno, eErrorTypePOSIX); - log->Printf("NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, m_tid, - error.AsCString()); +void NativeThreadLinux::MaybePrepareSingleStepWorkaround() { + if (!SingleStepWorkaroundNeeded()) + return; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, + &m_original_cpu_set) != 0) { + // This should really not fail. But, just in case... + if (log) { + Error error(errno, eErrorTypePOSIX); + log->Printf( + "NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64 + ": %s", + __FUNCTION__, m_tid, error.AsCString()); } + return; + } + + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); + if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 && + log) { + // This may fail in very locked down systems, if the thread is not allowed + // to run on + // cpu 0. If that happens, only thing we can do is it log it and continue... + Error error(errno, eErrorTypePOSIX); + log->Printf( + "NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64 + ": %s", + __FUNCTION__, m_tid, error.AsCString()); + } } -void -NativeThreadLinux::MaybeCleanupSingleStepWorkaround() -{ - if (!SingleStepWorkaroundNeeded()) - return; - - if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) - { - Error error(errno, eErrorTypePOSIX); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - log->Printf("NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, - m_tid, error.AsCString()); - } +void NativeThreadLinux::MaybeCleanupSingleStepWorkaround() { + if (!SingleStepWorkaroundNeeded()) + return; + + if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, + &m_original_cpu_set) != 0) { + Error error(errno, eErrorTypePOSIX); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + log->Printf( + "NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64 + ": %s", + __FUNCTION__, m_tid, error.AsCString()); + } } -Error -NativeThreadLinux::SingleStep(uint32_t signo) -{ - const StateType new_state = StateType::eStateStepping; - MaybeLogStateChange (new_state); - m_state = new_state; - m_stop_info.reason = StopReason::eStopReasonNone; - - MaybePrepareSingleStepWorkaround(); - - intptr_t data = 0; - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; - - // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the - // next instruction has been setup in NativeProcessLinux::Resume. - return NativeProcessLinux::PtraceWrapper(GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP - : PTRACE_CONT, - m_tid, nullptr, reinterpret_cast<void *>(data)); +Error NativeThreadLinux::SingleStep(uint32_t signo) { + const StateType new_state = StateType::eStateStepping; + MaybeLogStateChange(new_state); + m_state = new_state; + m_stop_info.reason = StopReason::eStopReasonNone; + + MaybePrepareSingleStepWorkaround(); + + intptr_t data = 0; + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; + + // If hardware single-stepping is not supported, we just do a continue. The + // breakpoint on the + // next instruction has been setup in NativeProcessLinux::Resume. + return NativeProcessLinux::PtraceWrapper( + GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP + : PTRACE_CONT, + m_tid, nullptr, reinterpret_cast<void *>(data)); } -void -NativeThreadLinux::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo); - - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonSignal; - m_stop_info.details.signal.signo = signo; - - m_stop_description.clear(); - if (info) - { - switch (signo) - { - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - //In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit address. - const auto reason = (info->si_signo == SIGBUS && info->si_code == SI_KERNEL) ? - CrashReason::eInvalidAddress : GetCrashReason(*info); - m_stop_description = GetCrashReasonString(reason, reinterpret_cast<uintptr_t>(info->si_addr)); - break; - } +void NativeThreadLinux::SetStoppedBySignal(uint32_t signo, + const siginfo_t *info) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("NativeThreadLinux::%s called with signal 0x%02" PRIx32, + __FUNCTION__, signo); + + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonSignal; + m_stop_info.details.signal.signo = signo; + + m_stop_description.clear(); + if (info) { + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit + // address. + const auto reason = + (info->si_signo == SIGBUS && info->si_code == SI_KERNEL) + ? CrashReason::eInvalidAddress + : GetCrashReason(*info); + m_stop_description = GetCrashReasonString( + reason, reinterpret_cast<uintptr_t>(info->si_addr)); + break; } + } } -bool -NativeThreadLinux::IsStopped (int *signo) -{ - if (!StateIsStoppedState (m_state, false)) - return false; - - // If we are stopped by a signal, return the signo. - if (signo && - m_state == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonSignal) - { - *signo = m_stop_info.details.signal.signo; - } +bool NativeThreadLinux::IsStopped(int *signo) { + if (!StateIsStoppedState(m_state, false)) + return false; - // Regardless, we are stopped. - return true; + // If we are stopped by a signal, return the signo. + if (signo && m_state == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonSignal) { + *signo = m_stop_info.details.signal.signo; + } + + // Regardless, we are stopped. + return true; } -void -NativeThreadLinux::SetStopped() -{ - if (m_state == StateType::eStateStepping) - MaybeCleanupSingleStepWorkaround(); +void NativeThreadLinux::SetStopped() { + if (m_state == StateType::eStateStepping) + MaybeCleanupSingleStepWorkaround(); - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange(new_state); - m_state = new_state; - m_stop_description.clear(); + const StateType new_state = StateType::eStateStopped; + MaybeLogStateChange(new_state); + m_state = new_state; + m_stop_description.clear(); } -void -NativeThreadLinux::SetStoppedByExec () -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("NativeThreadLinux::%s()", __FUNCTION__); +void NativeThreadLinux::SetStoppedByExec() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("NativeThreadLinux::%s()", __FUNCTION__); - SetStopped(); + SetStopped(); - m_stop_info.reason = StopReason::eStopReasonExec; - m_stop_info.details.signal.signo = SIGSTOP; + m_stop_info.reason = StopReason::eStopReasonExec; + m_stop_info.details.signal.signo = SIGSTOP; } -void -NativeThreadLinux::SetStoppedByBreakpoint () -{ - SetStopped(); +void NativeThreadLinux::SetStoppedByBreakpoint() { + SetStopped(); - m_stop_info.reason = StopReason::eStopReasonBreakpoint; - m_stop_info.details.signal.signo = SIGTRAP; - m_stop_description.clear(); + m_stop_info.reason = StopReason::eStopReasonBreakpoint; + m_stop_info.details.signal.signo = SIGTRAP; + m_stop_description.clear(); } -void -NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index) -{ - SetStopped(); +void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { + SetStopped(); - lldbassert(wp_index != LLDB_INVALID_INDEX32 && - "wp_index cannot be invalid"); + lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); - std::ostringstream ostr; - ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; - ostr << wp_index; + std::ostringstream ostr; + ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << wp_index; - /* - * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example: - * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then - * watch exception is generated even when 'n' is read/written. To handle this case, - * find the base address of the load/store instruction and append it in the stop-info - * packet. - */ - ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + /* + * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For + * example: + * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at + * 'm', then + * watch exception is generated even when 'n' is read/written. To handle this + * case, + * find the base address of the load/store instruction and append it in the + * stop-info + * packet. + */ + ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); - m_stop_description = ostr.str(); + m_stop_description = ostr.str(); - m_stop_info.reason = StopReason::eStopReasonWatchpoint; - m_stop_info.details.signal.signo = SIGTRAP; + m_stop_info.reason = StopReason::eStopReasonWatchpoint; + m_stop_info.details.signal.signo = SIGTRAP; } -bool -NativeThreadLinux::IsStoppedAtBreakpoint () -{ - return GetState () == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonBreakpoint; +bool NativeThreadLinux::IsStoppedAtBreakpoint() { + return GetState() == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonBreakpoint; } -bool -NativeThreadLinux::IsStoppedAtWatchpoint () -{ - return GetState () == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonWatchpoint; +bool NativeThreadLinux::IsStoppedAtWatchpoint() { + return GetState() == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonWatchpoint; } -void -NativeThreadLinux::SetStoppedByTrace () -{ - SetStopped(); +void NativeThreadLinux::SetStoppedByTrace() { + SetStopped(); - m_stop_info.reason = StopReason::eStopReasonTrace; - m_stop_info.details.signal.signo = SIGTRAP; + m_stop_info.reason = StopReason::eStopReasonTrace; + m_stop_info.details.signal.signo = SIGTRAP; } -void -NativeThreadLinux::SetStoppedWithNoReason () -{ - SetStopped(); +void NativeThreadLinux::SetStoppedWithNoReason() { + SetStopped(); - m_stop_info.reason = StopReason::eStopReasonNone; - m_stop_info.details.signal.signo = 0; + m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_info.details.signal.signo = 0; } -void -NativeThreadLinux::SetExited () -{ - const StateType new_state = StateType::eStateExited; - MaybeLogStateChange (new_state); - m_state = new_state; +void NativeThreadLinux::SetExited() { + const StateType new_state = StateType::eStateExited; + MaybeLogStateChange(new_state); + m_state = new_state; - m_stop_info.reason = StopReason::eStopReasonThreadExiting; + m_stop_info.reason = StopReason::eStopReasonThreadExiting; } -Error -NativeThreadLinux::RequestStop () -{ - Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); +Error NativeThreadLinux::RequestStop() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - NativeProcessLinux &process = GetProcess(); + NativeProcessLinux &process = GetProcess(); + + lldb::pid_t pid = process.GetID(); + lldb::tid_t tid = GetID(); - lldb::pid_t pid = process.GetID(); - lldb::tid_t tid = GetID(); + if (log) + log->Printf("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 + ", tid: %" PRIu64 ")", + __FUNCTION__, pid, tid); + Error err; + errno = 0; + if (::tgkill(pid, tid, SIGSTOP) != 0) { + err.SetErrorToErrno(); if (log) - log->Printf ("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid); - - Error err; - errno = 0; - if (::tgkill (pid, tid, SIGSTOP) != 0) - { - err.SetErrorToErrno (); - if (log) - log->Printf ("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ()); - } + log->Printf("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 + ", SIGSTOP) failed: %s", + __FUNCTION__, pid, tid, err.AsCString()); + } - return err; + return err; } -void -NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - // If we're not logging, we're done. - if (!log) - return; - - // If this is a state change to the same state, we're done. - lldb::StateType old_state = m_state; - if (new_state == old_state) - return; - - NativeProcessProtocolSP m_process_sp = m_process_wp.lock (); - lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID; - - // Log it. - log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state)); +void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + // If we're not logging, we're done. + if (!log) + return; + + // If this is a state change to the same state, we're done. + lldb::StateType old_state = m_state; + if (new_state == old_state) + return; + + NativeProcessProtocolSP m_process_sp = m_process_wp.lock(); + lldb::pid_t pid = + m_process_sp ? m_process_sp->GetID() : LLDB_INVALID_PROCESS_ID; + + // Log it. + log->Printf("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 + ") changing from state %s to %s", + pid, GetID(), StateAsCString(old_state), + StateAsCString(new_state)); } -NativeProcessLinux & -NativeThreadLinux::GetProcess() -{ - auto process_sp = std::static_pointer_cast<NativeProcessLinux>(NativeThreadProtocol::GetProcess()); - assert(process_sp); - return *process_sp; +NativeProcessLinux &NativeThreadLinux::GetProcess() { + auto process_sp = std::static_pointer_cast<NativeProcessLinux>( + NativeThreadProtocol::GetProcess()); + assert(process_sp); + return *process_sp; } diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h index f1b6a6e4478..f170bb1e850 100644 --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -10,8 +10,8 @@ #ifndef liblldb_NativeThreadLinux_H_ #define liblldb_NativeThreadLinux_H_ -#include "lldb/lldb-private-forward.h" #include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/lldb-private-forward.h" #include <sched.h> @@ -22,118 +22,95 @@ namespace lldb_private { namespace process_linux { - class NativeProcessLinux; +class NativeProcessLinux; - class NativeThreadLinux : public NativeThreadProtocol - { - friend class NativeProcessLinux; +class NativeThreadLinux : public NativeThreadProtocol { + friend class NativeProcessLinux; - public: - NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid); +public: + NativeThreadLinux(NativeProcessLinux *process, lldb::tid_t tid); - // --------------------------------------------------------------------- - // 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; - private: - // --------------------------------------------------------------------- - // Interface for friend classes - // --------------------------------------------------------------------- +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); + /// 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); - 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); - 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(); - // --------------------------------------------------------------------- - // Private interface - // --------------------------------------------------------------------- - void - MaybeLogStateChange (lldb::StateType new_state); + // --------------------------------------------------------------------- + // Private interface + // --------------------------------------------------------------------- + void MaybeLogStateChange(lldb::StateType new_state); - NativeProcessLinux & - GetProcess(); + NativeProcessLinux &GetProcess(); - void - SetStopped(); + void SetStopped(); - inline void - MaybePrepareSingleStepWorkaround(); + inline void MaybePrepareSingleStepWorkaround(); - inline void - MaybeCleanupSingleStepWorkaround(); + inline void MaybeCleanupSingleStepWorkaround(); - // --------------------------------------------------------------------- - // Member Variables - // --------------------------------------------------------------------- - 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. - }; + // --------------------------------------------------------------------- + // Member Variables + // --------------------------------------------------------------------- + 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. +}; - typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP; +typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp index 4d1f231f4f9..a1bb7a6e09d 100644 --- a/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp @@ -26,83 +26,78 @@ using namespace lldb_private; using namespace lldb_private::process_linux; -lldb::DataBufferSP -ProcFileReader::ReadIntoDataBuffer (lldb::pid_t pid, const char *name) -{ - int fd; - char path[PATH_MAX]; - - // Make sure we've got a nil terminated buffer for all the folks calling - // GetBytes() directly off our returned DataBufferSP if we hit an error. - lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0)); - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0) - { - if ((fd = open (path, O_RDONLY, 0)) >= 0) - { - size_t bytes_read = 0; - std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); - - for (;;) - { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - if (status == 0) - { - buf_ap->SetByteSize (bytes_read); - buf_sp.reset (buf_ap.release()); - break; - } - - bytes_read += status; - - if (avail - status == 0) - buf_ap->SetByteSize (2 * buf_ap->GetByteSize()); - } - - close (fd); +lldb::DataBufferSP ProcFileReader::ReadIntoDataBuffer(lldb::pid_t pid, + const char *name) { + int fd; + char path[PATH_MAX]; + + // Make sure we've got a nil terminated buffer for all the folks calling + // GetBytes() directly off our returned DataBufferSP if we hit an error. + lldb::DataBufferSP buf_sp(new DataBufferHeap(1, 0)); + + // Ideally, we would simply create a FileSpec and call ReadFileContents. + // However, files in procfs have zero size (since they are, in general, + // dynamically generated by the kernel) which is incompatible with the + // current ReadFileContents implementation. Therefore we simply stream the + // data into a DataBuffer ourselves. + if (snprintf(path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0) { + if ((fd = open(path, O_RDONLY, 0)) >= 0) { + size_t bytes_read = 0; + std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); + + for (;;) { + size_t avail = buf_ap->GetByteSize() - bytes_read; + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); + + if (status < 0) + break; + + if (status == 0) { + buf_ap->SetByteSize(bytes_read); + buf_sp.reset(buf_ap.release()); + break; } - } - - return buf_sp; -} -Error -ProcFileReader::ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser) -{ - Error error; - - // Try to open the /proc/{pid}/maps entry. - char filename [PATH_MAX]; - snprintf (filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name); - filename[sizeof (filename) - 1] = '\0'; - - std::ifstream proc_file (filename); - if (proc_file.fail ()) - { - error.SetErrorStringWithFormat ("failed to open file '%s'", filename); - return error; - } + bytes_read += status; - // Read the file line by line, processing until either end of file or when the line_parser returns false. - std::string line; - bool should_continue = true; + if (avail - status == 0) + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); + } - while (should_continue && std::getline (proc_file, line)) - { - // Pass the line over to the line_parser for processing. If the line_parser returns false, we - // stop processing. - should_continue = line_parser (line); + close(fd); } + } + + return buf_sp; +} +Error ProcFileReader::ProcessLineByLine( + lldb::pid_t pid, const char *name, + std::function<bool(const std::string &line)> line_parser) { + Error error; + + // Try to open the /proc/{pid}/maps entry. + char filename[PATH_MAX]; + snprintf(filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name); + filename[sizeof(filename) - 1] = '\0'; + + std::ifstream proc_file(filename); + if (proc_file.fail()) { + error.SetErrorStringWithFormat("failed to open file '%s'", filename); return error; + } + + // Read the file line by line, processing until either end of file or when the + // line_parser returns false. + std::string line; + bool should_continue = true; + + while (should_continue && std::getline(proc_file, line)) { + // Pass the line over to the line_parser for processing. If the line_parser + // returns false, we + // stop processing. + should_continue = line_parser(line); + } + + return error; } diff --git a/lldb/source/Plugins/Process/Linux/ProcFileReader.h b/lldb/source/Plugins/Process/Linux/ProcFileReader.h index 7b381243306..dcdb3553d8c 100644 --- a/lldb/source/Plugins/Process/Linux/ProcFileReader.h +++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.h @@ -18,18 +18,18 @@ namespace lldb_private { namespace process_linux { - class ProcFileReader - { - public: - - static lldb::DataBufferSP - ReadIntoDataBuffer (lldb::pid_t pid, const char *name); - - /// Parse the /proc/{@a pid}/{@a name} file line by line, passing each line to line_parser, until - /// either end of file or until line_parser returns false. - static Error - ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser); - }; +class ProcFileReader { +public: + static lldb::DataBufferSP ReadIntoDataBuffer(lldb::pid_t pid, + const char *name); + + /// Parse the /proc/{@a pid}/{@a name} file line by line, passing each line to + /// line_parser, until + /// either end of file or until line_parser returns false. + static Error + ProcessLineByLine(lldb::pid_t pid, const char *name, + std::function<bool(const std::string &line)> line_parser); +}; } // namespace process_linux } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Linux/Procfs.h b/lldb/source/Plugins/Process/Linux/Procfs.h index cad433fb095..1d9c9dbe273 100644 --- a/lldb/source/Plugins/Process/Linux/Procfs.h +++ b/lldb/source/Plugins/Process/Linux/Procfs.h @@ -13,19 +13,19 @@ #include <sys/ptrace.h> #ifdef __ANDROID__ -#if defined (__arm64__) || defined (__aarch64__) +#if defined(__arm64__) || defined(__aarch64__) typedef unsigned long elf_greg_t; -typedef elf_greg_t elf_gregset_t[(sizeof (struct user_pt_regs) / sizeof(elf_greg_t))]; +typedef elf_greg_t + elf_gregset_t[(sizeof(struct user_pt_regs) / sizeof(elf_greg_t))]; typedef struct user_fpsimd_state elf_fpregset_t; #ifndef NT_FPREGSET - #define NT_FPREGSET NT_PRFPREG +#define NT_FPREGSET NT_PRFPREG #endif // NT_FPREGSET -#elif defined (__mips__) +#elif defined(__mips__) #ifndef NT_FPREGSET - #define NT_FPREGSET NT_PRFPREG +#define NT_FPREGSET NT_PRFPREG #endif // NT_FPREGSET #endif -#else // __ANDROID__ +#else // __ANDROID__ #include <sys/procfs.h> #endif // __ANDROID__ - diff --git a/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp b/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp index 8c557d4b6ff..b23c1bd245d 100644 --- a/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp +++ b/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp @@ -25,153 +25,142 @@ using namespace lldb_private::process_linux; #if defined(__arm64__) || defined(__aarch64__) -namespace -{ - -void LLVM_ATTRIBUTE_NORETURN -Child() -{ - if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) - _exit(1); - - // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer will fiddle with our cpu - // affinities and monitor the behaviour. - for (;;) - { - raise(SIGSTOP); - - // Generate a bunch of instructions here, so that a single-step does not land in the - // raise() accidentally. If single-stepping works, we will be spinning in this loop. If - // it doesn't, we'll land in the raise() call above. - for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i) - ; - } +namespace { + +void LLVM_ATTRIBUTE_NORETURN Child() { + if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) + _exit(1); + + // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer + // will fiddle with our cpu + // affinities and monitor the behaviour. + for (;;) { + raise(SIGSTOP); + + // Generate a bunch of instructions here, so that a single-step does not + // land in the + // raise() accidentally. If single-stepping works, we will be spinning in + // this loop. If + // it doesn't, we'll land in the raise() call above. + for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i) + ; + } } -struct ChildDeleter -{ - ::pid_t pid; +struct ChildDeleter { + ::pid_t pid; - ~ChildDeleter() - { - int status; - kill(pid, SIGKILL); // Kill the child. - waitpid(pid, &status, __WALL); // Pick up the remains. - } + ~ChildDeleter() { + int status; + kill(pid, SIGKILL); // Kill the child. + waitpid(pid, &status, __WALL); // Pick up the remains. + } }; } // end anonymous namespace -bool -impl::SingleStepWorkaroundNeeded() -{ - // We shall spawn a child, and use it to verify the debug capabilities of the cpu. We shall - // iterate through the cpus, bind the child to each one in turn, and verify that - // single-stepping works on that cpu. A workaround is needed if we find at least one broken - // cpu. - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - Error error; - ::pid_t child_pid = fork(); - if (child_pid == -1) - { - if (log) - { - error.SetErrorToErrno(); - log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString()); - } - return false; +bool impl::SingleStepWorkaroundNeeded() { + // We shall spawn a child, and use it to verify the debug capabilities of the + // cpu. We shall + // iterate through the cpus, bind the child to each one in turn, and verify + // that + // single-stepping works on that cpu. A workaround is needed if we find at + // least one broken + // cpu. + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + Error error; + ::pid_t child_pid = fork(); + if (child_pid == -1) { + if (log) { + error.SetErrorToErrno(); + log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString()); + } + return false; + } + if (child_pid == 0) + Child(); + + ChildDeleter child_deleter{child_pid}; + cpu_set_t available_cpus; + if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == + -1) { + if (log) { + error.SetErrorToErrno(); + log->Printf("%s failed to get available cpus: %s", __FUNCTION__, + error.AsCString()); + } + return false; + } + + int status; + ::pid_t wpid = waitpid(child_pid, &status, __WALL); + if (wpid != child_pid || !WIFSTOPPED(status)) { + if (log) { + error.SetErrorToErrno(); + log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, + error.AsCString()); } - if (child_pid == 0) - Child(); - - ChildDeleter child_deleter{child_pid}; - cpu_set_t available_cpus; - if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == -1) - { - if (log) - { - error.SetErrorToErrno(); - log->Printf("%s failed to get available cpus: %s", __FUNCTION__, error.AsCString()); - } - return false; + return false; + } + + unsigned cpu; + for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) { + if (!CPU_ISSET(cpu, &available_cpus)) + continue; + + cpu_set_t cpus; + CPU_ZERO(&cpus); + CPU_SET(cpu, &cpus); + if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) { + if (log) { + error.SetErrorToErrno(); + log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, + error.AsCString()); + } + continue; } int status; - ::pid_t wpid = waitpid(child_pid, &status, __WALL); - if (wpid != child_pid || !WIFSTOPPED(status)) - { - if (log) - { - error.SetErrorToErrno(); - log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString()); - } - return false; + error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); + if (error.Fail()) { + if (log) + log->Printf("%s single step failed: %s", __FUNCTION__, + error.AsCString()); + break; } - unsigned cpu; - for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) - { - if (!CPU_ISSET(cpu, &available_cpus)) - continue; - - cpu_set_t cpus; - CPU_ZERO(&cpus); - CPU_SET(cpu, &cpus); - if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) - { - if (log) - { - error.SetErrorToErrno(); - log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, error.AsCString()); - } - continue; - } - - int status; - error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); - if (error.Fail()) - { - if (log) - log->Printf("%s single step failed: %s", __FUNCTION__, error.AsCString()); - break; - } - - wpid = waitpid(child_pid, &status, __WALL); - if (wpid != child_pid || !WIFSTOPPED(status)) - { - if (log) - { - error.SetErrorToErrno(); - log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString()); - } - break; - } - if (WSTOPSIG(status) != SIGTRAP) - { - if (log) - log->Printf("%s single stepping on cpu %d failed with status %x", __FUNCTION__, cpu, status); - break; - } + wpid = waitpid(child_pid, &status, __WALL); + if (wpid != child_pid || !WIFSTOPPED(status)) { + if (log) { + error.SetErrorToErrno(); + log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, + status, error.AsCString()); + } + break; } - - // cpu is either the index of the first broken cpu, or CPU_SETSIZE. - if (cpu == 0) - { - if (log) - log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING LIKELY TO BE UNRELIABLE.", - __FUNCTION__); - // No point in trying to fiddle with the affinities, just give it our best shot and see how it goes. - return false; + if (WSTOPSIG(status) != SIGTRAP) { + if (log) + log->Printf("%s single stepping on cpu %d failed with status %x", + __FUNCTION__, cpu, status); + break; } + } + + // cpu is either the index of the first broken cpu, or CPU_SETSIZE. + if (cpu == 0) { + if (log) + log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING " + "LIKELY TO BE UNRELIABLE.", + __FUNCTION__); + // No point in trying to fiddle with the affinities, just give it our best + // shot and see how it goes. + return false; + } - return cpu != CPU_SETSIZE; + return cpu != CPU_SETSIZE; } #else // !arm64 -bool -impl::SingleStepWorkaroundNeeded() -{ - return false; -} +bool impl::SingleStepWorkaroundNeeded() { return false; } #endif diff --git a/lldb/source/Plugins/Process/Linux/SingleStepCheck.h b/lldb/source/Plugins/Process/Linux/SingleStepCheck.h index f83f7c973f8..6e3310da840 100644 --- a/lldb/source/Plugins/Process/Linux/SingleStepCheck.h +++ b/lldb/source/Plugins/Process/Linux/SingleStepCheck.h @@ -10,30 +10,29 @@ #ifndef liblldb_SingleStepCheck_H_ #define liblldb_SingleStepCheck_H_ -namespace lldb_private -{ -namespace process_linux -{ +namespace lldb_private { +namespace process_linux { -namespace impl -{ -extern bool -SingleStepWorkaroundNeeded(); +namespace impl { +extern bool SingleStepWorkaroundNeeded(); } -// arm64 linux had a bug which prevented single-stepping and watchpoints from working on non-boot -// cpus, due to them being incorrectly initialized after coming out of suspend. This issue is -// particularly affecting android M, which uses suspend ("doze mode") quite aggressively. This -// code detects that situation and makes single-stepping work by doing all the step operations on +// arm64 linux had a bug which prevented single-stepping and watchpoints from +// working on non-boot +// cpus, due to them being incorrectly initialized after coming out of suspend. +// This issue is +// particularly affecting android M, which uses suspend ("doze mode") quite +// aggressively. This +// code detects that situation and makes single-stepping work by doing all the +// step operations on // the boot cpu. // -// The underlying issue has been fixed in android N and linux 4.4. This code can be removed once +// The underlying issue has been fixed in android N and linux 4.4. This code can +// be removed once // these systems become obsolete. -inline bool -SingleStepWorkaroundNeeded() -{ - static bool value = impl::SingleStepWorkaroundNeeded(); - return value; +inline bool SingleStepWorkaroundNeeded() { + static bool value = impl::SingleStepWorkaroundNeeded(); + return value; } } // end namespace process_linux } // end namespace lldb_private diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index bb0dfcfdb35..c016677674a 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "CommunicationKDP.h" // C Includes @@ -38,39 +37,26 @@ using namespace lldb_private; // CommunicationKDP constructor //---------------------------------------------------------------------- CommunicationKDP::CommunicationKDP(const char *comm_name) - : Communication(comm_name), - m_addr_byte_size(4), - m_byte_order(eByteOrderLittle), - m_packet_timeout(5), - m_sequence_mutex(), - m_is_running(false), - m_session_key(0u), - m_request_sequence_id(0u), - m_exception_sequence_id(0u), - m_kdp_version_version(0u), - m_kdp_version_feature(0u), - m_kdp_hostinfo_cpu_mask(0u), - m_kdp_hostinfo_cpu_type(0u), - m_kdp_hostinfo_cpu_subtype(0u) -{ -} + : Communication(comm_name), m_addr_byte_size(4), + m_byte_order(eByteOrderLittle), m_packet_timeout(5), m_sequence_mutex(), + m_is_running(false), m_session_key(0u), m_request_sequence_id(0u), + m_exception_sequence_id(0u), m_kdp_version_version(0u), + m_kdp_version_feature(0u), m_kdp_hostinfo_cpu_mask(0u), + m_kdp_hostinfo_cpu_type(0u), m_kdp_hostinfo_cpu_subtype(0u) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CommunicationKDP::~CommunicationKDP() -{ - if (IsConnected()) - { - Disconnect(); - } +CommunicationKDP::~CommunicationKDP() { + if (IsConnected()) { + Disconnect(); + } } -bool -CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet) -{ - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return SendRequestPacketNoLock (request_packet); +bool CommunicationKDP::SendRequestPacket( + const PacketStreamType &request_packet) { + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + return SendRequestPacketNoLock(request_packet); } #if 0 @@ -82,408 +68,370 @@ typedef struct { } kdp_hdr_t; #endif -void -CommunicationKDP::MakeRequestPacketHeader (CommandType request_type, - PacketStreamType &request_packet, - uint16_t request_length) -{ - request_packet.Clear(); - request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type - request_packet.PutHex8 (m_request_sequence_id++); // Sequence number - request_packet.PutHex16 (request_length); // Length of the packet including this header - request_packet.PutHex32 (m_session_key); // Session key +void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type, + PacketStreamType &request_packet, + uint16_t request_length) { + request_packet.Clear(); + request_packet.PutHex8(request_type | + ePacketTypeRequest); // Set the request type + request_packet.PutHex8(m_request_sequence_id++); // Sequence number + request_packet.PutHex16( + request_length); // Length of the packet including this header + request_packet.PutHex32(m_session_key); // Session key } -bool -CommunicationKDP::SendRequestAndGetReply (const CommandType command, - const PacketStreamType &request_packet, - DataExtractor &reply_packet) -{ - if (IsRunning()) - { - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize()); - log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return false; +bool CommunicationKDP::SendRequestAndGetReply( + const CommandType command, const PacketStreamType &request_packet, + DataExtractor &reply_packet) { + if (IsRunning()) { + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize()); + log->Printf("error: kdp running, not sending packet: %.*s", + (uint32_t)log_strm.GetSize(), log_strm.GetData()); } + return false; + } - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG - // NOTE: this only works for packets that are in native endian byte order - assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2))); + // NOTE: this only works for packets that are in native endian byte order + assert(request_packet.GetSize() == + *((uint16_t *)(request_packet.GetData() + 2))); #endif - lldb::offset_t offset = 1; - const uint32_t num_retries = 3; - for (uint32_t i=0; i<num_retries; ++i) - { - if (SendRequestPacketNoLock(request_packet)) - { - const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; - while (1) - { - if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ())) - { - offset = 0; - const uint8_t reply_command = reply_packet.GetU8 (&offset); - const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset); - if (request_sequence_id == reply_sequence_id) - { - // The sequent ID was correct, now verify we got the response we were looking for - if ((reply_command & eCommandTypeMask) == command) - { - // Success - if (command == KDP_RESUMECPUS) - m_is_running.SetValue(true, eBroadcastAlways); - return true; - } - else - { - // Failed to get the correct response, bail - reply_packet.Clear(); - return false; - } - } - else if (reply_sequence_id > request_sequence_id) - { - // Sequence ID was greater than the sequence ID of the packet we sent, something - // is really wrong... - reply_packet.Clear(); - return false; - } - else - { - // The reply sequence ID was less than our current packet's sequence ID - // so we should keep trying to get a response because this was a response - // for a previous packet that we must have retried. - } - } - else - { - // Break and retry sending the packet as we didn't get a response due to timeout - break; - } + lldb::offset_t offset = 1; + const uint32_t num_retries = 3; + for (uint32_t i = 0; i < num_retries; ++i) { + if (SendRequestPacketNoLock(request_packet)) { + const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; + while (1) { + if (WaitForPacketWithTimeoutMicroSecondsNoLock( + reply_packet, GetPacketTimeoutInMicroSeconds())) { + offset = 0; + const uint8_t reply_command = reply_packet.GetU8(&offset); + const uint8_t reply_sequence_id = reply_packet.GetU8(&offset); + if (request_sequence_id == reply_sequence_id) { + // The sequent ID was correct, now verify we got the response we + // were looking for + if ((reply_command & eCommandTypeMask) == command) { + // Success + if (command == KDP_RESUMECPUS) + m_is_running.SetValue(true, eBroadcastAlways); + return true; + } else { + // Failed to get the correct response, bail + reply_packet.Clear(); + return false; } + } else if (reply_sequence_id > request_sequence_id) { + // Sequence ID was greater than the sequence ID of the packet we + // sent, something + // is really wrong... + reply_packet.Clear(); + return false; + } else { + // The reply sequence ID was less than our current packet's sequence + // ID + // so we should keep trying to get a response because this was a + // response + // for a previous packet that we must have retried. + } + } else { + // Break and retry sending the packet as we didn't get a response due + // to timeout + break; } + } } - reply_packet.Clear(); - return false; + } + reply_packet.Clear(); + return false; } -bool -CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet) -{ - if (IsConnected()) - { - const char *packet_data = request_packet.GetData(); - const size_t packet_size = request_packet.GetSize(); - - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, packet_data, packet_size); - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - ConnectionStatus status = eConnectionStatusSuccess; - - size_t bytes_written = Write (packet_data, - packet_size, - status, - NULL); - - if (bytes_written == packet_size) - return true; - - if (log) - log->Printf ("error: failed to send packet entire packet %" PRIu64 " of %" PRIu64 " bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size); +bool CommunicationKDP::SendRequestPacketNoLock( + const PacketStreamType &request_packet) { + if (IsConnected()) { + const char *packet_data = request_packet.GetData(); + const size_t packet_size = request_packet.GetSize(); + + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, packet_data, packet_size); + log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } - return false; -} + ConnectionStatus status = eConnectionStatusSuccess; -bool -CommunicationKDP::GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock) -{ - return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex, std::try_to_lock)).owns_lock(); + size_t bytes_written = Write(packet_data, packet_size, status, NULL); + + if (bytes_written == packet_size) + return true; + + if (log) + log->Printf("error: failed to send packet entire packet %" PRIu64 + " of %" PRIu64 " bytes sent", + (uint64_t)bytes_written, (uint64_t)packet_size); + } + return false; } -bool -CommunicationKDP::WaitForNotRunningPrivate(const std::chrono::microseconds &timeout) -{ - return m_is_running.WaitForValueEqualTo(false, timeout, NULL); +bool CommunicationKDP::GetSequenceMutex( + std::unique_lock<std::recursive_mutex> &lock) { + return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex, + std::try_to_lock)) + .owns_lock(); } -size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec) -{ - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); +bool CommunicationKDP::WaitForNotRunningPrivate( + const std::chrono::microseconds &timeout) { + return m_is_running.WaitForValueEqualTo(false, timeout, NULL); } size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec) -{ - uint8_t buffer[8192]; - Error error; - - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE)); +CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds(DataExtractor &packet, + uint32_t timeout_usec) { + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + return WaitForPacketWithTimeoutMicroSecondsNoLock(packet, timeout_usec); +} - // Check for a packet from our cache first without trying any reading... - if (CheckForPacket (NULL, 0, packet)) +size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( + DataExtractor &packet, uint32_t timeout_usec) { + uint8_t buffer[8192]; + Error error; + + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS | + KDP_LOG_VERBOSE)); + + // Check for a packet from our cache first without trying any reading... + if (CheckForPacket(NULL, 0, packet)) + return packet.GetByteSize(); + + bool timed_out = false; + while (IsConnected() && !timed_out) { + lldb::ConnectionStatus status = eConnectionStatusNoConnection; + size_t bytes_read = + Read(buffer, sizeof(buffer), timeout_usec, status, &error); + + if (log) + log->Printf("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, " + "status = %s, error = %s) => bytes_read = %" PRIu64, + LLVM_PRETTY_FUNCTION, timeout_usec, + Communication::ConnectionStatusAsCString(status), + error.AsCString(), (uint64_t)bytes_read); + + if (bytes_read > 0) { + if (CheckForPacket(buffer, bytes_read, packet)) return packet.GetByteSize(); - - bool timed_out = false; - while (IsConnected() && !timed_out) - { - lldb::ConnectionStatus status = eConnectionStatusNoConnection; - size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); - - if (log) - log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, - LLVM_PRETTY_FUNCTION, - timeout_usec, - Communication::ConnectionStatusAsCString (status), - error.AsCString(), - (uint64_t)bytes_read); - - if (bytes_read > 0) - { - if (CheckForPacket (buffer, bytes_read, packet)) - return packet.GetByteSize(); - } - else - { - switch (status) - { - case eConnectionStatusInterrupted: - case eConnectionStatusTimedOut: - timed_out = true; - break; - case eConnectionStatusSuccess: - //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); - break; - - case eConnectionStatusEndOfFile: - case eConnectionStatusNoConnection: - case eConnectionStatusLostConnection: - case eConnectionStatusError: - Disconnect(); - break; - } - } + } else { + switch (status) { + case eConnectionStatusInterrupted: + case eConnectionStatusTimedOut: + timed_out = true; + break; + case eConnectionStatusSuccess: + // printf ("status = success but error = %s\n", + // error.AsCString("<invalid>")); + break; + + case eConnectionStatusEndOfFile: + case eConnectionStatusNoConnection: + case eConnectionStatusLostConnection: + case eConnectionStatusError: + Disconnect(); + break; + } } - packet.Clear (); - return 0; + } + packet.Clear(); + return 0; } -bool -CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet) -{ - // Put the packet data into the buffer in a thread safe fashion - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); +bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len, + DataExtractor &packet) { + // Put the packet data into the buffer in a thread safe fashion + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - if (src && src_len > 0) - { - if (log && log->GetVerbose()) - { - PacketStreamType log_strm; - DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); - log->Printf ("CommunicationKDP::%s adding %u bytes: %s", - __FUNCTION__, - (uint32_t)src_len, - log_strm.GetData()); - } - m_bytes.append ((const char *)src, src_len); + if (src && src_len > 0) { + if (log && log->GetVerbose()) { + PacketStreamType log_strm; + DataExtractor::DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, + LLDB_INVALID_ADDRESS); + log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, + (uint32_t)src_len, log_strm.GetData()); } - - // Make sure we at least have enough bytes for a packet header - const size_t bytes_available = m_bytes.size(); - if (bytes_available >= 8) - { - packet.SetData (&m_bytes[0], bytes_available, m_byte_order); - lldb::offset_t offset = 0; - uint8_t reply_command = packet.GetU8(&offset); - switch (reply_command) - { - case ePacketTypeRequest | KDP_EXCEPTION: - case ePacketTypeRequest | KDP_TERMINATION: - // We got an exception request, so be sure to send an ACK - { - PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - // Set the reply but and make the ACK packet - request_ack_packet.PutHex8 (reply_command | ePacketTypeReply); - request_ack_packet.PutHex8 (packet.GetU8(&offset)); - request_ack_packet.PutHex16 (packet.GetU16(&offset)); - request_ack_packet.PutHex32 (packet.GetU32(&offset)); - m_is_running.SetValue(false, eBroadcastAlways); - // Ack to the exception or termination - SendRequestPacketNoLock (request_ack_packet); - } - // Fall through to case below to get packet contents - LLVM_FALLTHROUGH; - case ePacketTypeReply | KDP_CONNECT: - case ePacketTypeReply | KDP_DISCONNECT: - case ePacketTypeReply | KDP_HOSTINFO: - case ePacketTypeReply | KDP_VERSION: - case ePacketTypeReply | KDP_MAXBYTES: - case ePacketTypeReply | KDP_READMEM: - case ePacketTypeReply | KDP_WRITEMEM: - case ePacketTypeReply | KDP_READREGS: - case ePacketTypeReply | KDP_WRITEREGS: - case ePacketTypeReply | KDP_LOAD: - case ePacketTypeReply | KDP_IMAGEPATH: - case ePacketTypeReply | KDP_SUSPEND: - case ePacketTypeReply | KDP_RESUMECPUS: - case ePacketTypeReply | KDP_BREAKPOINT_SET: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: - case ePacketTypeReply | KDP_REGIONS: - case ePacketTypeReply | KDP_REATTACH: - case ePacketTypeReply | KDP_HOSTREBOOT: - case ePacketTypeReply | KDP_READMEM64: - case ePacketTypeReply | KDP_WRITEMEM64: - case ePacketTypeReply | KDP_BREAKPOINT_SET64: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: - case ePacketTypeReply | KDP_KERNELVERSION: - case ePacketTypeReply | KDP_READPHYSMEM64: - case ePacketTypeReply | KDP_WRITEPHYSMEM64: - case ePacketTypeReply | KDP_READIOPORT: - case ePacketTypeReply | KDP_WRITEIOPORT: - case ePacketTypeReply | KDP_READMSR64: - case ePacketTypeReply | KDP_WRITEMSR64: - case ePacketTypeReply | KDP_DUMPINFO: - { - offset = 2; - const uint16_t length = packet.GetU16 (&offset); - if (length <= bytes_available) - { - // We have an entire packet ready, we need to copy the data - // bytes into a buffer that will be owned by the packet and - // erase the bytes from our communcation buffer "m_bytes" - packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length))); - m_bytes.erase (0, length); - - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, packet); - - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return true; - } - } - break; - - default: - // Unrecognized reply command byte, erase this byte and try to get back on track - if (log) - log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", - __FUNCTION__, - (uint8_t)m_bytes[0]); - m_bytes.erase(0, 1); - break; + m_bytes.append((const char *)src, src_len); + } + + // Make sure we at least have enough bytes for a packet header + const size_t bytes_available = m_bytes.size(); + if (bytes_available >= 8) { + packet.SetData(&m_bytes[0], bytes_available, m_byte_order); + lldb::offset_t offset = 0; + uint8_t reply_command = packet.GetU8(&offset); + switch (reply_command) { + case ePacketTypeRequest | KDP_EXCEPTION: + case ePacketTypeRequest | KDP_TERMINATION: + // We got an exception request, so be sure to send an ACK + { + PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + // Set the reply but and make the ACK packet + request_ack_packet.PutHex8(reply_command | ePacketTypeReply); + request_ack_packet.PutHex8(packet.GetU8(&offset)); + request_ack_packet.PutHex16(packet.GetU16(&offset)); + request_ack_packet.PutHex32(packet.GetU32(&offset)); + m_is_running.SetValue(false, eBroadcastAlways); + // Ack to the exception or termination + SendRequestPacketNoLock(request_ack_packet); + } + // Fall through to case below to get packet contents + LLVM_FALLTHROUGH; + case ePacketTypeReply | KDP_CONNECT: + case ePacketTypeReply | KDP_DISCONNECT: + case ePacketTypeReply | KDP_HOSTINFO: + case ePacketTypeReply | KDP_VERSION: + case ePacketTypeReply | KDP_MAXBYTES: + case ePacketTypeReply | KDP_READMEM: + case ePacketTypeReply | KDP_WRITEMEM: + case ePacketTypeReply | KDP_READREGS: + case ePacketTypeReply | KDP_WRITEREGS: + case ePacketTypeReply | KDP_LOAD: + case ePacketTypeReply | KDP_IMAGEPATH: + case ePacketTypeReply | KDP_SUSPEND: + case ePacketTypeReply | KDP_RESUMECPUS: + case ePacketTypeReply | KDP_BREAKPOINT_SET: + case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: + case ePacketTypeReply | KDP_REGIONS: + case ePacketTypeReply | KDP_REATTACH: + case ePacketTypeReply | KDP_HOSTREBOOT: + case ePacketTypeReply | KDP_READMEM64: + case ePacketTypeReply | KDP_WRITEMEM64: + case ePacketTypeReply | KDP_BREAKPOINT_SET64: + case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: + case ePacketTypeReply | KDP_KERNELVERSION: + case ePacketTypeReply | KDP_READPHYSMEM64: + case ePacketTypeReply | KDP_WRITEPHYSMEM64: + case ePacketTypeReply | KDP_READIOPORT: + case ePacketTypeReply | KDP_WRITEIOPORT: + case ePacketTypeReply | KDP_READMSR64: + case ePacketTypeReply | KDP_WRITEMSR64: + case ePacketTypeReply | KDP_DUMPINFO: { + offset = 2; + const uint16_t length = packet.GetU16(&offset); + if (length <= bytes_available) { + // We have an entire packet ready, we need to copy the data + // bytes into a buffer that will be owned by the packet and + // erase the bytes from our communcation buffer "m_bytes" + packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length))); + m_bytes.erase(0, length); + + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, packet); + + log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } + return true; + } + } break; + + default: + // Unrecognized reply command byte, erase this byte and try to get back on + // track + if (log) + log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", + __FUNCTION__, (uint8_t)m_bytes[0]); + m_bytes.erase(0, 1); + break; } - packet.Clear(); - return false; + } + packet.Clear(); + return false; } - -bool -CommunicationKDP::SendRequestConnect (uint16_t reply_port, - uint16_t exc_port, - const char *greeting) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - if (greeting == NULL) - greeting = ""; - - const CommandType command = KDP_CONNECT; - // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL - const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; - MakeRequestPacketHeader (command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder (eByteOrderLittle); - request_packet.PutHex16 (htons(reply_port)); - request_packet.PutHex16 (htons(exc_port)); - request_packet.SetByteOrder (m_byte_order); - request_packet.PutCString (greeting); - DataExtractor reply_packet; - return SendRequestAndGetReply (command, request_packet, reply_packet); +bool CommunicationKDP::SendRequestConnect(uint16_t reply_port, + uint16_t exc_port, + const char *greeting) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + if (greeting == NULL) + greeting = ""; + + const CommandType command = KDP_CONNECT; + // Length is 82 uint16_t and the length of the greeting C string with the + // terminating NULL + const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; + MakeRequestPacketHeader(command, request_packet, command_length); + // Always send connect ports as little endian + request_packet.SetByteOrder(eByteOrderLittle); + request_packet.PutHex16(htons(reply_port)); + request_packet.PutHex16(htons(exc_port)); + request_packet.SetByteOrder(m_byte_order); + request_packet.PutCString(greeting); + DataExtractor reply_packet; + return SendRequestAndGetReply(command, request_packet, reply_packet); } -void -CommunicationKDP::ClearKDPSettings () -{ - m_request_sequence_id = 0; - m_kdp_version_version = 0; - m_kdp_version_feature = 0; - m_kdp_hostinfo_cpu_mask = 0; - m_kdp_hostinfo_cpu_type = 0; - m_kdp_hostinfo_cpu_subtype = 0; +void CommunicationKDP::ClearKDPSettings() { + m_request_sequence_id = 0; + m_kdp_version_version = 0; + m_kdp_version_feature = 0; + m_kdp_hostinfo_cpu_mask = 0; + m_kdp_hostinfo_cpu_type = 0; + m_kdp_hostinfo_cpu_subtype = 0; } -bool -CommunicationKDP::SendRequestReattach (uint16_t reply_port) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_REATTACH; - // Length is 8 bytes for the header plus 2 bytes for the reply UDP port - const uint32_t command_length = 8 + 2; - MakeRequestPacketHeader (command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder (eByteOrderLittle); - request_packet.PutHex16(htons(reply_port)); - request_packet.SetByteOrder (m_byte_order); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - // Reset the sequence ID to zero for reattach - ClearKDPSettings (); - lldb::offset_t offset = 4; - m_session_key = reply_packet.GetU32 (&offset); - return true; - } - return false; +bool CommunicationKDP::SendRequestReattach(uint16_t reply_port) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_REATTACH; + // Length is 8 bytes for the header plus 2 bytes for the reply UDP port + const uint32_t command_length = 8 + 2; + MakeRequestPacketHeader(command, request_packet, command_length); + // Always send connect ports as little endian + request_packet.SetByteOrder(eByteOrderLittle); + request_packet.PutHex16(htons(reply_port)); + request_packet.SetByteOrder(m_byte_order); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + // Reset the sequence ID to zero for reattach + ClearKDPSettings(); + lldb::offset_t offset = 4; + m_session_key = reply_packet.GetU32(&offset); + return true; + } + return false; } -uint32_t -CommunicationKDP::GetVersion () -{ - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_version; +uint32_t CommunicationKDP::GetVersion() { + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_version; } -uint32_t -CommunicationKDP::GetFeatureFlags () -{ - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_feature; +uint32_t CommunicationKDP::GetFeatureFlags() { + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_feature; } -bool -CommunicationKDP::SendRequestVersion () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_VERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - m_kdp_version_version = reply_packet.GetU32 (&offset); - m_kdp_version_feature = reply_packet.GetU32 (&offset); - return true; - } - return false; +bool CommunicationKDP::SendRequestVersion() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_VERSION; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + m_kdp_version_version = reply_packet.GetU32(&offset); + m_kdp_version_feature = reply_packet.GetU32(&offset); + return true; + } + return false; } #if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... @@ -514,932 +462,863 @@ CommunicationKDP::SendRequestImagePath () } #endif -uint32_t -CommunicationKDP::GetCPUMask () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_mask; +uint32_t CommunicationKDP::GetCPUMask() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_mask; } -uint32_t -CommunicationKDP::GetCPUType () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_type; +uint32_t CommunicationKDP::GetCPUType() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_type; } -uint32_t -CommunicationKDP::GetCPUSubtype () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_subtype; +uint32_t CommunicationKDP::GetCPUSubtype() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_subtype; } -lldb_private::UUID -CommunicationKDP::GetUUID () -{ - UUID uuid; - if (GetKernelVersion() == NULL) - return uuid; - - if (m_kernel_version.find("UUID=") == std::string::npos) - return uuid; - - size_t p = m_kernel_version.find("UUID=") + strlen ("UUID="); - std::string uuid_str = m_kernel_version.substr(p, 36); - if (uuid_str.size() < 32) - return uuid; +lldb_private::UUID CommunicationKDP::GetUUID() { + UUID uuid; + if (GetKernelVersion() == NULL) + return uuid; - if (uuid.SetFromCString (uuid_str.c_str()) == 0) - { - UUID invalid_uuid; - return invalid_uuid; - } + if (m_kernel_version.find("UUID=") == std::string::npos) + return uuid; + size_t p = m_kernel_version.find("UUID=") + strlen("UUID="); + std::string uuid_str = m_kernel_version.substr(p, 36); + if (uuid_str.size() < 32) return uuid; -} -bool -CommunicationKDP::RemoteIsEFI () -{ - if (GetKernelVersion() == NULL) - return false; - if (strncmp (m_kernel_version.c_str(), "EFI", 3) == 0) - return true; - else - return false; -} + if (uuid.SetFromCString(uuid_str.c_str()) == 0) { + UUID invalid_uuid; + return invalid_uuid; + } -bool -CommunicationKDP::RemoteIsDarwinKernel () -{ - if (GetKernelVersion() == NULL) - return false; - if (m_kernel_version.find("Darwin Kernel") != std::string::npos) - return true; - else - return false; + return uuid; } -lldb::addr_t -CommunicationKDP::GetLoadAddress () -{ - if (GetKernelVersion() == NULL) - return LLDB_INVALID_ADDRESS; - - if (m_kernel_version.find("stext=") == std::string::npos) - return LLDB_INVALID_ADDRESS; - size_t p = m_kernel_version.find("stext=") + strlen ("stext="); - if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x') - return LLDB_INVALID_ADDRESS; - - addr_t kernel_load_address; - errno = 0; - kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16); - if (errno != 0 || kernel_load_address == 0) - return LLDB_INVALID_ADDRESS; - - return kernel_load_address; +bool CommunicationKDP::RemoteIsEFI() { + if (GetKernelVersion() == NULL) + return false; + if (strncmp(m_kernel_version.c_str(), "EFI", 3) == 0) + return true; + else + return false; } -bool -CommunicationKDP::SendRequestHostInfo () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_HOSTINFO; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset); - m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset); - m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset); - - ArchSpec kernel_arch; - kernel_arch.SetArchitecture (eArchTypeMachO, - m_kdp_hostinfo_cpu_type, - m_kdp_hostinfo_cpu_subtype); - - m_addr_byte_size = kernel_arch.GetAddressByteSize(); - m_byte_order = kernel_arch.GetByteOrder(); - return true; - } +bool CommunicationKDP::RemoteIsDarwinKernel() { + if (GetKernelVersion() == NULL) + return false; + if (m_kernel_version.find("Darwin Kernel") != std::string::npos) + return true; + else return false; } -const char * -CommunicationKDP::GetKernelVersion () -{ - if (m_kernel_version.empty()) - SendRequestKernelVersion (); - return m_kernel_version.c_str(); -} +lldb::addr_t CommunicationKDP::GetLoadAddress() { + if (GetKernelVersion() == NULL) + return LLDB_INVALID_ADDRESS; -bool -CommunicationKDP::SendRequestKernelVersion () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_KERNELVERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - const char *kernel_version_cstr = reply_packet.PeekCStr(8); - if (kernel_version_cstr && kernel_version_cstr[0]) - m_kernel_version.assign (kernel_version_cstr); - return true; - } - return false; + if (m_kernel_version.find("stext=") == std::string::npos) + return LLDB_INVALID_ADDRESS; + size_t p = m_kernel_version.find("stext=") + strlen("stext="); + if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x') + return LLDB_INVALID_ADDRESS; + + addr_t kernel_load_address; + errno = 0; + kernel_load_address = ::strtoul(m_kernel_version.c_str() + p, NULL, 16); + if (errno != 0 || kernel_load_address == 0) + return LLDB_INVALID_ADDRESS; + + return kernel_load_address; } -bool -CommunicationKDP::SendRequestDisconnect () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_DISCONNECT; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - // Are we supposed to get a reply for disconnect? - } - ClearKDPSettings (); +bool CommunicationKDP::SendRequestHostInfo() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_HOSTINFO; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + m_kdp_hostinfo_cpu_mask = reply_packet.GetU32(&offset); + m_kdp_hostinfo_cpu_type = reply_packet.GetU32(&offset); + m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32(&offset); + + ArchSpec kernel_arch; + kernel_arch.SetArchitecture(eArchTypeMachO, m_kdp_hostinfo_cpu_type, + m_kdp_hostinfo_cpu_subtype); + + m_addr_byte_size = kernel_arch.GetAddressByteSize(); + m_byte_order = kernel_arch.GetByteOrder(); return true; + } + return false; } -uint32_t -CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr, - void *dst, - uint32_t dst_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - request_packet.PutHex32 (dst_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) - { - const void *src = reply_packet.GetData(&offset, src_len); - if (src) - { - ::memcpy (dst, src, src_len); - error.Clear(); - return src_len; - } - } - if (kdp_error) - error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error); - else - error.SetErrorString ("kdp read memory failed"); - } - else - { - error.SetErrorString ("failed to send packet"); - } - return 0; +const char *CommunicationKDP::GetKernelVersion() { + if (m_kernel_version.empty()) + SendRequestKernelVersion(); + return m_kernel_version.c_str(); } +bool CommunicationKDP::SendRequestKernelVersion() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_KERNELVERSION; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + const char *kernel_version_cstr = reply_packet.PeekCStr(8); + if (kernel_version_cstr && kernel_version_cstr[0]) + m_kernel_version.assign(kernel_version_cstr); + return true; + } + return false; +} -uint32_t -CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr, - const void *src, - uint32_t src_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - request_packet.PutHex32 (src_len); - request_packet.PutRawBytes(src, src_len); +bool CommunicationKDP::SendRequestDisconnect() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_DISCONNECT; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + // Are we supposed to get a reply for disconnect? + } + ClearKDPSettings(); + return true; +} - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error) - error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error); - else - { - error.Clear(); - return src_len; - } +uint32_t CommunicationKDP::SendRequestReadMemory(lldb::addr_t addr, void *dst, + uint32_t dst_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM; + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + command_addr_byte_size + 4; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + request_packet.PutHex32(dst_len); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + uint32_t src_len = reply_packet.GetByteSize() - 12; + + if (src_len > 0) { + const void *src = reply_packet.GetData(&offset, src_len); + if (src) { + ::memcpy(dst, src, src_len); + error.Clear(); + return src_len; + } } + if (kdp_error) + error.SetErrorStringWithFormat("kdp read memory failed (error %u)", + kdp_error); else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + error.SetErrorString("kdp read memory failed"); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } -bool -CommunicationKDP::SendRawRequest (uint8_t command_byte, - const void *src, // Raw packet payload bytes - uint32_t src_len, // Raw packet payload length - DataExtractor &reply_packet, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + src_len; - const CommandType command = (CommandType)command_byte; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutRawBytes(src, src_len); - - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error && (command_byte != KDP_DUMPINFO)) - error.SetErrorStringWithFormat ("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error); - else - { - error.Clear(); - return true; - } - } - else - { - error.SetErrorString ("failed to send packet"); +uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr, + const void *src, + uint32_t src_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + request_packet.PutHex32(src_len); + request_packet.PutRawBytes(src, src_len); + + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error) + error.SetErrorStringWithFormat("kdp write memory failed (error %u)", + kdp_error); + else { + error.Clear(); + return src_len; } - return false; + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } - -const char * -CommunicationKDP::GetCommandAsCString (uint8_t command) -{ - switch (command) - { - case KDP_CONNECT: return "KDP_CONNECT"; - case KDP_DISCONNECT: return "KDP_DISCONNECT"; - case KDP_HOSTINFO: return "KDP_HOSTINFO"; - case KDP_VERSION: return "KDP_VERSION"; - case KDP_MAXBYTES: return "KDP_MAXBYTES"; - case KDP_READMEM: return "KDP_READMEM"; - case KDP_WRITEMEM: return "KDP_WRITEMEM"; - case KDP_READREGS: return "KDP_READREGS"; - case KDP_WRITEREGS: return "KDP_WRITEREGS"; - case KDP_LOAD: return "KDP_LOAD"; - case KDP_IMAGEPATH: return "KDP_IMAGEPATH"; - case KDP_SUSPEND: return "KDP_SUSPEND"; - case KDP_RESUMECPUS: return "KDP_RESUMECPUS"; - case KDP_EXCEPTION: return "KDP_EXCEPTION"; - case KDP_TERMINATION: return "KDP_TERMINATION"; - case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET"; - case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE"; - case KDP_REGIONS: return "KDP_REGIONS"; - case KDP_REATTACH: return "KDP_REATTACH"; - case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT"; - case KDP_READMEM64: return "KDP_READMEM64"; - case KDP_WRITEMEM64: return "KDP_WRITEMEM64"; - case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET"; - case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE"; - case KDP_KERNELVERSION: return "KDP_KERNELVERSION"; - case KDP_READPHYSMEM64: return "KDP_READPHYSMEM64"; - case KDP_WRITEPHYSMEM64: return "KDP_WRITEPHYSMEM64"; - case KDP_READIOPORT: return "KDP_READIOPORT"; - case KDP_WRITEIOPORT: return "KDP_WRITEIOPORT"; - case KDP_READMSR64: return "KDP_READMSR64"; - case KDP_WRITEMSR64: return "KDP_WRITEMSR64"; - case KDP_DUMPINFO: return "KDP_DUMPINFO"; +bool CommunicationKDP::SendRawRequest( + uint8_t command_byte, + const void *src, // Raw packet payload bytes + uint32_t src_len, // Raw packet payload length + DataExtractor &reply_packet, Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + src_len; + const CommandType command = (CommandType)command_byte; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutRawBytes(src, src_len); + + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error && (command_byte != KDP_DUMPINFO)) + error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)", + command_byte, kdp_error); + else { + error.Clear(); + return true; } - return NULL; + } else { + error.SetErrorString("failed to send packet"); + } + return false; } -void -CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len) -{ - DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size); - DumpPacket (s, extractor); +const char *CommunicationKDP::GetCommandAsCString(uint8_t command) { + switch (command) { + case KDP_CONNECT: + return "KDP_CONNECT"; + case KDP_DISCONNECT: + return "KDP_DISCONNECT"; + case KDP_HOSTINFO: + return "KDP_HOSTINFO"; + case KDP_VERSION: + return "KDP_VERSION"; + case KDP_MAXBYTES: + return "KDP_MAXBYTES"; + case KDP_READMEM: + return "KDP_READMEM"; + case KDP_WRITEMEM: + return "KDP_WRITEMEM"; + case KDP_READREGS: + return "KDP_READREGS"; + case KDP_WRITEREGS: + return "KDP_WRITEREGS"; + case KDP_LOAD: + return "KDP_LOAD"; + case KDP_IMAGEPATH: + return "KDP_IMAGEPATH"; + case KDP_SUSPEND: + return "KDP_SUSPEND"; + case KDP_RESUMECPUS: + return "KDP_RESUMECPUS"; + case KDP_EXCEPTION: + return "KDP_EXCEPTION"; + case KDP_TERMINATION: + return "KDP_TERMINATION"; + case KDP_BREAKPOINT_SET: + return "KDP_BREAKPOINT_SET"; + case KDP_BREAKPOINT_REMOVE: + return "KDP_BREAKPOINT_REMOVE"; + case KDP_REGIONS: + return "KDP_REGIONS"; + case KDP_REATTACH: + return "KDP_REATTACH"; + case KDP_HOSTREBOOT: + return "KDP_HOSTREBOOT"; + case KDP_READMEM64: + return "KDP_READMEM64"; + case KDP_WRITEMEM64: + return "KDP_WRITEMEM64"; + case KDP_BREAKPOINT_SET64: + return "KDP_BREAKPOINT64_SET"; + case KDP_BREAKPOINT_REMOVE64: + return "KDP_BREAKPOINT64_REMOVE"; + case KDP_KERNELVERSION: + return "KDP_KERNELVERSION"; + case KDP_READPHYSMEM64: + return "KDP_READPHYSMEM64"; + case KDP_WRITEPHYSMEM64: + return "KDP_WRITEPHYSMEM64"; + case KDP_READIOPORT: + return "KDP_READIOPORT"; + case KDP_WRITEIOPORT: + return "KDP_WRITEIOPORT"; + case KDP_READMSR64: + return "KDP_READMSR64"; + case KDP_WRITEMSR64: + return "KDP_WRITEMSR64"; + case KDP_DUMPINFO: + return "KDP_DUMPINFO"; + } + return NULL; } -void -CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet) -{ - const char *error_desc = NULL; - if (packet.GetByteSize() < 8) - { - error_desc = "error: invalid packet (too short): "; - } - else - { - lldb::offset_t offset = 0; - const uint8_t first_packet_byte = packet.GetU8 (&offset); - const uint8_t sequence_id = packet.GetU8 (&offset); - const uint16_t length = packet.GetU16 (&offset); - const uint32_t key = packet.GetU32 (&offset); - const CommandType command = ExtractCommand (first_packet_byte); - const char *command_name = GetCommandAsCString (command); - if (command_name) - { - const bool is_reply = ExtractIsReply(first_packet_byte); - s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", - IsRunning(), - is_reply ? "<--" : "-->", - command_name, - first_packet_byte, - sequence_id, - length, - key); - - if (is_reply) - { - // Dump request reply packets - switch (command) - { - // Commands that return a single 32 bit error - case KDP_CONNECT: - case KDP_WRITEMEM: - case KDP_WRITEMEM64: - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: - case KDP_WRITEREGS: - case KDP_LOAD: - case KDP_WRITEIOPORT: - case KDP_WRITEMSR64: - { - const uint32_t error = packet.GetU32 (&offset); - s.Printf(" (error=0x%8.8x)", error); - } - break; - - case KDP_DISCONNECT: - case KDP_REATTACH: - case KDP_HOSTREBOOT: - case KDP_SUSPEND: - case KDP_RESUMECPUS: - case KDP_EXCEPTION: - case KDP_TERMINATION: - // No return value for the reply, just the header to ack - s.PutCString(" ()"); - break; - - case KDP_HOSTINFO: - { - const uint32_t cpu_mask = packet.GetU32 (&offset); - const uint32_t cpu_type = packet.GetU32 (&offset); - const uint32_t cpu_subtype = packet.GetU32 (&offset); - s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype); - } - break; - - case KDP_VERSION: - { - const uint32_t version = packet.GetU32 (&offset); - const uint32_t feature = packet.GetU32 (&offset); - s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); - } - break; - - case KDP_REGIONS: - { - const uint32_t region_count = packet.GetU32 (&offset); - s.Printf(" (count = %u", region_count); - for (uint32_t i=0; i<region_count; ++i) - { - const addr_t region_addr = packet.GetPointer (&offset); - const uint32_t region_size = packet.GetU32 (&offset); - const uint32_t region_prot = packet.GetU32 (&offset); - s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot)); - } - } - break; - - case KDP_READMEM: - case KDP_READMEM64: - case KDP_READPHYSMEM64: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatBytesWithASCII, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - m_last_read_memory_addr, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_READREGS: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x regs:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - count / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_KERNELVERSION: - { - const char *kernel_version = packet.PeekCStr(8); - s.Printf(" (version = \"%s\")", kernel_version); - } - break; - - case KDP_MAXBYTES: - { - const uint32_t max_bytes = packet.GetU32 (&offset); - s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); - } - break; - case KDP_IMAGEPATH: - { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } - break; - - case KDP_READIOPORT: - case KDP_READMSR64: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x io:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - case KDP_DUMPINFO: - { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - - } - break; - - default: - s.Printf(" (add support for dumping this packet reply!!!"); - break; - - } - } - else - { - // Dump request packets - switch (command) - { - case KDP_CONNECT: - { - const uint16_t reply_port = ntohs(packet.GetU16 (&offset)); - const uint16_t exc_port = ntohs(packet.GetU16 (&offset)); - s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset)); - } - break; - - case KDP_DISCONNECT: - case KDP_HOSTREBOOT: - case KDP_HOSTINFO: - case KDP_VERSION: - case KDP_REGIONS: - case KDP_KERNELVERSION: - case KDP_MAXBYTES: - case KDP_IMAGEPATH: - case KDP_SUSPEND: - // No args, just the header in the request... - s.PutCString(" ()"); - break; - - case KDP_RESUMECPUS: - { - const uint32_t cpu_mask = packet.GetU32 (&offset); - s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); - } - break; - - case KDP_READMEM: - { - const uint32_t addr = packet.GetU32 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); - m_last_read_memory_addr = addr; - } - break; - - case KDP_WRITEMEM: - { - const uint32_t addr = packet.GetU32 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_READMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); - m_last_read_memory_addr = addr; - } - break; - - case KDP_READPHYSMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - const uint32_t lcpu = packet.GetU16 (&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu); - m_last_read_memory_addr = addr; - } - break; - - case KDP_WRITEMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_WRITEPHYSMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - const uint32_t lcpu = packet.GetU16 (&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_READREGS: - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t flavor = packet.GetU32 (&offset); - s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); - } - break; - - case KDP_WRITEREGS: - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t flavor = packet.GetU32 (&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - nbytes / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: - { - const uint32_t addr = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x)", addr); - } - break; - - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: - { - const uint64_t addr = packet.GetU64 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); - } - break; - - - case KDP_LOAD: - { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } - break; - - case KDP_EXCEPTION: - { - const uint32_t count = packet.GetU32 (&offset); - - for (uint32_t i=0; i<count; ++i) - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t exc = packet.GetU32 (&offset); - const uint32_t code = packet.GetU32 (&offset); - const uint32_t subcode = packet.GetU32 (&offset); - const char *exc_cstr = NULL; - switch (exc) - { - case 1: exc_cstr = "EXC_BAD_ACCESS"; break; - case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break; - case 3: exc_cstr = "EXC_ARITHMETIC"; break; - case 4: exc_cstr = "EXC_EMULATION"; break; - case 5: exc_cstr = "EXC_SOFTWARE"; break; - case 6: exc_cstr = "EXC_BREAKPOINT"; break; - case 7: exc_cstr = "EXC_SYSCALL"; break; - case 8: exc_cstr = "EXC_MACH_SYSCALL"; break; - case 9: exc_cstr = "EXC_RPC_ALERT"; break; - case 10: exc_cstr = "EXC_CRASH"; break; - default: - break; - } - - s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ", - cpu, exc_cstr, exc, code, code, subcode, subcode); - } - } - break; - - case KDP_TERMINATION: - { - const uint32_t term_code = packet.GetU32 (&offset); - const uint32_t exit_code = packet.GetU32 (&offset); - s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code); - } - break; - - case KDP_REATTACH: - { - const uint16_t reply_port = ntohs(packet.GetU16 (&offset)); - s.Printf(" (reply_port = %u)", reply_port); - } - break; - - case KDP_READMSR64: - { - const uint32_t address = packet.GetU32 (&offset); - const uint16_t lcpu = packet.GetU16 (&offset); - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); - } - break; - - case KDP_WRITEMSR64: - { - const uint32_t address = packet.GetU32 (&offset); - const uint16_t lcpu = packet.GetU16 (&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_READIOPORT: - { - const uint16_t lcpu = packet.GetU16 (&offset); - const uint16_t address = packet.GetU16 (&offset); - const uint16_t nbytes = packet.GetU16 (&offset); - s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes); - } - break; - - case KDP_WRITEIOPORT: - { - const uint16_t lcpu = packet.GetU16 (&offset); - const uint16_t address = packet.GetU16 (&offset); - const uint16_t nbytes = packet.GetU16 (&offset); - s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_DUMPINFO: - { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - - } - break; - - } - } - } - else - { - error_desc = "error: invalid packet command: "; - } - } - - if (error_desc) - { - s.PutCString (error_desc); - - packet.Dump (&s, // Stream to dump to - 0, // Offset into "packet" - eFormatBytes, // Dump as hex bytes - 1, // Size of each item is 1 for single bytes - packet.GetByteSize(), // Number of bytes - UINT32_MAX, // Num bytes per line - LLDB_INVALID_ADDRESS, // Base address - 0, 0); // Bitfield info set to not do anything bitfield related - } +void CommunicationKDP::DumpPacket(Stream &s, const void *data, + uint32_t data_len) { + DataExtractor extractor(data, data_len, m_byte_order, m_addr_byte_size); + DumpPacket(s, extractor); } -uint32_t -CommunicationKDP::SendRequestReadRegisters (uint32_t cpu, - uint32_t flavor, - void *dst, - uint32_t dst_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_READREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32 (cpu); - request_packet.PutHex32 (flavor); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) - { - const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); - const void *src = reply_packet.GetData(&offset, bytes_to_copy); - if (src) - { - ::memcpy (dst, src, bytes_to_copy); - error.Clear(); - // Return the number of bytes we could have returned regardless if - // we copied them or not, just so we know when things don't match up - return src_len; +void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { + const char *error_desc = NULL; + if (packet.GetByteSize() < 8) { + error_desc = "error: invalid packet (too short): "; + } else { + lldb::offset_t offset = 0; + const uint8_t first_packet_byte = packet.GetU8(&offset); + const uint8_t sequence_id = packet.GetU8(&offset); + const uint16_t length = packet.GetU16(&offset); + const uint32_t key = packet.GetU32(&offset); + const CommandType command = ExtractCommand(first_packet_byte); + const char *command_name = GetCommandAsCString(command); + if (command_name) { + const bool is_reply = ExtractIsReply(first_packet_byte); + s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", + IsRunning(), is_reply ? "<--" : "-->", command_name, + first_packet_byte, sequence_id, length, key); + + if (is_reply) { + // Dump request reply packets + switch (command) { + // Commands that return a single 32 bit error + case KDP_CONNECT: + case KDP_WRITEMEM: + case KDP_WRITEMEM64: + case KDP_BREAKPOINT_SET: + case KDP_BREAKPOINT_REMOVE: + case KDP_BREAKPOINT_SET64: + case KDP_BREAKPOINT_REMOVE64: + case KDP_WRITEREGS: + case KDP_LOAD: + case KDP_WRITEIOPORT: + case KDP_WRITEMSR64: { + const uint32_t error = packet.GetU32(&offset); + s.Printf(" (error=0x%8.8x)", error); + } break; + + case KDP_DISCONNECT: + case KDP_REATTACH: + case KDP_HOSTREBOOT: + case KDP_SUSPEND: + case KDP_RESUMECPUS: + case KDP_EXCEPTION: + case KDP_TERMINATION: + // No return value for the reply, just the header to ack + s.PutCString(" ()"); + break; + + case KDP_HOSTINFO: { + const uint32_t cpu_mask = packet.GetU32(&offset); + const uint32_t cpu_type = packet.GetU32(&offset); + const uint32_t cpu_subtype = packet.GetU32(&offset); + s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", + cpu_mask, cpu_type, cpu_subtype); + } break; + + case KDP_VERSION: { + const uint32_t version = packet.GetU32(&offset); + const uint32_t feature = packet.GetU32(&offset); + s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); + } break; + + case KDP_REGIONS: { + const uint32_t region_count = packet.GetU32(&offset); + s.Printf(" (count = %u", region_count); + for (uint32_t i = 0; i < region_count; ++i) { + const addr_t region_addr = packet.GetPointer(&offset); + const uint32_t region_size = packet.GetU32(&offset); + const uint32_t region_prot = packet.GetU32(&offset); + s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 + " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", + region_addr, region_addr, region_addr + region_size, + region_size, GetPermissionsAsCString(region_prot)); + } + } break; + + case KDP_READMEM: + case KDP_READMEM64: + case KDP_READPHYSMEM64: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x:\n", error); + if (count > 0) + packet.Dump(&s, // Stream to dump to + offset, // Offset within "packet" + eFormatBytesWithASCII, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + m_last_read_memory_addr, // Don't show addresses before + // each line + 0, 0); // No bitfields + } break; + + case KDP_READREGS: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x regs:\n", error); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item in bytes + count / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_KERNELVERSION: { + const char *kernel_version = packet.PeekCStr(8); + s.Printf(" (version = \"%s\")", kernel_version); + } break; + + case KDP_MAXBYTES: { + const uint32_t max_bytes = packet.GetU32(&offset); + s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); + } break; + case KDP_IMAGEPATH: { + const char *path = packet.GetCStr(&offset); + s.Printf(" (path = \"%s\")", path); + } break; + + case KDP_READIOPORT: + case KDP_READMSR64: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x io:\n", error); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + case KDP_DUMPINFO: { + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (count = %u, bytes = \n", count); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + + } break; + + default: + s.Printf(" (add support for dumping this packet reply!!!"); + break; + } + } else { + // Dump request packets + switch (command) { + case KDP_CONNECT: { + const uint16_t reply_port = ntohs(packet.GetU16(&offset)); + const uint16_t exc_port = ntohs(packet.GetU16(&offset)); + s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", + reply_port, exc_port, packet.GetCStr(&offset)); + } break; + + case KDP_DISCONNECT: + case KDP_HOSTREBOOT: + case KDP_HOSTINFO: + case KDP_VERSION: + case KDP_REGIONS: + case KDP_KERNELVERSION: + case KDP_MAXBYTES: + case KDP_IMAGEPATH: + case KDP_SUSPEND: + // No args, just the header in the request... + s.PutCString(" ()"); + break; + + case KDP_RESUMECPUS: { + const uint32_t cpu_mask = packet.GetU32(&offset); + s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); + } break; + + case KDP_READMEM: { + const uint32_t addr = packet.GetU32(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); + m_last_read_memory_addr = addr; + } break; + + case KDP_WRITEMEM: { + const uint32_t addr = packet.GetU32(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_READMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); + m_last_read_memory_addr = addr; + } break; + + case KDP_READPHYSMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + const uint32_t lcpu = packet.GetU16(&offset); + s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, + lcpu); + m_last_read_memory_addr = addr; + } break; + + case KDP_WRITEMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, + size); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_WRITEPHYSMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + const uint32_t lcpu = packet.GetU16(&offset); + s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", + addr, size, lcpu); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_READREGS: { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t flavor = packet.GetU32(&offset); + s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); + } break; + + case KDP_WRITEREGS: { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t flavor = packet.GetU32(&offset); + const uint32_t nbytes = packet.GetByteSize() - offset; + s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item in bytes + nbytes / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_BREAKPOINT_SET: + case KDP_BREAKPOINT_REMOVE: { + const uint32_t addr = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x)", addr); + } break; + + case KDP_BREAKPOINT_SET64: + case KDP_BREAKPOINT_REMOVE64: { + const uint64_t addr = packet.GetU64(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); + } break; + + case KDP_LOAD: { + const char *path = packet.GetCStr(&offset); + s.Printf(" (path = \"%s\")", path); + } break; + + case KDP_EXCEPTION: { + const uint32_t count = packet.GetU32(&offset); + + for (uint32_t i = 0; i < count; ++i) { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t exc = packet.GetU32(&offset); + const uint32_t code = packet.GetU32(&offset); + const uint32_t subcode = packet.GetU32(&offset); + const char *exc_cstr = NULL; + switch (exc) { + case 1: + exc_cstr = "EXC_BAD_ACCESS"; + break; + case 2: + exc_cstr = "EXC_BAD_INSTRUCTION"; + break; + case 3: + exc_cstr = "EXC_ARITHMETIC"; + break; + case 4: + exc_cstr = "EXC_EMULATION"; + break; + case 5: + exc_cstr = "EXC_SOFTWARE"; + break; + case 6: + exc_cstr = "EXC_BREAKPOINT"; + break; + case 7: + exc_cstr = "EXC_SYSCALL"; + break; + case 8: + exc_cstr = "EXC_MACH_SYSCALL"; + break; + case 9: + exc_cstr = "EXC_RPC_ALERT"; + break; + case 10: + exc_cstr = "EXC_CRASH"; + break; + default: + break; } + + s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), " + "subcode = %u (0x%8.8x)} ", + cpu, exc_cstr, exc, code, code, subcode, subcode); + } + } break; + + case KDP_TERMINATION: { + const uint32_t term_code = packet.GetU32(&offset); + const uint32_t exit_code = packet.GetU32(&offset); + s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", + term_code, term_code, exit_code, exit_code); + } break; + + case KDP_REATTACH: { + const uint16_t reply_port = ntohs(packet.GetU16(&offset)); + s.Printf(" (reply_port = %u)", reply_port); + } break; + + case KDP_READMSR64: { + const uint32_t address = packet.GetU32(&offset); + const uint16_t lcpu = packet.GetU16(&offset); + s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); + } break; + + case KDP_WRITEMSR64: { + const uint32_t address = packet.GetU32(&offset); + const uint16_t lcpu = packet.GetU16(&offset); + const uint32_t nbytes = packet.GetByteSize() - offset; + s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, + address, nbytes); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_READIOPORT: { + const uint16_t lcpu = packet.GetU16(&offset); + const uint16_t address = packet.GetU16(&offset); + const uint16_t nbytes = packet.GetU16(&offset); + s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, + nbytes); + } break; + + case KDP_WRITEIOPORT: { + const uint16_t lcpu = packet.GetU16(&offset); + const uint16_t address = packet.GetU16(&offset); + const uint16_t nbytes = packet.GetU16(&offset); + s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, + address, nbytes); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_DUMPINFO: { + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (count = %u, bytes = \n", count); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + + } break; } - if (kdp_error) - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error); - else - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor); + } + } else { + error_desc = "error: invalid packet command: "; } - else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + } + + if (error_desc) { + s.PutCString(error_desc); + + packet.Dump(&s, // Stream to dump to + 0, // Offset into "packet" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for single bytes + packet.GetByteSize(), // Number of bytes + UINT32_MAX, // Num bytes per line + LLDB_INVALID_ADDRESS, // Base address + 0, 0); // Bitfield info set to not do anything bitfield related + } } -uint32_t -CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu, - uint32_t flavor, - const void *src, - uint32_t src_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_WRITEREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4 + src_len; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32 (cpu); - request_packet.PutHex32 (flavor); - request_packet.Write(src, src_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error == 0) - return src_len; - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error); +uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu, + uint32_t flavor, void *dst, + uint32_t dst_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_READREGS; + // Size is header + 4 byte cpu and 4 byte flavor + const uint32_t command_length = 8 + 4 + 4; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(cpu); + request_packet.PutHex32(flavor); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + uint32_t src_len = reply_packet.GetByteSize() - 12; + + if (src_len > 0) { + const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); + const void *src = reply_packet.GetData(&offset, bytes_to_copy); + if (src) { + ::memcpy(dst, src, bytes_to_copy); + error.Clear(); + // Return the number of bytes we could have returned regardless if + // we copied them or not, just so we know when things don't match up + return src_len; + } } + if (kdp_error) + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, + flavor, kdp_error); else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u", cpu, flavor); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } - -bool -CommunicationKDP::SendRequestResume () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_RESUMECPUS; - const uint32_t command_length = 12; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32(GetCPUMask()); - - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - return true; - return false; +uint32_t CommunicationKDP::SendRequestWriteRegisters(uint32_t cpu, + uint32_t flavor, + const void *src, + uint32_t src_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_WRITEREGS; + // Size is header + 4 byte cpu and 4 byte flavor + const uint32_t command_length = 8 + 4 + 4 + src_len; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(cpu); + request_packet.PutHex32(flavor); + request_packet.Write(src, src_len); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error == 0) + return src_len; + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, + flavor, kdp_error); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } -bool -CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ): - (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE); +bool CommunicationKDP::SendRequestResume() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_RESUMECPUS; + const uint32_t command_length = 12; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(GetCPUMask()); - const uint32_t command_length = 8 + command_addr_byte_size; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error == 0) - return true; - } - return false; + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) + return true; + return false; } -bool -CommunicationKDP::SendRequestSuspend () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_SUSPEND; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - return true; - return false; +bool CommunicationKDP::SendRequestBreakpoint(bool set, addr_t addr) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = + set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET) + : (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE); + + const uint32_t command_length = 8 + command_addr_byte_size; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error == 0) + return true; + } + return false; } +bool CommunicationKDP::SendRequestSuspend() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_SUSPEND; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) + return true; + return false; +} diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h index fe77cbb9ae4..6e02cb22d51 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h @@ -18,330 +18,248 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" #include "lldb/Core/StreamBuffer.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" +#include "lldb/lldb-private.h" -class CommunicationKDP : public lldb_private::Communication -{ +class CommunicationKDP : public lldb_private::Communication { public: - enum - { - eBroadcastBitRunPacketSent = kLoUserBroadcastBit - }; - - const static uint32_t kMaxPacketSize = 1200; - const static uint32_t kMaxDataSize = 1024; - typedef lldb_private::StreamBuffer<1024> PacketStreamType; - typedef enum - { - KDP_CONNECT = 0u, - KDP_DISCONNECT, - KDP_HOSTINFO, - KDP_VERSION, - KDP_MAXBYTES, - KDP_READMEM, - KDP_WRITEMEM, - KDP_READREGS, - KDP_WRITEREGS, - KDP_LOAD, - KDP_IMAGEPATH, - KDP_SUSPEND, - KDP_RESUMECPUS, - KDP_EXCEPTION, - KDP_TERMINATION, - KDP_BREAKPOINT_SET, - KDP_BREAKPOINT_REMOVE, - KDP_REGIONS, - KDP_REATTACH, - KDP_HOSTREBOOT, - KDP_READMEM64, - KDP_WRITEMEM64, - KDP_BREAKPOINT_SET64, - KDP_BREAKPOINT_REMOVE64, - KDP_KERNELVERSION, - KDP_READPHYSMEM64, - KDP_WRITEPHYSMEM64, - KDP_READIOPORT, - KDP_WRITEIOPORT, - KDP_READMSR64, - KDP_WRITEMSR64, - KDP_DUMPINFO - } CommandType; - - enum - { - KDP_FEATURE_BP = (1u << 0) - }; - - typedef enum - { - KDP_PROTERR_SUCCESS = 0, - KDP_PROTERR_ALREADY_CONNECTED, - KDP_PROTERR_BAD_NBYTES, - KDP_PROTERR_BADFLAVOR - } KDPError; - - typedef enum - { - ePacketTypeRequest = 0x00u, - ePacketTypeReply = 0x80u, - ePacketTypeMask = 0x80u, - eCommandTypeMask = 0x7fu - } PacketType; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommunicationKDP (const char *comm_name); - - virtual - ~CommunicationKDP(); - - bool - SendRequestPacket (const PacketStreamType &request_packet); - - // Wait for a packet within 'nsec' seconds - size_t - WaitForPacketWithTimeoutMicroSeconds (lldb_private::DataExtractor &response, - uint32_t usec); - - bool - GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock); - - bool - CheckForPacket (const uint8_t *src, - size_t src_len, - lldb_private::DataExtractor &packet); - bool - IsRunning() const - { - return m_is_running.GetValue(); - } - - //------------------------------------------------------------------ - // Set the global packet timeout. - // - // For clients, this is the timeout that gets used when sending - // packets and waiting for responses. For servers, this might not - // get used, and if it doesn't this should be moved to the - // CommunicationKDPClient. - //------------------------------------------------------------------ - uint32_t - SetPacketTimeout (uint32_t packet_timeout) - { - const uint32_t old_packet_timeout = m_packet_timeout; - m_packet_timeout = packet_timeout; - return old_packet_timeout; - } - - uint32_t - GetPacketTimeoutInMicroSeconds () const - { - return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec; - } - - //------------------------------------------------------------------ - // Public Request Packets - //------------------------------------------------------------------ - bool - SendRequestConnect (uint16_t reply_port, - uint16_t exc_port, - const char *greeting); - - bool - SendRequestReattach (uint16_t reply_port); - - bool - SendRequestDisconnect (); - - uint32_t - SendRequestReadMemory (lldb::addr_t addr, - void *dst, - uint32_t dst_size, - lldb_private::Error &error); - - uint32_t - SendRequestWriteMemory (lldb::addr_t addr, - const void *src, - uint32_t src_len, - lldb_private::Error &error); - - bool - SendRawRequest (uint8_t command_byte, - const void *src, - uint32_t src_len, - lldb_private::DataExtractor &reply, - lldb_private::Error &error); - - uint32_t - SendRequestReadRegisters (uint32_t cpu, - uint32_t flavor, - void *dst, - uint32_t dst_size, - lldb_private::Error &error); - - uint32_t - SendRequestWriteRegisters (uint32_t cpu, - uint32_t flavor, - const void *src, - uint32_t src_size, - lldb_private::Error &error); - - const char * - GetKernelVersion (); - - // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... - // const char * - // GetImagePath (); - - uint32_t - GetVersion (); - - uint32_t - GetFeatureFlags (); - - bool - LocalBreakpointsAreSupported () - { - return (GetFeatureFlags() & KDP_FEATURE_BP) != 0; - } - - uint32_t - GetCPUMask (); - - uint32_t - GetCPUType (); - - uint32_t - GetCPUSubtype (); - - lldb_private::UUID - GetUUID (); - - bool - RemoteIsEFI (); - - bool - RemoteIsDarwinKernel (); - - lldb::addr_t - GetLoadAddress (); - - bool - SendRequestResume (); - - bool - SendRequestSuspend (); - - bool - SendRequestBreakpoint (bool set, lldb::addr_t addr); + enum { eBroadcastBitRunPacketSent = kLoUserBroadcastBit }; + + const static uint32_t kMaxPacketSize = 1200; + const static uint32_t kMaxDataSize = 1024; + typedef lldb_private::StreamBuffer<1024> PacketStreamType; + typedef enum { + KDP_CONNECT = 0u, + KDP_DISCONNECT, + KDP_HOSTINFO, + KDP_VERSION, + KDP_MAXBYTES, + KDP_READMEM, + KDP_WRITEMEM, + KDP_READREGS, + KDP_WRITEREGS, + KDP_LOAD, + KDP_IMAGEPATH, + KDP_SUSPEND, + KDP_RESUMECPUS, + KDP_EXCEPTION, + KDP_TERMINATION, + KDP_BREAKPOINT_SET, + KDP_BREAKPOINT_REMOVE, + KDP_REGIONS, + KDP_REATTACH, + KDP_HOSTREBOOT, + KDP_READMEM64, + KDP_WRITEMEM64, + KDP_BREAKPOINT_SET64, + KDP_BREAKPOINT_REMOVE64, + KDP_KERNELVERSION, + KDP_READPHYSMEM64, + KDP_WRITEPHYSMEM64, + KDP_READIOPORT, + KDP_WRITEIOPORT, + KDP_READMSR64, + KDP_WRITEMSR64, + KDP_DUMPINFO + } CommandType; + + enum { KDP_FEATURE_BP = (1u << 0) }; + + typedef enum { + KDP_PROTERR_SUCCESS = 0, + KDP_PROTERR_ALREADY_CONNECTED, + KDP_PROTERR_BAD_NBYTES, + KDP_PROTERR_BADFLAVOR + } KDPError; + + typedef enum { + ePacketTypeRequest = 0x00u, + ePacketTypeReply = 0x80u, + ePacketTypeMask = 0x80u, + eCommandTypeMask = 0x7fu + } PacketType; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommunicationKDP(const char *comm_name); + + virtual ~CommunicationKDP(); + + bool SendRequestPacket(const PacketStreamType &request_packet); + + // Wait for a packet within 'nsec' seconds + size_t + WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response, + uint32_t usec); + + bool GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock); + + bool CheckForPacket(const uint8_t *src, size_t src_len, + lldb_private::DataExtractor &packet); + bool IsRunning() const { return m_is_running.GetValue(); } + + //------------------------------------------------------------------ + // Set the global packet timeout. + // + // For clients, this is the timeout that gets used when sending + // packets and waiting for responses. For servers, this might not + // get used, and if it doesn't this should be moved to the + // CommunicationKDPClient. + //------------------------------------------------------------------ + uint32_t SetPacketTimeout(uint32_t packet_timeout) { + const uint32_t old_packet_timeout = m_packet_timeout; + m_packet_timeout = packet_timeout; + return old_packet_timeout; + } + + uint32_t GetPacketTimeoutInMicroSeconds() const { + return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec; + } + + //------------------------------------------------------------------ + // Public Request Packets + //------------------------------------------------------------------ + bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port, + const char *greeting); + + bool SendRequestReattach(uint16_t reply_port); + + bool SendRequestDisconnect(); + + uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst, + uint32_t dst_size, lldb_private::Error &error); + + uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src, + uint32_t src_len, lldb_private::Error &error); + + bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len, + lldb_private::DataExtractor &reply, + lldb_private::Error &error); + + uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst, + uint32_t dst_size, + lldb_private::Error &error); -protected: + uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor, + const void *src, uint32_t src_size, + lldb_private::Error &error); + + const char *GetKernelVersion(); + + // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... + // const char * + // GetImagePath (); + + uint32_t GetVersion(); + + uint32_t GetFeatureFlags(); + + bool LocalBreakpointsAreSupported() { + return (GetFeatureFlags() & KDP_FEATURE_BP) != 0; + } + + uint32_t GetCPUMask(); + + uint32_t GetCPUType(); - bool - SendRequestPacketNoLock (const PacketStreamType &request_packet); - - size_t - WaitForPacketWithTimeoutMicroSecondsNoLock (lldb_private::DataExtractor &response, - uint32_t timeout_usec); - - bool - WaitForNotRunningPrivate(const std::chrono::microseconds &timeout); - - void - MakeRequestPacketHeader (CommandType request_type, - PacketStreamType &request_packet, - uint16_t request_length); - - //------------------------------------------------------------------ - // Protected Request Packets (use public accessors which will cache - // results. - //------------------------------------------------------------------ - bool - SendRequestVersion (); - - bool - SendRequestHostInfo (); - - bool - SendRequestKernelVersion (); - - // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... - //bool - //SendRequestImagePath (); - - void - DumpPacket (lldb_private::Stream &s, - const void *data, - uint32_t data_len); - - void - DumpPacket (lldb_private::Stream &s, - const lldb_private::DataExtractor& extractor); - - bool - VersionIsValid() const - { - return m_kdp_version_version != 0; - } - - bool - HostInfoIsValid() const - { - return m_kdp_hostinfo_cpu_type != 0; - } - - bool - ExtractIsReply (uint8_t first_packet_byte) const - { - // TODO: handle big endian... - return (first_packet_byte & ePacketTypeMask) != 0; - } - - CommandType - ExtractCommand (uint8_t first_packet_byte) const - { - // TODO: handle big endian... - return (CommandType)(first_packet_byte & eCommandTypeMask); - } - - static const char * - GetCommandAsCString (uint8_t command); - - void - ClearKDPSettings (); - - bool - SendRequestAndGetReply (const CommandType command, - const PacketStreamType &request_packet, - lldb_private::DataExtractor &reply_packet); - //------------------------------------------------------------------ - // Classes that inherit from CommunicationKDP can see and modify these - //------------------------------------------------------------------ - uint32_t m_addr_byte_size; - lldb::ByteOrder m_byte_order; - uint32_t m_packet_timeout; - std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time - lldb_private::Predicate<bool> m_is_running; - uint32_t m_session_key; - uint8_t m_request_sequence_id; - uint8_t m_exception_sequence_id; - uint32_t m_kdp_version_version; - uint32_t m_kdp_version_feature; - uint32_t m_kdp_hostinfo_cpu_mask; - uint32_t m_kdp_hostinfo_cpu_type; - uint32_t m_kdp_hostinfo_cpu_subtype; - std::string m_kernel_version; - //std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... - lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging + uint32_t GetCPUSubtype(); + + lldb_private::UUID GetUUID(); + + bool RemoteIsEFI(); + + bool RemoteIsDarwinKernel(); + + lldb::addr_t GetLoadAddress(); + + bool SendRequestResume(); + + bool SendRequestSuspend(); + + bool SendRequestBreakpoint(bool set, lldb::addr_t addr); + +protected: + bool SendRequestPacketNoLock(const PacketStreamType &request_packet); + + size_t WaitForPacketWithTimeoutMicroSecondsNoLock( + lldb_private::DataExtractor &response, uint32_t timeout_usec); + + bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout); + + void MakeRequestPacketHeader(CommandType request_type, + PacketStreamType &request_packet, + uint16_t request_length); + + //------------------------------------------------------------------ + // Protected Request Packets (use public accessors which will cache + // results. + //------------------------------------------------------------------ + bool SendRequestVersion(); + + bool SendRequestHostInfo(); + + bool SendRequestKernelVersion(); + + // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... + // bool + // SendRequestImagePath (); + + void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len); + + void DumpPacket(lldb_private::Stream &s, + const lldb_private::DataExtractor &extractor); + + bool VersionIsValid() const { return m_kdp_version_version != 0; } + + bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; } + + bool ExtractIsReply(uint8_t first_packet_byte) const { + // TODO: handle big endian... + return (first_packet_byte & ePacketTypeMask) != 0; + } + + CommandType ExtractCommand(uint8_t first_packet_byte) const { + // TODO: handle big endian... + return (CommandType)(first_packet_byte & eCommandTypeMask); + } + + static const char *GetCommandAsCString(uint8_t command); + + void ClearKDPSettings(); + + bool SendRequestAndGetReply(const CommandType command, + const PacketStreamType &request_packet, + lldb_private::DataExtractor &reply_packet); + //------------------------------------------------------------------ + // Classes that inherit from CommunicationKDP can see and modify these + //------------------------------------------------------------------ + uint32_t m_addr_byte_size; + lldb::ByteOrder m_byte_order; + uint32_t m_packet_timeout; + std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving + // packets to a single thread at a time + lldb_private::Predicate<bool> m_is_running; + uint32_t m_session_key; + uint8_t m_request_sequence_id; + uint8_t m_exception_sequence_id; + uint32_t m_kdp_version_version; + uint32_t m_kdp_version_feature; + uint32_t m_kdp_hostinfo_cpu_mask; + uint32_t m_kdp_hostinfo_cpu_type; + uint32_t m_kdp_hostinfo_cpu_subtype; + std::string m_kernel_version; + // std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to + // hang the KDP connection... + lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging private: - //------------------------------------------------------------------ - // For CommunicationKDP only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (CommunicationKDP); + //------------------------------------------------------------------ + // For CommunicationKDP only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(CommunicationKDP); }; -#endif // liblldb_CommunicationKDP_h_ +#endif // liblldb_CommunicationKDP_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 9b402ff63bf..756b145b3d6 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -16,9 +16,9 @@ // Other libraries and framework includes #include "lldb/Core/Debugger.h" -#include "lldb/Core/PluginManager.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/UUID.h" #include "lldb/Host/ConnectionFileDescriptor.h" @@ -42,1168 +42,1000 @@ #define USEC_PER_SEC 1000000 // Project includes +#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" #include "ProcessKDP.h" #include "ProcessKDPLog.h" #include "ThreadKDP.h" -#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" -#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" using namespace lldb; using namespace lldb_private; namespace { - static PropertyDefinition - g_properties[] = - { - { "packet-timeout" , OptionValue::eTypeUInt64 , true , 5, NULL, NULL, "Specify the default packet timeout in seconds." }, - { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL } - }; - - enum - { - ePropertyPacketTimeout - }; - - class PluginProperties : public Properties - { - public: - - static ConstString - GetSettingName () - { - return ProcessKDP::GetPluginNameStatic(); - } +static PropertyDefinition g_properties[] = { + {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, NULL, + "Specify the default packet timeout in seconds."}, + {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; - PluginProperties() : - Properties () - { - m_collection_sp.reset (new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } - - virtual - ~PluginProperties() - { - } - - uint64_t - GetPacketTimeout() - { - const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value); - } - }; +enum { ePropertyPacketTimeout }; - typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; +class PluginProperties : public Properties { +public: + static ConstString GetSettingName() { + return ProcessKDP::GetPluginNameStatic(); + } + + PluginProperties() : Properties() { + m_collection_sp.reset(new OptionValueProperties(GetSettingName())); + m_collection_sp->Initialize(g_properties); + } + + virtual ~PluginProperties() {} + + uint64_t GetPacketTimeout() { + const uint32_t idx = ePropertyPacketTimeout; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + NULL, idx, g_properties[idx].default_uint_value); + } +}; + +typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; + +static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { + static ProcessKDPPropertiesSP g_settings_sp; + if (!g_settings_sp) + g_settings_sp.reset(new PluginProperties()); + return g_settings_sp; +} - static const ProcessKDPPropertiesSP & - GetGlobalPluginProperties() - { - static ProcessKDPPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset (new PluginProperties ()); - return g_settings_sp; - } - } // anonymous namespace end static const lldb::tid_t g_kernel_tid = 1; -ConstString -ProcessKDP::GetPluginNameStatic() -{ - static ConstString g_name("kdp-remote"); - return g_name; +ConstString ProcessKDP::GetPluginNameStatic() { + static ConstString g_name("kdp-remote"); + return g_name; } -const char * -ProcessKDP::GetPluginDescriptionStatic() -{ - return "KDP Remote protocol based debugging plug-in for darwin kernel debugging."; +const char *ProcessKDP::GetPluginDescriptionStatic() { + return "KDP Remote protocol based debugging plug-in for darwin kernel " + "debugging."; } -void -ProcessKDP::Terminate() -{ - PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance); +void ProcessKDP::Terminate() { + PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); } - -lldb::ProcessSP -ProcessKDP::CreateInstance (TargetSP target_sp, - ListenerSP listener_sp, - const FileSpec *crash_file_path) -{ - lldb::ProcessSP process_sp; - if (crash_file_path == NULL) - process_sp.reset(new ProcessKDP (target_sp, listener_sp)); - return process_sp; +lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec *crash_file_path) { + lldb::ProcessSP process_sp; + if (crash_file_path == NULL) + process_sp.reset(new ProcessKDP(target_sp, listener_sp)); + return process_sp; } -bool -ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) -{ - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - Module *exe_module = target_sp->GetExecutableModulePointer(); - if (exe_module) - { - const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) - { - case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for iOS, but accept darwin just in case - case llvm::Triple::MacOSX: // For desktop targets - case llvm::Triple::IOS: // For arm targets - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - if (triple_ref.getVendor() == llvm::Triple::Apple) - { - ObjectFile *exe_objfile = exe_module->GetObjectFile(); - if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && - exe_objfile->GetStrata() == ObjectFile::eStrataKernel) - return true; - } - break; - - default: - break; - } +bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { + if (plugin_specified_by_name) + return true; + + // For now we are just making sure the file exists for a given module + Module *exe_module = target_sp->GetExecutableModulePointer(); + if (exe_module) { + const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); + switch (triple_ref.getOS()) { + case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for + // iOS, but accept darwin just in case + case llvm::Triple::MacOSX: // For desktop targets + case llvm::Triple::IOS: // For arm targets + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: + if (triple_ref.getVendor() == llvm::Triple::Apple) { + ObjectFile *exe_objfile = exe_module->GetObjectFile(); + if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && + exe_objfile->GetStrata() == ObjectFile::eStrataKernel) + return true; + } + break; + + default: + break; } - return false; + } + return false; } //---------------------------------------------------------------------- // ProcessKDP constructor //---------------------------------------------------------------------- -ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) : - Process (target_sp, listener_sp), - m_comm("lldb.process.kdp-remote.communication"), - m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"), - m_dyld_plugin_name (), - m_kernel_load_addr (LLDB_INVALID_ADDRESS), - m_command_sp(), - m_kernel_thread_wp() -{ - m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); - m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue"); - const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout(); - if (timeout_seconds > 0) - m_comm.SetPacketTimeout(timeout_seconds); +ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) + : Process(target_sp, listener_sp), + m_comm("lldb.process.kdp-remote.communication"), + m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), + m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), + m_command_sp(), m_kernel_thread_wp() { + m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, + "async thread should exit"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, + "async thread continue"); + const uint64_t timeout_seconds = + GetGlobalPluginProperties()->GetPacketTimeout(); + if (timeout_seconds > 0) + m_comm.SetPacketTimeout(timeout_seconds); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ProcessKDP::~ProcessKDP() -{ - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); +ProcessKDP::~ProcessKDP() { + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); } //---------------------------------------------------------------------- // PluginInterface //---------------------------------------------------------------------- -lldb_private::ConstString -ProcessKDP::GetPluginName() -{ - return GetPluginNameStatic(); +lldb_private::ConstString ProcessKDP::GetPluginName() { + return GetPluginNameStatic(); } -uint32_t -ProcessKDP::GetPluginVersion() -{ - return 1; -} +uint32_t ProcessKDP::GetPluginVersion() { return 1; } -Error -ProcessKDP::WillLaunch (Module* module) -{ - Error error; - error.SetErrorString ("launching not supported in kdp-remote plug-in"); - return error; +Error ProcessKDP::WillLaunch(Module *module) { + Error error; + error.SetErrorString("launching not supported in kdp-remote plug-in"); + return error; } -Error -ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid) -{ - Error error; - error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in"); - return error; +Error ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { + Error error; + error.SetErrorString( + "attaching to a by process ID not supported in kdp-remote plug-in"); + return error; } -Error -ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) -{ - Error error; - error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in"); - return error; +Error ProcessKDP::WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { + Error error; + error.SetErrorString( + "attaching to a by process name not supported in kdp-remote plug-in"); + return error; } -bool -ProcessKDP::GetHostArchitecture(ArchSpec &arch) -{ - uint32_t cpu = m_comm.GetCPUType(); - if (cpu) - { - uint32_t sub = m_comm.GetCPUSubtype(); - arch.SetArchitecture(eArchTypeMachO, cpu, sub); - // Leave architecture vendor as unspecified unknown - arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); - arch.GetTriple().setVendorName(llvm::StringRef()); - return true; - } - arch.Clear(); - return false; +bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { + uint32_t cpu = m_comm.GetCPUType(); + if (cpu) { + uint32_t sub = m_comm.GetCPUSubtype(); + arch.SetArchitecture(eArchTypeMachO, cpu, sub); + // Leave architecture vendor as unspecified unknown + arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); + arch.GetTriple().setVendorName(llvm::StringRef()); + return true; + } + arch.Clear(); + return false; } -Error -ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url) -{ - Error error; - - // Don't let any JIT happen when doing KDP as we can't allocate - // memory and we don't want to be mucking with threads that might - // already be handling exceptions - SetCanJIT(false); +Error ProcessKDP::DoConnectRemote(Stream *strm, const char *remote_url) { + Error error; - if (remote_url == NULL || remote_url[0] == '\0') - { - error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url); - return error; - } + // Don't let any JIT happen when doing KDP as we can't allocate + // memory and we don't want to be mucking with threads that might + // already be handling exceptions + SetCanJIT(false); - std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); - if (conn_ap.get()) - { - // Only try once for now. - // TODO: check if we should be retrying? - const uint32_t max_retry_count = 1; - for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count) - { - if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) - break; - usleep (100000); - } + if (remote_url == NULL || remote_url[0] == '\0') { + error.SetErrorStringWithFormat("invalid connection URL '%s'", remote_url); + return error; + } + + std::unique_ptr<ConnectionFileDescriptor> conn_ap( + new ConnectionFileDescriptor()); + if (conn_ap.get()) { + // Only try once for now. + // TODO: check if we should be retrying? + const uint32_t max_retry_count = 1; + for (uint32_t retry_count = 0; retry_count < max_retry_count; + ++retry_count) { + if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) + break; + usleep(100000); } - - if (conn_ap->IsConnected()) - { - const TCPSocket& socket = static_cast<const TCPSocket&>(*conn_ap->GetReadObject()); - const uint16_t reply_port = socket.GetLocalPortNumber(); - - if (reply_port != 0) - { - m_comm.SetConnection(conn_ap.release()); - - if (m_comm.SendRequestReattach(reply_port)) - { - if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB...")) - { - m_comm.GetVersion(); - - Target &target = GetTarget(); - ArchSpec kernel_arch; - // The host architecture - GetHostArchitecture(kernel_arch); - ArchSpec target_arch = target.GetArchitecture(); - // Merge in any unspecified stuff into the target architecture in - // case the target arch isn't set at all or incompletely. - target_arch.MergeFrom(kernel_arch); - target.SetArchitecture(target_arch); - - /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet. */ - /* An EFI kdp session has neither UUID nor load address. */ - - UUID kernel_uuid = m_comm.GetUUID (); - addr_t kernel_load_addr = m_comm.GetLoadAddress (); - - if (m_comm.RemoteIsEFI ()) - { - // Select an invalid plugin name for the dynamic loader so one doesn't get used - // since EFI does its own manual loading via python scripting - static ConstString g_none_dynamic_loader("none"); - m_dyld_plugin_name = g_none_dynamic_loader; - - if (kernel_uuid.IsValid()) { - // If EFI passed in a UUID= try to lookup UUID - // The slide will not be provided. But the UUID - // lookup will be used to launch EFI debug scripts - // from the dSYM, that can load all of the symbols. - ModuleSpec module_spec; - module_spec.GetUUID() = kernel_uuid; - module_spec.GetArchitecture() = target.GetArchitecture(); - - // Lookup UUID locally, before attempting dsymForUUID like action - module_spec.GetSymbolFileSpec() = Symbols::LocateExecutableSymbolFile(module_spec); - if (module_spec.GetSymbolFileSpec()) - { - ModuleSpec executable_module_spec = Symbols::LocateExecutableObjectFile (module_spec); - if (executable_module_spec.GetFileSpec().Exists()) - { - module_spec.GetFileSpec() = executable_module_spec.GetFileSpec(); - } - } - if (!module_spec.GetSymbolFileSpec() || !module_spec.GetSymbolFileSpec()) - Symbols::DownloadObjectAndSymbolFile (module_spec, true); - - if (module_spec.GetFileSpec().Exists()) - { - ModuleSP module_sp(new Module (module_spec)); - if (module_sp.get() && module_sp->GetObjectFile()) - { - // Get the current target executable - ModuleSP exe_module_sp (target.GetExecutableModule ()); - - // Make sure you don't already have the right module loaded and they will be uniqued - if (exe_module_sp.get() != module_sp.get()) - target.SetExecutableModule (module_sp, false); - } - } - } - } - else if (m_comm.RemoteIsDarwinKernel ()) - { - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); - if (kernel_load_addr != LLDB_INVALID_ADDRESS) - { - m_kernel_load_addr = kernel_load_addr; - } - } - - // Set the thread ID - UpdateThreadListIfNeeded (); - SetID (1); - GetThreadList (); - SetPrivateState (eStateStopped); - StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); - if (async_strm_sp) - { - const char *cstr; - if ((cstr = m_comm.GetKernelVersion ()) != NULL) - { - async_strm_sp->Printf ("Version: %s\n", cstr); - async_strm_sp->Flush(); - } -// if ((cstr = m_comm.GetImagePath ()) != NULL) -// { -// async_strm_sp->Printf ("Image Path: %s\n", cstr); -// async_strm_sp->Flush(); -// } - } + } + + if (conn_ap->IsConnected()) { + const TCPSocket &socket = + static_cast<const TCPSocket &>(*conn_ap->GetReadObject()); + const uint16_t reply_port = socket.GetLocalPortNumber(); + + if (reply_port != 0) { + m_comm.SetConnection(conn_ap.release()); + + if (m_comm.SendRequestReattach(reply_port)) { + if (m_comm.SendRequestConnect(reply_port, reply_port, + "Greetings from LLDB...")) { + m_comm.GetVersion(); + + Target &target = GetTarget(); + ArchSpec kernel_arch; + // The host architecture + GetHostArchitecture(kernel_arch); + ArchSpec target_arch = target.GetArchitecture(); + // Merge in any unspecified stuff into the target architecture in + // case the target arch isn't set at all or incompletely. + target_arch.MergeFrom(kernel_arch); + target.SetArchitecture(target_arch); + + /* Get the kernel's UUID and load address via KDP_KERNELVERSION + * packet. */ + /* An EFI kdp session has neither UUID nor load address. */ + + UUID kernel_uuid = m_comm.GetUUID(); + addr_t kernel_load_addr = m_comm.GetLoadAddress(); + + if (m_comm.RemoteIsEFI()) { + // Select an invalid plugin name for the dynamic loader so one + // doesn't get used + // since EFI does its own manual loading via python scripting + static ConstString g_none_dynamic_loader("none"); + m_dyld_plugin_name = g_none_dynamic_loader; + + if (kernel_uuid.IsValid()) { + // If EFI passed in a UUID= try to lookup UUID + // The slide will not be provided. But the UUID + // lookup will be used to launch EFI debug scripts + // from the dSYM, that can load all of the symbols. + ModuleSpec module_spec; + module_spec.GetUUID() = kernel_uuid; + module_spec.GetArchitecture() = target.GetArchitecture(); + + // Lookup UUID locally, before attempting dsymForUUID like action + module_spec.GetSymbolFileSpec() = + Symbols::LocateExecutableSymbolFile(module_spec); + if (module_spec.GetSymbolFileSpec()) { + ModuleSpec executable_module_spec = + Symbols::LocateExecutableObjectFile(module_spec); + if (executable_module_spec.GetFileSpec().Exists()) { + module_spec.GetFileSpec() = + executable_module_spec.GetFileSpec(); } - else - { - error.SetErrorString("KDP_REATTACH failed"); + } + if (!module_spec.GetSymbolFileSpec() || + !module_spec.GetSymbolFileSpec()) + Symbols::DownloadObjectAndSymbolFile(module_spec, true); + + if (module_spec.GetFileSpec().Exists()) { + ModuleSP module_sp(new Module(module_spec)); + if (module_sp.get() && module_sp->GetObjectFile()) { + // Get the current target executable + ModuleSP exe_module_sp(target.GetExecutableModule()); + + // Make sure you don't already have the right module loaded + // and they will be uniqued + if (exe_module_sp.get() != module_sp.get()) + target.SetExecutableModule(module_sp, false); } + } } - else - { - error.SetErrorString("KDP_REATTACH failed"); + } else if (m_comm.RemoteIsDarwinKernel()) { + m_dyld_plugin_name = + DynamicLoaderDarwinKernel::GetPluginNameStatic(); + if (kernel_load_addr != LLDB_INVALID_ADDRESS) { + m_kernel_load_addr = kernel_load_addr; } + } + + // Set the thread ID + UpdateThreadListIfNeeded(); + SetID(1); + GetThreadList(); + SetPrivateState(eStateStopped); + StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); + if (async_strm_sp) { + const char *cstr; + if ((cstr = m_comm.GetKernelVersion()) != NULL) { + async_strm_sp->Printf("Version: %s\n", cstr); + async_strm_sp->Flush(); + } + // if ((cstr = m_comm.GetImagePath ()) != NULL) + // { + // async_strm_sp->Printf ("Image Path: + // %s\n", cstr); + // async_strm_sp->Flush(); + // } + } + } else { + error.SetErrorString("KDP_REATTACH failed"); } - else - { - error.SetErrorString("invalid reply port from UDP connection"); - } - } - else - { - if (error.Success()) - error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url); + } else { + error.SetErrorString("KDP_REATTACH failed"); + } + } else { + error.SetErrorString("invalid reply port from UDP connection"); } - if (error.Fail()) - m_comm.Disconnect(); - - return error; + } else { + if (error.Success()) + error.SetErrorStringWithFormat("failed to connect to '%s'", remote_url); + } + if (error.Fail()) + m_comm.Disconnect(); + + return error; } //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- -Error -ProcessKDP::DoLaunch (Module *exe_module, - ProcessLaunchInfo &launch_info) -{ - Error error; - error.SetErrorString ("launching not supported in kdp-remote plug-in"); - return error; +Error ProcessKDP::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { + Error error; + error.SetErrorString("launching not supported in kdp-remote plug-in"); + return error; } -Error -ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) -{ - Error error; - error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging"); - return error; +Error ProcessKDP::DoAttachToProcessWithID( + lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { + Error error; + error.SetErrorString( + "attach to process by ID is not suppported in kdp remote debugging"); + return error; } -Error -ProcessKDP::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info) -{ - Error error; - error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging"); - return error; +Error ProcessKDP::DoAttachToProcessWithName( + const char *process_name, const ProcessAttachInfo &attach_info) { + Error error; + error.SetErrorString( + "attach to process by name is not suppported in kdp remote debugging"); + return error; } +void ProcessKDP::DidAttach(ArchSpec &process_arch) { + Process::DidAttach(process_arch); -void -ProcessKDP::DidAttach (ArchSpec &process_arch) -{ - Process::DidAttach(process_arch); - - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); - if (log) - log->Printf ("ProcessKDP::DidAttach()"); - if (GetID() != LLDB_INVALID_PROCESS_ID) - { - GetHostArchitecture(process_arch); - } + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf("ProcessKDP::DidAttach()"); + if (GetID() != LLDB_INVALID_PROCESS_ID) { + GetHostArchitecture(process_arch); + } } -addr_t -ProcessKDP::GetImageInfoAddress() -{ - return m_kernel_load_addr; -} +addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } -lldb_private::DynamicLoader * -ProcessKDP::GetDynamicLoader () -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); - return m_dyld_ap.get(); +lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin( + this, + m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); + return m_dyld_ap.get(); } -Error -ProcessKDP::WillResume () -{ - return Error(); -} +Error ProcessKDP::WillResume() { return Error(); } -Error -ProcessKDP::DoResume () -{ - Error error; - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); - // Only start the async thread if we try to do any process control - if (!m_async_thread.IsJoinable()) - StartAsyncThread(); - - bool resume = false; - - // With KDP there is only one thread we can tell what to do - ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid)); - - if (kernel_thread_sp) - { - const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState(); - - if (log) - log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state)); - switch (thread_resume_state) - { - case eStateSuspended: - // Nothing to do here when a thread will stay suspended - // we just leave the CPU mask bit set to zero for the thread - if (log) - log->Printf ("ProcessKDP::DoResume() = suspended???"); - break; - - case eStateStepping: - { - lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); - - if (reg_ctx_sp) - { - if (log) - log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); - reg_ctx_sp->HardwareSingleStep (true); - resume = true; - } - else - { - error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); - } - } - break; - - case eStateRunning: - { - lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); - - if (reg_ctx_sp) - { - if (log) - log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);"); - reg_ctx_sp->HardwareSingleStep (false); - resume = true; - } - else - { - error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); - } - } - break; +Error ProcessKDP::DoResume() { + Error error; + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + // Only start the async thread if we try to do any process control + if (!m_async_thread.IsJoinable()) + StartAsyncThread(); - default: - // The only valid thread resume states are listed above - assert (!"invalid thread resume state"); - break; - } - } + bool resume = false; + + // With KDP there is only one thread we can tell what to do + ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); + + if (kernel_thread_sp) { + const StateType thread_resume_state = + kernel_thread_sp->GetTemporaryResumeState(); - if (resume) - { + if (log) + log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", + StateAsCString(thread_resume_state)); + switch (thread_resume_state) { + case eStateSuspended: + // Nothing to do here when a thread will stay suspended + // we just leave the CPU mask bit set to zero for the thread + if (log) + log->Printf("ProcessKDP::DoResume() = suspended???"); + break; + + case eStateStepping: { + lldb::RegisterContextSP reg_ctx_sp( + kernel_thread_sp->GetRegisterContext()); + + if (reg_ctx_sp) { if (log) - log->Printf ("ProcessKDP::DoResume () sending resume"); - - if (m_comm.SendRequestResume ()) - { - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue); - SetPrivateState(eStateRunning); - } - else - error.SetErrorString ("KDP resume failed"); - } - else - { - error.SetErrorString ("kernel thread is suspended"); + log->Printf( + "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); + reg_ctx_sp->HardwareSingleStep(true); + resume = true; + } else { + error.SetErrorStringWithFormat( + "KDP thread 0x%llx has no register context", + kernel_thread_sp->GetID()); + } + } break; + + case eStateRunning: { + lldb::RegisterContextSP reg_ctx_sp( + kernel_thread_sp->GetRegisterContext()); + + if (reg_ctx_sp) { + if (log) + log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " + "(false);"); + reg_ctx_sp->HardwareSingleStep(false); + resume = true; + } else { + error.SetErrorStringWithFormat( + "KDP thread 0x%llx has no register context", + kernel_thread_sp->GetID()); + } + } break; + + default: + // The only valid thread resume states are listed above + assert(!"invalid thread resume state"); + break; } - - return error; -} + } -lldb::ThreadSP -ProcessKDP::GetKernelThread() -{ - // KDP only tells us about one thread/core. Any other threads will usually - // be the ones that are read from memory by the OS plug-ins. - - ThreadSP thread_sp (m_kernel_thread_wp.lock()); - if (!thread_sp) - { - thread_sp.reset(new ThreadKDP (*this, g_kernel_tid)); - m_kernel_thread_wp = thread_sp; - } - return thread_sp; + if (resume) { + if (log) + log->Printf("ProcessKDP::DoResume () sending resume"); + + if (m_comm.SendRequestResume()) { + m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); + SetPrivateState(eStateRunning); + } else + error.SetErrorString("KDP resume failed"); + } else { + error.SetErrorString("kernel thread is suspended"); + } + + return error; } +lldb::ThreadSP ProcessKDP::GetKernelThread() { + // KDP only tells us about one thread/core. Any other threads will usually + // be the ones that are read from memory by the OS plug-ins. + ThreadSP thread_sp(m_kernel_thread_wp.lock()); + if (!thread_sp) { + thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); + m_kernel_thread_wp = thread_sp; + } + return thread_sp; +} - -bool -ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - // locker will keep a mutex locked until it goes out of scope - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD)); - if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) - log->Printf ("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); - - // Even though there is a CPU mask, it doesn't mean we can see each CPU - // individually, there is really only one. Lets call this thread 1. - ThreadSP thread_sp (old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); - if (!thread_sp) - thread_sp = GetKernelThread (); - new_thread_list.AddThread(thread_sp); - - return new_thread_list.GetSize(false) > 0; +bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + // locker will keep a mutex locked until it goes out of scope + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); + if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) + log->Printf("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); + + // Even though there is a CPU mask, it doesn't mean we can see each CPU + // individually, there is really only one. Lets call this thread 1. + ThreadSP thread_sp( + old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); + if (!thread_sp) + thread_sp = GetKernelThread(); + new_thread_list.AddThread(thread_sp); + + return new_thread_list.GetSize(false) > 0; } -void -ProcessKDP::RefreshStateAfterStop () -{ - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - m_thread_list.RefreshStateAfterStop(); +void ProcessKDP::RefreshStateAfterStop() { + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + m_thread_list.RefreshStateAfterStop(); } -Error -ProcessKDP::DoHalt (bool &caused_stop) -{ - Error error; - - if (m_comm.IsRunning()) - { - if (m_destroy_in_process) - { - // If we are attemping to destroy, we need to not return an error to - // Halt or DoDestroy won't get called. - // We are also currently running, so send a process stopped event - SetPrivateState (eStateStopped); - } - else - { - error.SetErrorString ("KDP cannot interrupt a running kernel"); - } +Error ProcessKDP::DoHalt(bool &caused_stop) { + Error error; + + if (m_comm.IsRunning()) { + if (m_destroy_in_process) { + // If we are attemping to destroy, we need to not return an error to + // Halt or DoDestroy won't get called. + // We are also currently running, so send a process stopped event + SetPrivateState(eStateStopped); + } else { + error.SetErrorString("KDP cannot interrupt a running kernel"); } - return error; + } + return error; } -Error -ProcessKDP::DoDetach(bool keep_stopped) -{ - Error error; - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - if (log) - log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); - - if (m_comm.IsRunning()) - { - // We are running and we can't interrupt a running kernel, so we need - // to just close the connection to the kernel and hope for the best - } - else - { - // If we are going to keep the target stopped, then don't send the disconnect message. - if (!keep_stopped && m_comm.IsConnected()) - { - const bool success = m_comm.SendRequestDisconnect(); - if (log) - { - if (success) - log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); - else - log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed"); - } - m_comm.Disconnect (); - } +Error ProcessKDP::DoDetach(bool keep_stopped) { + Error error; + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); + + if (m_comm.IsRunning()) { + // We are running and we can't interrupt a running kernel, so we need + // to just close the connection to the kernel and hope for the best + } else { + // If we are going to keep the target stopped, then don't send the + // disconnect message. + if (!keep_stopped && m_comm.IsConnected()) { + const bool success = m_comm.SendRequestDisconnect(); + if (log) { + if (success) + log->PutCString( + "ProcessKDP::DoDetach() detach packet sent successfully"); + else + log->PutCString( + "ProcessKDP::DoDetach() connection channel shutdown failed"); + } + m_comm.Disconnect(); } - StopAsyncThread (); - m_comm.Clear(); - - SetPrivateState (eStateDetached); - ResumePrivateStateThread(); - - //KillDebugserverProcess (); - return error; + } + StopAsyncThread(); + m_comm.Clear(); + + SetPrivateState(eStateDetached); + ResumePrivateStateThread(); + + // KillDebugserverProcess (); + return error; } -Error -ProcessKDP::DoDestroy () -{ - // For KDP there really is no difference between destroy and detach - bool keep_stopped = false; - return DoDetach(keep_stopped); +Error ProcessKDP::DoDestroy() { + // For KDP there really is no difference between destroy and detach + bool keep_stopped = false; + return DoDetach(keep_stopped); } //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ -bool -ProcessKDP::IsAlive () -{ - return m_comm.IsConnected() && Process::IsAlive(); +bool ProcessKDP::IsAlive() { + return m_comm.IsConnected() && Process::IsAlive(); } //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ -size_t -ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) -{ - uint8_t *data_buffer = (uint8_t *) buf; - if (m_comm.IsConnected()) - { - const size_t max_read_size = 512; - size_t total_bytes_read = 0; - - // Read the requested amount of memory in 512 byte chunks - while (total_bytes_read < size) - { - size_t bytes_to_read_this_request = size - total_bytes_read; - if (bytes_to_read_this_request > max_read_size) - { - bytes_to_read_this_request = max_read_size; - } - size_t bytes_read = m_comm.SendRequestReadMemory (addr + total_bytes_read, - data_buffer + total_bytes_read, - bytes_to_read_this_request, error); - total_bytes_read += bytes_read; - if (error.Fail() || bytes_read == 0) - { - return total_bytes_read; - } - } - +size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, + Error &error) { + uint8_t *data_buffer = (uint8_t *)buf; + if (m_comm.IsConnected()) { + const size_t max_read_size = 512; + size_t total_bytes_read = 0; + + // Read the requested amount of memory in 512 byte chunks + while (total_bytes_read < size) { + size_t bytes_to_read_this_request = size - total_bytes_read; + if (bytes_to_read_this_request > max_read_size) { + bytes_to_read_this_request = max_read_size; + } + size_t bytes_read = m_comm.SendRequestReadMemory( + addr + total_bytes_read, data_buffer + total_bytes_read, + bytes_to_read_this_request, error); + total_bytes_read += bytes_read; + if (error.Fail() || bytes_read == 0) { return total_bytes_read; + } } - error.SetErrorString ("not connected"); - return 0; -} -size_t -ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error) -{ - if (m_comm.IsConnected()) - return m_comm.SendRequestWriteMemory (addr, buf, size, error); - error.SetErrorString ("not connected"); - return 0; + return total_bytes_read; + } + error.SetErrorString("not connected"); + return 0; } -lldb::addr_t -ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) -{ - error.SetErrorString ("memory allocation not suppported in kdp remote debugging"); - return LLDB_INVALID_ADDRESS; +size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, + Error &error) { + if (m_comm.IsConnected()) + return m_comm.SendRequestWriteMemory(addr, buf, size, error); + error.SetErrorString("not connected"); + return 0; } -Error -ProcessKDP::DoDeallocateMemory (lldb::addr_t addr) -{ - Error error; - error.SetErrorString ("memory deallocation not suppported in kdp remote debugging"); - return error; +lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) { + error.SetErrorString( + "memory allocation not suppported in kdp remote debugging"); + return LLDB_INVALID_ADDRESS; } -Error -ProcessKDP::EnableBreakpointSite (BreakpointSite *bp_site) -{ - if (m_comm.LocalBreakpointsAreSupported ()) - { - Error error; - if (!bp_site->IsEnabled()) - { - if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) - { - bp_site->SetEnabled(true); - bp_site->SetType (BreakpointSite::eExternal); - } - else - { - error.SetErrorString ("KDP set breakpoint failed"); - } - } - return error; - } - return EnableSoftwareBreakpoint (bp_site); +Error ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { + Error error; + error.SetErrorString( + "memory deallocation not suppported in kdp remote debugging"); + return error; } -Error -ProcessKDP::DisableBreakpointSite (BreakpointSite *bp_site) -{ - if (m_comm.LocalBreakpointsAreSupported ()) - { - Error error; - if (bp_site->IsEnabled()) - { - BreakpointSite::Type bp_type = bp_site->GetType(); - if (bp_type == BreakpointSite::eExternal) - { - if (m_destroy_in_process && m_comm.IsRunning()) - { - // We are trying to destroy our connection and we are running - bp_site->SetEnabled(false); - } - else - { - if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) - bp_site->SetEnabled(false); - else - error.SetErrorString ("KDP remove breakpoint failed"); - } - } - else - { - error = DisableSoftwareBreakpoint (bp_site); - } - } - return error; +Error ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { + if (m_comm.LocalBreakpointsAreSupported()) { + Error error; + if (!bp_site->IsEnabled()) { + if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { + bp_site->SetEnabled(true); + bp_site->SetType(BreakpointSite::eExternal); + } else { + error.SetErrorString("KDP set breakpoint failed"); + } } - return DisableSoftwareBreakpoint (bp_site); + return error; + } + return EnableSoftwareBreakpoint(bp_site); } -Error -ProcessKDP::EnableWatchpoint (Watchpoint *wp, bool notify) -{ +Error ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { + if (m_comm.LocalBreakpointsAreSupported()) { Error error; - error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); + if (bp_site->IsEnabled()) { + BreakpointSite::Type bp_type = bp_site->GetType(); + if (bp_type == BreakpointSite::eExternal) { + if (m_destroy_in_process && m_comm.IsRunning()) { + // We are trying to destroy our connection and we are running + bp_site->SetEnabled(false); + } else { + if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) + bp_site->SetEnabled(false); + else + error.SetErrorString("KDP remove breakpoint failed"); + } + } else { + error = DisableSoftwareBreakpoint(bp_site); + } + } return error; + } + return DisableSoftwareBreakpoint(bp_site); } -Error -ProcessKDP::DisableWatchpoint (Watchpoint *wp, bool notify) -{ - Error error; - error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); - return error; +Error ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + error.SetErrorString( + "watchpoints are not suppported in kdp remote debugging"); + return error; } -void -ProcessKDP::Clear() -{ - m_thread_list.Clear(); +Error ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + error.SetErrorString( + "watchpoints are not suppported in kdp remote debugging"); + return error; } -Error -ProcessKDP::DoSignal (int signo) -{ - Error error; - error.SetErrorString ("sending signals is not suppported in kdp remote debugging"); - return error; +void ProcessKDP::Clear() { m_thread_list.Clear(); } + +Error ProcessKDP::DoSignal(int signo) { + Error error; + error.SetErrorString( + "sending signals is not suppported in kdp remote debugging"); + return error; } -void -ProcessKDP::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin (GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance, - DebuggerInitialize); - - Log::Callbacks log_callbacks = { - ProcessKDPLog::DisableLog, - ProcessKDPLog::EnableLog, - ProcessKDPLog::ListLogCategories - }; - - Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks); - }); +void ProcessKDP::Initialize() { + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + DebuggerInitialize); + + Log::Callbacks log_callbacks = {ProcessKDPLog::DisableLog, + ProcessKDPLog::EnableLog, + ProcessKDPLog::ListLogCategories}; + + Log::RegisterLogChannel(ProcessKDP::GetPluginNameStatic(), log_callbacks); + }); } -void -ProcessKDP::DebuggerInitialize (lldb_private::Debugger &debugger) -{ - if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName())) - { - const bool is_global_setting = true; - PluginManager::CreateSettingForProcessPlugin (debugger, - GetGlobalPluginProperties()->GetValueProperties(), - ConstString ("Properties for the kdp-remote process plug-in."), - is_global_setting); - } +void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { + if (!PluginManager::GetSettingForProcessPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForProcessPlugin( + debugger, GetGlobalPluginProperties()->GetValueProperties(), + ConstString("Properties for the kdp-remote process plug-in."), + is_global_setting); + } } -bool -ProcessKDP::StartAsyncThread () -{ - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - - if (log) - log->Printf ("ProcessKDP::StartAsyncThread ()"); +bool ProcessKDP::StartAsyncThread() { + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - if (m_async_thread.IsJoinable()) - return true; + if (log) + log->Printf("ProcessKDP::StartAsyncThread ()"); - m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); - return m_async_thread.IsJoinable(); -} + if (m_async_thread.IsJoinable()) + return true; -void -ProcessKDP::StopAsyncThread () -{ - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - - if (log) - log->Printf ("ProcessKDP::StopAsyncThread ()"); - - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); - - // Stop the stdio thread - if (m_async_thread.IsJoinable()) - m_async_thread.Join(nullptr); + m_async_thread = ThreadLauncher::LaunchThread( + "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); + return m_async_thread.IsJoinable(); } +void ProcessKDP::StopAsyncThread() { + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -void * -ProcessKDP::AsyncThread (void *arg) -{ - ProcessKDP *process = (ProcessKDP*) arg; - - const lldb::pid_t pid = process->GetID(); + if (log) + log->Printf("ProcessKDP::StopAsyncThread ()"); - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); - if (log) - log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid); - - ListenerSP listener_sp (Listener::MakeListener("ProcessKDP::AsyncThread")); - EventSP event_sp; - const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | - eBroadcastBitAsyncThreadShouldExit; - - - if (listener_sp->StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) - { - bool done = false; - while (!done) - { - if (log) - log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", - pid); - if (listener_sp->WaitForEvent(std::chrono::microseconds(0), event_sp)) - { - uint32_t event_type = event_sp->GetType(); - if (log) - log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") Got an event of type: %d...", - pid, - event_type); - - // When we are running, poll for 1 second to try and get an exception - // to indicate the process has stopped. If we don't get one, check to - // make sure no one asked us to exit - bool is_running = false; - DataExtractor exc_reply_packet; - do - { - switch (event_type) - { - case eBroadcastBitAsyncContinue: - { - is_running = true; - if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC)) - { - ThreadSP thread_sp (process->GetKernelThread()); - if (thread_sp) - { - lldb::RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext()); - if (reg_ctx_sp) - reg_ctx_sp->InvalidateAllRegisters(); - static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet); - } - - // TODO: parse the stop reply packet - is_running = false; - process->SetPrivateState(eStateStopped); - } - else - { - // Check to see if we are supposed to exit. There is no way to - // interrupt a running kernel, so all we can do is wait for an - // exception or detach... - if (listener_sp->GetNextEvent(event_sp)) - { - // We got an event, go through the loop again - event_type = event_sp->GetType(); - } - } - } - break; - - case eBroadcastBitAsyncThreadShouldExit: - if (log) - log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", - pid); - done = true; - is_running = false; - break; - - default: - if (log) - log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got unknown event 0x%8.8x", - pid, - event_type); - done = true; - is_running = false; - break; - } - } while (is_running); - } - else - { - if (log) - log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", - pid); - done = true; + m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); + + // Stop the stdio thread + if (m_async_thread.IsJoinable()) + m_async_thread.Join(nullptr); +} + +void *ProcessKDP::AsyncThread(void *arg) { + ProcessKDP *process = (ProcessKDP *)arg; + + const lldb::pid_t pid = process->GetID(); + + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 + ") thread starting...", + arg, pid); + + ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); + EventSP event_sp; + const uint32_t desired_event_mask = + eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; + + if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, + desired_event_mask) == + desired_event_mask) { + bool done = false; + while (!done) { + if (log) + log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp)...", + pid); + if (listener_sp->WaitForEvent(std::chrono::microseconds(0), event_sp)) { + uint32_t event_type = event_sp->GetType(); + if (log) + log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 + ") Got an event of type: %d...", + pid, event_type); + + // When we are running, poll for 1 second to try and get an exception + // to indicate the process has stopped. If we don't get one, check to + // make sure no one asked us to exit + bool is_running = false; + DataExtractor exc_reply_packet; + do { + switch (event_type) { + case eBroadcastBitAsyncContinue: { + is_running = true; + if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( + exc_reply_packet, 1 * USEC_PER_SEC)) { + ThreadSP thread_sp(process->GetKernelThread()); + if (thread_sp) { + lldb::RegisterContextSP reg_ctx_sp( + thread_sp->GetRegisterContext()); + if (reg_ctx_sp) + reg_ctx_sp->InvalidateAllRegisters(); + static_cast<ThreadKDP *>(thread_sp.get()) + ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); + } + + // TODO: parse the stop reply packet + is_running = false; + process->SetPrivateState(eStateStopped); + } else { + // Check to see if we are supposed to exit. There is no way to + // interrupt a running kernel, so all we can do is wait for an + // exception or detach... + if (listener_sp->GetNextEvent(event_sp)) { + // We got an event, go through the loop again + event_type = event_sp->GetType(); + } } - } + } break; + + case eBroadcastBitAsyncThreadShouldExit: + if (log) + log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 + ") got eBroadcastBitAsyncThreadShouldExit...", + pid); + done = true; + is_running = false; + break; + + default: + if (log) + log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 + ") got unknown event 0x%8.8x", + pid, event_type); + done = true; + is_running = false; + break; + } + } while (is_running); + } else { + if (log) + log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp) => false", + pid); + done = true; + } } - - if (log) - log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread exiting...", - arg, - pid); + } - process->m_async_thread.Reset(); - return NULL; -} + if (log) + log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 + ") thread exiting...", + arg, pid); + process->m_async_thread.Reset(); + return NULL; +} -class CommandObjectProcessKDPPacketSend : public CommandObjectParsed -{ +class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { private: - - OptionGroupOptions m_option_group; - OptionGroupUInt64 m_command_byte; - OptionGroupString m_packet_data; - - virtual Options * - GetOptions () - { - return &m_option_group; - } - + OptionGroupOptions m_option_group; + OptionGroupUInt64 m_command_byte; + OptionGroupString m_packet_data; + + virtual Options *GetOptions() { return &m_option_group; } public: - CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process plugin packet send", - "Send a custom packet through the KDP protocol by specifying the command byte and the packet payload data. A packet will be sent with a correct header and payload, and the raw result bytes will be displayed as a string value. ", - NULL), + CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process plugin packet send", + "Send a custom packet through the KDP protocol by " + "specifying the command byte and the packet " + "payload data. A packet will be sent with a " + "correct header and payload, and the raw result " + "bytes will be displayed as a string value. ", + NULL), m_option_group(), - m_command_byte(LLDB_OPT_SET_1, true , "command", 'c', 0, eArgTypeNone, "Specify the command byte to use when sending the KDP request packet.", 0), - m_packet_data (LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, "Specify packet payload bytes as a hex ASCII string with no spaces or hex prefixes.", NULL) - { - m_option_group.Append (&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_packet_data , LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectProcessKDPPacketSend () - { - } - - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - if (!m_command_byte.GetOptionValue().OptionWasSet()) - { - result.AppendError ("the --command option must be set to a valid command byte"); - result.SetStatus (eReturnStatusFailed); - } - else - { - const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0); - if (command_byte > 0 && command_byte <= UINT8_MAX) - { - ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - const StateType state = process->GetState(); - - if (StateIsStoppedState (state, true)) - { - std::vector<uint8_t> payload_bytes; - const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue(); - if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) - { - StringExtractor extractor(ascii_hex_bytes_cstr); - const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size(); - if (ascii_hex_bytes_cstr_len & 1) - { - result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - payload_bytes.resize(ascii_hex_bytes_cstr_len/2); - if (extractor.GetHexBytes(payload_bytes, '\xdd') != payload_bytes.size()) - { - result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - Error error; - DataExtractor reply; - process->GetCommunication().SendRawRequest (command_byte, - payload_bytes.empty() ? NULL : payload_bytes.data(), - payload_bytes.size(), - reply, - error); - - if (error.Success()) - { - // Copy the binary bytes into a hex ASCII string for the result - StreamString packet; - packet.PutBytesAsRawHex8(reply.GetDataStart(), - reply.GetByteSize(), - endian::InlHostByteOrder(), - endian::InlHostByteOrder()); - result.AppendMessage(packet.GetString().c_str()); - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - else - { - const char *error_cstr = error.AsCString(); - if (error_cstr && error_cstr[0]) - result.AppendError (error_cstr); - else - result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state)); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError ("invalid process"); - result.SetStatus (eReturnStatusFailed); - } + m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, + "Specify the command byte to use when sending the KDP " + "request packet.", + 0), + m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, + "Specify packet payload bytes as a hex ASCII string with " + "no spaces or hex prefixes.", + NULL) { + m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectProcessKDPPacketSend() {} + + bool DoExecute(Args &command, CommandReturnObject &result) { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + if (!m_command_byte.GetOptionValue().OptionWasSet()) { + result.AppendError( + "the --command option must be set to a valid command byte"); + result.SetStatus(eReturnStatusFailed); + } else { + const uint64_t command_byte = + m_command_byte.GetOptionValue().GetUInt64Value(0); + if (command_byte > 0 && command_byte <= UINT8_MAX) { + ProcessKDP *process = + (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) { + const StateType state = process->GetState(); + + if (StateIsStoppedState(state, true)) { + std::vector<uint8_t> payload_bytes; + const char *ascii_hex_bytes_cstr = + m_packet_data.GetOptionValue().GetCurrentValue(); + if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { + StringExtractor extractor(ascii_hex_bytes_cstr); + const size_t ascii_hex_bytes_cstr_len = + extractor.GetStringRef().size(); + if (ascii_hex_bytes_cstr_len & 1) { + result.AppendErrorWithFormat("payload data must contain an " + "even number of ASCII hex " + "characters: '%s'", + ascii_hex_bytes_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte); - result.SetStatus (eReturnStatusFailed); + payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); + if (extractor.GetHexBytes(payload_bytes, '\xdd') != + payload_bytes.size()) { + result.AppendErrorWithFormat("payload data must only contain " + "ASCII hex characters (no " + "spaces or hex prefixes): '%s'", + ascii_hex_bytes_cstr); + result.SetStatus(eReturnStatusFailed); + return false; } + } + Error error; + DataExtractor reply; + process->GetCommunication().SendRawRequest( + command_byte, + payload_bytes.empty() ? NULL : payload_bytes.data(), + payload_bytes.size(), reply, error); + + if (error.Success()) { + // Copy the binary bytes into a hex ASCII string for the result + StreamString packet; + packet.PutBytesAsRawHex8( + reply.GetDataStart(), reply.GetByteSize(), + endian::InlHostByteOrder(), endian::InlHostByteOrder()); + result.AppendMessage(packet.GetString().c_str()); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } else { + const char *error_cstr = error.AsCString(); + if (error_cstr && error_cstr[0]) + result.AppendError(error_cstr); + else + result.AppendErrorWithFormat("unknown error 0x%8.8x", + error.GetError()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + result.AppendErrorWithFormat("process must be stopped in order " + "to send KDP packets, state is %s", + StateAsCString(state)); + result.SetStatus(eReturnStatusFailed); } + } else { + result.AppendError("invalid process"); + result.SetStatus(eReturnStatusFailed); + } + } else { + result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 + ", valid values are 1 - 255", + command_byte); + result.SetStatus(eReturnStatusFailed); } - else - { - result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - } - return false; + } + } else { + result.AppendErrorWithFormat("'%s' takes no arguments, only options.", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); } + return false; + } }; -class CommandObjectProcessKDPPacket : public CommandObjectMultiword -{ +class CommandObjectProcessKDPPacket : public CommandObjectMultiword { private: - public: - CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "process plugin packet", - "Commands that deal with KDP remote packets.", - NULL) - { - LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessKDPPacketSend (interpreter))); - } - - ~CommandObjectProcessKDPPacket () - { - } + CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "process plugin packet", + "Commands that deal with KDP remote packets.", + NULL) { + LoadSubCommand( + "send", + CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); + } + + ~CommandObjectProcessKDPPacket() {} }; -class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword -{ +class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { public: - CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessKDP process.", - "process plugin <subcommand> [<subcommand-options>]") - { - LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket (interpreter))); - } - - ~CommandObjectMultiwordProcessKDP () - { - } + CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "process plugin", + "Commands for operating on a ProcessKDP process.", + "process plugin <subcommand> [<subcommand-options>]") { + LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( + interpreter))); + } + + ~CommandObjectMultiwordProcessKDP() {} }; -CommandObject * -ProcessKDP::GetPluginCommandObject() -{ - if (!m_command_sp) - m_command_sp.reset (new CommandObjectMultiwordProcessKDP (GetTarget().GetDebugger().GetCommandInterpreter())); - return m_command_sp.get(); +CommandObject *ProcessKDP::GetPluginCommandObject() { + if (!m_command_sp) + m_command_sp.reset(new CommandObjectMultiwordProcessKDP( + GetTarget().GetDebugger().GetCommandInterpreter())); + return m_command_sp.get(); } - diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 49f63624251..c4b046990ea 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -32,243 +32,192 @@ class ThreadKDP; -class ProcessKDP : public lldb_private::Process -{ +class ProcessKDP : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); - - static void - Initialize(); - - static void - DebuggerInitialize (lldb_private::Debugger &debugger); - - static void - Terminate(); - - static lldb_private::ConstString - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ProcessKDP(lldb::TargetSP target_sp, lldb::ListenerSP listener); - - virtual - ~ProcessKDP(); - - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - virtual bool - CanDebug (lldb::TargetSP target_sp, - bool plugin_specified_by_name); - - virtual lldb_private::CommandObject * - GetPluginCommandObject(); - - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - virtual lldb_private::Error - WillLaunch (lldb_private::Module* module); - - virtual lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info); - - virtual lldb_private::Error - WillAttachToProcessWithID (lldb::pid_t pid); - - virtual lldb_private::Error - WillAttachToProcessWithName (const char *process_name, bool wait_for_launch); - - virtual lldb_private::Error - DoConnectRemote (lldb_private::Stream *strm, const char *remote_url); - - virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info); - - virtual lldb_private::Error - DoAttachToProcessWithName (const char *process_name, const lldb_private::ProcessAttachInfo &attach_info); - - virtual void - DidAttach (lldb_private::ArchSpec &process_arch); - - lldb::addr_t - GetImageInfoAddress(); - - lldb_private::DynamicLoader * - GetDynamicLoader (); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - - virtual uint32_t - GetPluginVersion(); - - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - virtual lldb_private::Error - WillResume (); - - virtual lldb_private::Error - DoResume (); - - virtual lldb_private::Error - DoHalt (bool &caused_stop); - - virtual lldb_private::Error - DoDetach (bool keep_stopped); - - virtual lldb_private::Error - DoSignal (int signal); - - virtual lldb_private::Error - DoDestroy (); - - virtual void - RefreshStateAfterStop(); - - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - virtual bool - IsAlive (); - - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - virtual size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); - - virtual size_t - DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error); - - virtual lldb::addr_t - DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error); - - virtual lldb_private::Error - DoDeallocateMemory (lldb::addr_t ptr); - - //---------------------------------------------------------------------- - // Process Breakpoints - //---------------------------------------------------------------------- - virtual lldb_private::Error - EnableBreakpointSite (lldb_private::BreakpointSite *bp_site); - - virtual lldb_private::Error - DisableBreakpointSite (lldb_private::BreakpointSite *bp_site); - - //---------------------------------------------------------------------- - // Process Watchpoints - //---------------------------------------------------------------------- - virtual lldb_private::Error - EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); - - virtual lldb_private::Error - DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); - - CommunicationKDP & - GetCommunication() - { - return m_comm; - } + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path); + + static void Initialize(); + + static void DebuggerInitialize(lldb_private::Debugger &debugger); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ProcessKDP(lldb::TargetSP target_sp, lldb::ListenerSP listener); + + virtual ~ProcessKDP(); + + //------------------------------------------------------------------ + // Check if a given Process + //------------------------------------------------------------------ + virtual bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name); + + virtual lldb_private::CommandObject *GetPluginCommandObject(); + + //------------------------------------------------------------------ + // Creating a new process, or attaching to an existing one + //------------------------------------------------------------------ + virtual lldb_private::Error WillLaunch(lldb_private::Module *module); + + virtual lldb_private::Error + DoLaunch(lldb_private::Module *exe_module, + lldb_private::ProcessLaunchInfo &launch_info); + + virtual lldb_private::Error WillAttachToProcessWithID(lldb::pid_t pid); + + virtual lldb_private::Error + WillAttachToProcessWithName(const char *process_name, bool wait_for_launch); + + virtual lldb_private::Error DoConnectRemote(lldb_private::Stream *strm, + const char *remote_url); + + virtual lldb_private::Error + DoAttachToProcessWithID(lldb::pid_t pid, + const lldb_private::ProcessAttachInfo &attach_info); + + virtual lldb_private::Error + DoAttachToProcessWithName(const char *process_name, + const lldb_private::ProcessAttachInfo &attach_info); + + virtual void DidAttach(lldb_private::ArchSpec &process_arch); + + lldb::addr_t GetImageInfoAddress(); + + lldb_private::DynamicLoader *GetDynamicLoader(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString GetPluginName(); + + virtual uint32_t GetPluginVersion(); + + //------------------------------------------------------------------ + // Process Control + //------------------------------------------------------------------ + virtual lldb_private::Error WillResume(); + + virtual lldb_private::Error DoResume(); + + virtual lldb_private::Error DoHalt(bool &caused_stop); + + virtual lldb_private::Error DoDetach(bool keep_stopped); + + virtual lldb_private::Error DoSignal(int signal); + + virtual lldb_private::Error DoDestroy(); + + virtual void RefreshStateAfterStop(); + + //------------------------------------------------------------------ + // Process Queries + //------------------------------------------------------------------ + virtual bool IsAlive(); + + //------------------------------------------------------------------ + // Process Memory + //------------------------------------------------------------------ + virtual size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error); + + virtual size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, + lldb_private::Error &error); + + virtual lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, + lldb_private::Error &error); + + virtual lldb_private::Error DoDeallocateMemory(lldb::addr_t ptr); + + //---------------------------------------------------------------------- + // Process Breakpoints + //---------------------------------------------------------------------- + virtual lldb_private::Error + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site); + + virtual lldb_private::Error + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site); + + //---------------------------------------------------------------------- + // Process Watchpoints + //---------------------------------------------------------------------- + virtual lldb_private::Error EnableWatchpoint(lldb_private::Watchpoint *wp, + bool notify = true); + + virtual lldb_private::Error DisableWatchpoint(lldb_private::Watchpoint *wp, + bool notify = true); + + CommunicationKDP &GetCommunication() { return m_comm; } protected: - friend class ThreadKDP; - friend class CommunicationKDP; - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - bool - IsRunning ( lldb::StateType state ) - { - return state == lldb::eStateRunning || IsStepping(state); - } - - bool - IsStepping ( lldb::StateType state) - { - return state == lldb::eStateStepping; - } - - bool - CanResume ( lldb::StateType state) - { - return state == lldb::eStateStopped; - } - - bool - HasExited (lldb::StateType state) - { - return state == lldb::eStateExited; - } - - bool - GetHostArchitecture (lldb_private::ArchSpec &arch); - - bool - ProcessIDIsValid ( ) const; - - void - Clear ( ); - - virtual bool - UpdateThreadList (lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); - - enum - { - eBroadcastBitAsyncContinue = (1 << 0), - eBroadcastBitAsyncThreadShouldExit = (1 << 1) - }; - - lldb::ThreadSP - GetKernelThread (); - - //------------------------------------------------------------------ - /// Broadcaster event bits definitions. - //------------------------------------------------------------------ - CommunicationKDP m_comm; - lldb_private::Broadcaster m_async_broadcaster; - lldb_private::HostThread m_async_thread; - lldb_private::ConstString m_dyld_plugin_name; - lldb::addr_t m_kernel_load_addr; - lldb::CommandObjectSP m_command_sp; - lldb::ThreadWP m_kernel_thread_wp; - - - bool - StartAsyncThread (); - - void - StopAsyncThread (); - - static void * - AsyncThread (void *arg); - + friend class ThreadKDP; + friend class CommunicationKDP; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + bool IsRunning(lldb::StateType state) { + return state == lldb::eStateRunning || IsStepping(state); + } + + bool IsStepping(lldb::StateType state) { + return state == lldb::eStateStepping; + } + + bool CanResume(lldb::StateType state) { return state == lldb::eStateStopped; } + + bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; } + + bool GetHostArchitecture(lldb_private::ArchSpec &arch); + + bool ProcessIDIsValid() const; + + void Clear(); + + virtual bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list); + + enum { + eBroadcastBitAsyncContinue = (1 << 0), + eBroadcastBitAsyncThreadShouldExit = (1 << 1) + }; + + lldb::ThreadSP GetKernelThread(); + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + CommunicationKDP m_comm; + lldb_private::Broadcaster m_async_broadcaster; + lldb_private::HostThread m_async_thread; + lldb_private::ConstString m_dyld_plugin_name; + lldb::addr_t m_kernel_load_addr; + lldb::CommandObjectSP m_command_sp; + lldb::ThreadWP m_kernel_thread_wp; + + bool StartAsyncThread(); + + void StopAsyncThread(); + + static void *AsyncThread(void *arg); + private: - //------------------------------------------------------------------ - // For ProcessKDP only - //------------------------------------------------------------------ - - DISALLOW_COPY_AND_ASSIGN (ProcessKDP); - + //------------------------------------------------------------------ + // For ProcessKDP only + //------------------------------------------------------------------ + + DISALLOW_COPY_AND_ASSIGN(ProcessKDP); }; -#endif // liblldb_ProcessKDP_h_ +#endif // liblldb_ProcessKDP_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp index 79cb62aa006..479f09aa898 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp @@ -9,178 +9,184 @@ #include "ProcessKDPLog.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" #include "ProcessKDP.h" using namespace lldb; using namespace lldb_private; - // We want to avoid global constructors where code needs to be run so here we // control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_log_sp the first time this function is +// that will construct the static g_log_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = NULL; -static Log * -GetLog () -{ - if (!g_log_enabled) - return NULL; - return g_log; +static Log *g_log = NULL; +static Log *GetLog() { + if (!g_log_enabled) + return NULL; + return g_log; } -Log * -ProcessKDPLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; +Log *ProcessKDPLog::GetLogIfAllCategoriesSet(uint32_t mask) { + Log *log(GetLog()); + if (log && mask) { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return NULL; + } + return log; } -void -ProcessKDPLog::DisableLog (const char **categories, Stream *feedback_strm) -{ - Log *log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - if (categories[0] != NULL) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; categories[i] != NULL; ++i) - { - const char *arg = categories[i]; - - - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~KDP_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~KDP_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~KDP_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~KDP_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~KDP_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~KDP_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~KDP_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~KDP_LOG_PROCESS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~KDP_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~KDP_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~KDP_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~KDP_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - - } +void ProcessKDPLog::DisableLog(const char **categories, Stream *feedback_strm) { + Log *log(GetLog()); + if (log) { + uint32_t flag_bits = 0; + + if (categories[0] != NULL) { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits &= ~KDP_LOG_ALL; + else if (::strcasecmp(arg, "async") == 0) + flag_bits &= ~KDP_LOG_ASYNC; + else if (::strncasecmp(arg, "break", 5) == 0) + flag_bits &= ~KDP_LOG_BREAKPOINTS; + else if (::strncasecmp(arg, "comm", 4) == 0) + flag_bits &= ~KDP_LOG_COMM; + else if (::strcasecmp(arg, "default") == 0) + flag_bits &= ~KDP_LOG_DEFAULT; + else if (::strcasecmp(arg, "packets") == 0) + flag_bits &= ~KDP_LOG_PACKETS; + else if (::strcasecmp(arg, "memory") == 0) + flag_bits &= ~KDP_LOG_MEMORY; + else if (::strcasecmp(arg, "data-short") == 0) + flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp(arg, "data-long") == 0) + flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp(arg, "process") == 0) + flag_bits &= ~KDP_LOG_PROCESS; + else if (::strcasecmp(arg, "step") == 0) + flag_bits &= ~KDP_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + flag_bits &= ~KDP_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + flag_bits &= ~KDP_LOG_VERBOSE; + else if (::strncasecmp(arg, "watch", 5) == 0) + flag_bits &= ~KDP_LOG_WATCHPOINTS; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); } - - log->GetMask().Reset (flag_bits); - if (flag_bits == 0) - g_log_enabled = false; + } } - - return; -} -Log * -ProcessKDPLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } + log->GetMask().Reset(flag_bits); + if (flag_bits == 0) + g_log_enabled = false; + } + return; +} + +Log *ProcessKDPLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, + const char **categories, Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits = 0; + if (g_log) + flag_bits = g_log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log) - { - bool got_unknown_category = false; - for (size_t i=0; categories[i] != NULL; ++i) - { - const char *arg = categories[i]; - - if (::strcasecmp (arg, "all") == 0 ) flag_bits |= KDP_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= KDP_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= KDP_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= KDP_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= KDP_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= KDP_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= KDP_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= KDP_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= KDP_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= KDP_LOG_PROCESS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= KDP_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= KDP_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= KDP_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= KDP_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } + + if (g_log) { + bool got_unknown_category = false; + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits |= KDP_LOG_ALL; + else if (::strcasecmp(arg, "async") == 0) + flag_bits |= KDP_LOG_ASYNC; + else if (::strncasecmp(arg, "break", 5) == 0) + flag_bits |= KDP_LOG_BREAKPOINTS; + else if (::strncasecmp(arg, "comm", 4) == 0) + flag_bits |= KDP_LOG_COMM; + else if (::strcasecmp(arg, "default") == 0) + flag_bits |= KDP_LOG_DEFAULT; + else if (::strcasecmp(arg, "packets") == 0) + flag_bits |= KDP_LOG_PACKETS; + else if (::strcasecmp(arg, "memory") == 0) + flag_bits |= KDP_LOG_MEMORY; + else if (::strcasecmp(arg, "data-short") == 0) + flag_bits |= KDP_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp(arg, "data-long") == 0) + flag_bits |= KDP_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp(arg, "process") == 0) + flag_bits |= KDP_LOG_PROCESS; + else if (::strcasecmp(arg, "step") == 0) + flag_bits |= KDP_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + flag_bits |= KDP_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + flag_bits |= KDP_LOG_VERBOSE; + else if (::strncasecmp(arg, "watch", 5) == 0) + flag_bits |= KDP_LOG_WATCHPOINTS; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListLogCategories(feedback_strm); } - if (flag_bits == 0) - flag_bits = KDP_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); + } } - g_log_enabled = true; - return g_log; + if (flag_bits == 0) + flag_bits = KDP_LOG_DEFAULT; + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + } + g_log_enabled = true; + return g_log; } -void -ProcessKDPLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", - ProcessKDP::GetPluginNameStatic().GetCString()); +void ProcessKDPLog::ListLogCategories(Stream *strm) { + strm->Printf( + "Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " async - log asynchronous activity\n" + " break - log breakpoints\n" + " communication - log communication activity\n" + " default - enable the default set of logging categories for liblldb\n" + " packets - log gdb remote packets\n" + " memory - log memory reads and writes\n" + " data-short - log memory bytes for memory reads and writes for short " + "transactions only\n" + " data-long - log memory bytes for memory reads and writes for all " + "transactions\n" + " process - log process events and activities\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n", + ProcessKDP::GetPluginNameStatic().GetCString()); } - -void -ProcessKDPLog::LogIf (uint32_t mask, const char *format, ...) -{ - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } +void ProcessKDPLog::LogIf(uint32_t mask, const char *format, ...) { + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(mask)); + if (log) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h index 0cb32d9b2dc..703c775268d 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h @@ -17,38 +17,37 @@ // Project includes #include "lldb/Core/Log.h" -#define KDP_LOG_VERBOSE (1u << 0) -#define KDP_LOG_PROCESS (1u << 1) -#define KDP_LOG_THREAD (1u << 2) -#define KDP_LOG_PACKETS (1u << 3) -#define KDP_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define KDP_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define KDP_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define KDP_LOG_BREAKPOINTS (1u << 7) -#define KDP_LOG_WATCHPOINTS (1u << 8) -#define KDP_LOG_STEP (1u << 9) -#define KDP_LOG_COMM (1u << 10) -#define KDP_LOG_ASYNC (1u << 11) -#define KDP_LOG_ALL (UINT32_MAX) -#define KDP_LOG_DEFAULT KDP_LOG_PACKETS - -class ProcessKDPLog -{ +#define KDP_LOG_VERBOSE (1u << 0) +#define KDP_LOG_PROCESS (1u << 1) +#define KDP_LOG_THREAD (1u << 2) +#define KDP_LOG_PACKETS (1u << 3) +#define KDP_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define KDP_LOG_MEMORY_DATA_SHORT \ + (1u << 5) // Log short memory reads/writes bytes +#define KDP_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes +#define KDP_LOG_BREAKPOINTS (1u << 7) +#define KDP_LOG_WATCHPOINTS (1u << 8) +#define KDP_LOG_STEP (1u << 9) +#define KDP_LOG_COMM (1u << 10) +#define KDP_LOG_ASYNC (1u << 11) +#define KDP_LOG_ALL (UINT32_MAX) +#define KDP_LOG_DEFAULT KDP_LOG_PACKETS + +class ProcessKDPLog { public: - static lldb_private::Log * - GetLogIfAllCategoriesSet(uint32_t mask = 0); + static lldb_private::Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); - static void - DisableLog (const char **categories, lldb_private::Stream *feedback_strm); + static void DisableLog(const char **categories, + lldb_private::Stream *feedback_strm); - static lldb_private::Log * - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, lldb_private::Stream *feedback_strm); + static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, + uint32_t log_options, + const char **categories, + lldb_private::Stream *feedback_strm); - static void - ListLogCategories (lldb_private::Stream *strm); + static void ListLogCategories(lldb_private::Stream *strm); - static void - LogIf (uint32_t mask, const char *format, ...); + static void LogIf(uint32_t mask, const char *format, ...); }; -#endif // liblldb_ProcessKDPLog_h_ +#endif // liblldb_ProcessKDPLog_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp index 449ac646ab3..06c33dba857 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp @@ -19,143 +19,133 @@ using namespace lldb; using namespace lldb_private; - -RegisterContextKDP_arm::RegisterContextKDP_arm (ThreadKDP &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_arm (thread, concrete_frame_idx), - m_kdp_thread (thread) -{ -} - -RegisterContextKDP_arm::~RegisterContextKDP_arm() -{ -} - -int -RegisterContextKDP_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +RegisterContextKDP_arm::RegisterContextKDP_arm(ThreadKDP &thread, + uint32_t concrete_frame_idx) + : RegisterContextDarwin_arm(thread, concrete_frame_idx), + m_kdp_thread(thread) {} + +RegisterContextKDP_arm::~RegisterContextKDP_arm() {} + +int RegisterContextKDP_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm::DoWriteDBG(lldb::tid_t tid, int flavor, + const DBG &dbg) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } - - diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h index 1e547289d9c..fe02b064822 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h @@ -19,43 +19,30 @@ class ThreadKDP; -class RegisterContextKDP_arm : public RegisterContextDarwin_arm -{ +class RegisterContextKDP_arm : public RegisterContextDarwin_arm { public: + RegisterContextKDP_arm(ThreadKDP &thread, uint32_t concrete_frame_idx); - RegisterContextKDP_arm (ThreadKDP &thread, - uint32_t concrete_frame_idx); - - virtual - ~RegisterContextKDP_arm(); + virtual ~RegisterContextKDP_arm(); protected: + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); + + int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); - - int - DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg); - - ThreadKDP &m_kdp_thread; + ThreadKDP &m_kdp_thread; }; -#endif // liblldb_RegisterContextKDP_arm_h_ +#endif // liblldb_RegisterContextKDP_arm_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp index ed62f1982d3..6a2733e6275 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextKDP_arm64.cpp ------------------------------*- C++ -*-===// +//===-- RegisterContextKDP_arm64.cpp ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -19,143 +20,133 @@ using namespace lldb; using namespace lldb_private; - -RegisterContextKDP_arm64::RegisterContextKDP_arm64 (ThreadKDP &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_arm64 (thread, concrete_frame_idx), - m_kdp_thread (thread) -{ -} - -RegisterContextKDP_arm64::~RegisterContextKDP_arm64() -{ -} - -int -RegisterContextKDP_arm64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +RegisterContextKDP_arm64::RegisterContextKDP_arm64(ThreadKDP &thread, + uint32_t concrete_frame_idx) + : RegisterContextDarwin_arm64(thread, concrete_frame_idx), + m_kdp_thread(thread) {} + +RegisterContextKDP_arm64::~RegisterContextKDP_arm64() {} + +int RegisterContextKDP_arm64::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_arm64::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_arm64::DoWriteDBG(lldb::tid_t tid, int flavor, + const DBG &dbg) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } - - diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h index 8780b7be4a9..0922654de2c 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h @@ -1,4 +1,5 @@ -//===-- RegisterContextKDP_arm64.h --------------------------------*- C++ -*-===// +//===-- RegisterContextKDP_arm64.h --------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -19,43 +20,30 @@ class ThreadKDP; -class RegisterContextKDP_arm64 : public RegisterContextDarwin_arm64 -{ +class RegisterContextKDP_arm64 : public RegisterContextDarwin_arm64 { public: + RegisterContextKDP_arm64(ThreadKDP &thread, uint32_t concrete_frame_idx); - RegisterContextKDP_arm64 (ThreadKDP &thread, - uint32_t concrete_frame_idx); - - virtual - ~RegisterContextKDP_arm64(); + virtual ~RegisterContextKDP_arm64(); protected: + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); + + int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); - - int - DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg); - - ThreadKDP &m_kdp_thread; + ThreadKDP &m_kdp_thread; }; -#endif // liblldb_RegisterContextKDP_arm64_h_ +#endif // liblldb_RegisterContextKDP_arm64_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp index 882b0c2e931..4a130c18d07 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes // Other libraries and framework includes @@ -19,111 +18,102 @@ using namespace lldb; using namespace lldb_private; +RegisterContextKDP_i386::RegisterContextKDP_i386(ThreadKDP &thread, + uint32_t concrete_frame_idx) + : RegisterContextDarwin_i386(thread, concrete_frame_idx), + m_kdp_thread(thread) {} -RegisterContextKDP_i386::RegisterContextKDP_i386 (ThreadKDP &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_i386 (thread, concrete_frame_idx), - m_kdp_thread (thread) -{ -} - -RegisterContextKDP_i386::~RegisterContextKDP_i386() -{ -} +RegisterContextKDP_i386::~RegisterContextKDP_i386() {} -int -RegisterContextKDP_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_i386::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } - - diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h index 4b6bc5b262f..5803670a08b 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h @@ -18,36 +18,26 @@ class ThreadKDP; -class RegisterContextKDP_i386 : public RegisterContextDarwin_i386 -{ +class RegisterContextKDP_i386 : public RegisterContextDarwin_i386 { public: - RegisterContextKDP_i386 (ThreadKDP &thread, - uint32_t concrete_frame_idx); - - virtual - ~RegisterContextKDP_i386(); - + RegisterContextKDP_i386(ThreadKDP &thread, uint32_t concrete_frame_idx); + + virtual ~RegisterContextKDP_i386(); + protected: - - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); - - ThreadKDP &m_kdp_thread; + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); + + ThreadKDP &m_kdp_thread; }; -#endif // liblldb_RegisterContextKDP_i386_h_ +#endif // liblldb_RegisterContextKDP_i386_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp index f4247a5da27..ad10d3f6be5 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes // Other libraries and framework includes @@ -19,109 +18,105 @@ using namespace lldb; using namespace lldb_private; +RegisterContextKDP_x86_64::RegisterContextKDP_x86_64( + ThreadKDP &thread, uint32_t concrete_frame_idx) + : RegisterContextDarwin_x86_64(thread, concrete_frame_idx), + m_kdp_thread(thread) {} -RegisterContextKDP_x86_64::RegisterContextKDP_x86_64 (ThreadKDP &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_x86_64 (thread, concrete_frame_idx), - m_kdp_thread (thread) -{ -} - -RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64() -{ -} +RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64() {} -int -RegisterContextKDP_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoReadGPR(lldb::tid_t tid, int flavor, + GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoReadFPU(lldb::tid_t tid, int flavor, + FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoReadEXC(lldb::tid_t tid, int flavor, + EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } -int -RegisterContextKDP_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error)) - { - if (error.Success()) - return 0; - } +int RegisterContextKDP_x86_64::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), + error)) { + if (error.Success()) + return 0; } - return -1; + } + return -1; } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h index a426349198f..7a40bb62638 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h @@ -18,37 +18,26 @@ class ThreadKDP; -class RegisterContextKDP_x86_64 : public RegisterContextDarwin_x86_64 -{ +class RegisterContextKDP_x86_64 : public RegisterContextDarwin_x86_64 { public: - - RegisterContextKDP_x86_64 (ThreadKDP &thread, - uint32_t concrete_frame_idx); - - virtual - ~RegisterContextKDP_x86_64(); - + RegisterContextKDP_x86_64(ThreadKDP &thread, uint32_t concrete_frame_idx); + + virtual ~RegisterContextKDP_x86_64(); + protected: - - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); - - ThreadKDP &m_kdp_thread; + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); + + ThreadKDP &m_kdp_thread; }; -#endif // liblldb_RegisterContextKDP_x86_64_h_ +#endif // liblldb_RegisterContextKDP_x86_64_h_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index 3b8bed101a8..273e1966f3f 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -7,29 +7,28 @@ // //===----------------------------------------------------------------------===// - #include "ThreadKDP.h" #include "lldb/Utility/SafeMachO.h" +#include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataExtractor.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/State.h" +#include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" -#include "lldb/Breakpoint/Watchpoint.h" +#include "Plugins/Process/Utility/StopInfoMachException.h" #include "ProcessKDP.h" #include "ProcessKDPLog.h" #include "RegisterContextKDP_arm.h" #include "RegisterContextKDP_arm64.h" #include "RegisterContextKDP_i386.h" #include "RegisterContextKDP_x86_64.h" -#include "Plugins/Process/Utility/StopInfoMachException.h" using namespace lldb; using namespace lldb_private; @@ -38,174 +37,137 @@ using namespace lldb_private; // Thread Registers //---------------------------------------------------------------------- -ThreadKDP::ThreadKDP (Process &process, lldb::tid_t tid) : - Thread(process, tid), - m_thread_name (), - m_dispatch_queue_name (), - m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS) -{ - ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::ThreadKDP (tid = 0x%4.4x)", this, GetID()); -} - -ThreadKDP::~ThreadKDP () -{ - ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::~ThreadKDP (tid = 0x%4.4x)", this, GetID()); - DestroyThread(); +ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid) + : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), + m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) { + ProcessKDPLog::LogIf(KDP_LOG_THREAD, + "%p: ThreadKDP::ThreadKDP (tid = 0x%4.4x)", this, + GetID()); } -const char * -ThreadKDP::GetName () -{ - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); +ThreadKDP::~ThreadKDP() { + ProcessKDPLog::LogIf(KDP_LOG_THREAD, + "%p: ThreadKDP::~ThreadKDP (tid = 0x%4.4x)", this, + GetID()); + DestroyThread(); } -const char * -ThreadKDP::GetQueueName () -{ +const char *ThreadKDP::GetName() { + if (m_thread_name.empty()) return NULL; + return m_thread_name.c_str(); } -void -ThreadKDP::RefreshStateAfterStop() -{ - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do - // the right thing. - const bool force = false; - lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext()); - if (reg_ctx_sp) - reg_ctx_sp->InvalidateIfNeeded (force); +const char *ThreadKDP::GetQueueName() { return NULL; } + +void ThreadKDP::RefreshStateAfterStop() { + // Invalidate all registers in our register context. We don't set "force" to + // true because the stop reply packet might have had some register values + // that were expedited and these will already be copied into the register + // context by the time this function gets called. The KDPRegisterContext + // class has been made smart enough to detect when it needs to invalidate + // which registers are valid by putting hooks in the register read and + // register supply functions where they check the process stop ID and do + // the right thing. + const bool force = false; + lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); + if (reg_ctx_sp) + reg_ctx_sp->InvalidateIfNeeded(force); } -bool -ThreadKDP::ThreadIDIsValid (lldb::tid_t thread) -{ - return thread != 0; -} - -void -ThreadKDP::Dump(Log *log, uint32_t index) -{ -} +bool ThreadKDP::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } +void ThreadKDP::Dump(Log *log, uint32_t index) {} -bool -ThreadKDP::ShouldStop (bool &step_more) -{ - return true; -} -lldb::RegisterContextSP -ThreadKDP::GetRegisterContext () -{ - if (m_reg_context_sp.get() == NULL) - m_reg_context_sp = CreateRegisterContextForFrame (NULL); - return m_reg_context_sp; +bool ThreadKDP::ShouldStop(bool &step_more) { return true; } +lldb::RegisterContextSP ThreadKDP::GetRegisterContext() { + if (m_reg_context_sp.get() == NULL) + m_reg_context_sp = CreateRegisterContextForFrame(NULL); + return m_reg_context_sp; } lldb::RegisterContextSP -ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex (); - - if (concrete_frame_idx == 0) - { - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - switch (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().GetCPUType()) - { - case llvm::MachO::CPU_TYPE_ARM: - reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_ARM64: - reg_ctx_sp.reset (new RegisterContextKDP_arm64 (*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_I386: - reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_X86_64: - reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx)); - break; - default: - assert (!"Add CPU type support in KDP"); - break; - } - } - } - else - { - Unwind *unwinder = GetUnwinder (); - if (unwinder) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame); +ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + switch (static_cast<ProcessKDP *>(process_sp.get()) + ->GetCommunication() + .GetCPUType()) { + case llvm::MachO::CPU_TYPE_ARM: + reg_ctx_sp.reset(new RegisterContextKDP_arm(*this, concrete_frame_idx)); + break; + case llvm::MachO::CPU_TYPE_ARM64: + reg_ctx_sp.reset( + new RegisterContextKDP_arm64(*this, concrete_frame_idx)); + break; + case llvm::MachO::CPU_TYPE_I386: + reg_ctx_sp.reset( + new RegisterContextKDP_i386(*this, concrete_frame_idx)); + break; + case llvm::MachO::CPU_TYPE_X86_64: + reg_ctx_sp.reset( + new RegisterContextKDP_x86_64(*this, concrete_frame_idx)); + break; + default: + assert(!"Add CPU type support in KDP"); + break; + } } - return reg_ctx_sp; + } else { + Unwind *unwinder = GetUnwinder(); + if (unwinder) + reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; } -bool -ThreadKDP::CalculateStopInfo () -{ - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - if (m_cached_stop_info_sp) - { - SetStopInfo (m_cached_stop_info_sp); - } - else - { - SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP)); - } - return true; +bool ThreadKDP::CalculateStopInfo() { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + if (m_cached_stop_info_sp) { + SetStopInfo(m_cached_stop_info_sp); + } else { + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP)); } - return false; + return true; + } + return false; } -void -ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet) -{ - lldb::offset_t offset = 0; - uint8_t reply_command = exc_reply_packet.GetU8(&offset); - if (reply_command == CommunicationKDP::KDP_EXCEPTION) - { - offset = 8; - const uint32_t count = exc_reply_packet.GetU32 (&offset); - if (count >= 1) - { - //const uint32_t cpu = exc_reply_packet.GetU32 (&offset); - offset += 4; // Skip the useless CPU field - const uint32_t exc_type = exc_reply_packet.GetU32 (&offset); - const uint32_t exc_code = exc_reply_packet.GetU32 (&offset); - const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset); - // We have to make a copy of the stop info because the thread list - // will iterate through the threads and clear all stop infos.. - - // Let the StopInfoMachException::CreateStopReasonWithMachException() - // function update the PC if needed as we might hit a software breakpoint - // and need to decrement the PC (i386 and x86_64 need this) and KDP - // doesn't do this for us. - const bool pc_already_adjusted = false; - const bool adjust_pc_if_needed = true; - - m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this, - exc_type, - 2, - exc_code, - exc_subcode, - 0, - pc_already_adjusted, - adjust_pc_if_needed); - } +void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION( + const DataExtractor &exc_reply_packet) { + lldb::offset_t offset = 0; + uint8_t reply_command = exc_reply_packet.GetU8(&offset); + if (reply_command == CommunicationKDP::KDP_EXCEPTION) { + offset = 8; + const uint32_t count = exc_reply_packet.GetU32(&offset); + if (count >= 1) { + // const uint32_t cpu = exc_reply_packet.GetU32 (&offset); + offset += 4; // Skip the useless CPU field + const uint32_t exc_type = exc_reply_packet.GetU32(&offset); + const uint32_t exc_code = exc_reply_packet.GetU32(&offset); + const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset); + // We have to make a copy of the stop info because the thread list + // will iterate through the threads and clear all stop infos.. + + // Let the StopInfoMachException::CreateStopReasonWithMachException() + // function update the PC if needed as we might hit a software breakpoint + // and need to decrement the PC (i386 and x86_64 need this) and KDP + // doesn't do this for us. + const bool pc_already_adjusted = false; + const bool adjust_pc_if_needed = true; + + m_cached_stop_info_sp = + StopInfoMachException::CreateStopReasonWithMachException( + *this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted, + adjust_pc_if_needed); } + } } - diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h index 7dc373f0355..ea517b4254f 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h @@ -17,82 +17,61 @@ class ProcessKDP; -class ThreadKDP : public lldb_private::Thread -{ +class ThreadKDP : public lldb_private::Thread { public: - ThreadKDP (lldb_private::Process &process, - lldb::tid_t tid); + ThreadKDP(lldb_private::Process &process, lldb::tid_t tid); - virtual - ~ThreadKDP (); + virtual ~ThreadKDP(); - virtual void - RefreshStateAfterStop(); + virtual void RefreshStateAfterStop(); - virtual const char * - GetName (); + virtual const char *GetName(); - virtual const char * - GetQueueName (); + virtual const char *GetQueueName(); - virtual lldb::RegisterContextSP - GetRegisterContext (); + virtual lldb::RegisterContextSP GetRegisterContext(); - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); + virtual lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame); - void - Dump (lldb_private::Log *log, uint32_t index); + void Dump(lldb_private::Log *log, uint32_t index); - static bool - ThreadIDIsValid (lldb::tid_t thread); + static bool ThreadIDIsValid(lldb::tid_t thread); - bool - ShouldStop (bool &step_more); + bool ShouldStop(bool &step_more); - const char * - GetBasicInfoAsString (); + const char *GetBasicInfoAsString(); - void - SetName (const char *name) - { - if (name && name[0]) - m_thread_name.assign (name); - else - m_thread_name.clear(); - } + void SetName(const char *name) { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } - lldb::addr_t - GetThreadDispatchQAddr () - { - return m_thread_dispatch_qaddr; - } + lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; } - void - SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr) - { - m_thread_dispatch_qaddr = thread_dispatch_qaddr; - } - - void - SetStopInfoFrom_KDP_EXCEPTION (const lldb_private::DataExtractor &exc_reply_packet); + void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) { + m_thread_dispatch_qaddr = thread_dispatch_qaddr; + } + + void SetStopInfoFrom_KDP_EXCEPTION( + const lldb_private::DataExtractor &exc_reply_packet); protected: - - friend class ProcessKDP; - - //------------------------------------------------------------------ - // Member variables. - //------------------------------------------------------------------ - std::string m_thread_name; - std::string m_dispatch_queue_name; - lldb::addr_t m_thread_dispatch_qaddr; - lldb::StopInfoSP m_cached_stop_info_sp; - //------------------------------------------------------------------ - // Protected member functions. - //------------------------------------------------------------------ - virtual bool - CalculateStopInfo (); + friend class ProcessKDP; + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + std::string m_thread_name; + std::string m_dispatch_queue_name; + lldb::addr_t m_thread_dispatch_qaddr; + lldb::StopInfoSP m_cached_stop_info_sp; + //------------------------------------------------------------------ + // Protected member functions. + //------------------------------------------------------------------ + virtual bool CalculateStopInfo(); }; -#endif // liblldb_ThreadKDP_h_ +#endif // liblldb_ThreadKDP_h_ diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp index 44409a4ce55..c567b4a9655 100644 --- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp @@ -13,304 +13,281 @@ namespace { -void -AppendFaultAddr (std::string& str, lldb::addr_t addr) -{ - std::stringstream ss; - ss << " (fault address: 0x" << std::hex << addr << ")"; - str += ss.str(); +void AppendFaultAddr(std::string &str, lldb::addr_t addr) { + std::stringstream ss; + ss << " (fault address: 0x" << std::hex << addr << ")"; + str += ss.str(); } -CrashReason -GetCrashReasonForSIGSEGV(const siginfo_t& info) -{ - assert(info.si_signo == SIGSEGV); +CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) { + assert(info.si_signo == SIGSEGV); - switch (info.si_code) - { + switch (info.si_code) { #ifdef SI_KERNEL - case SI_KERNEL: - // Some platforms will occasionally send nonstandard spurious SI_KERNEL codes. - // One way to get this is via unaligned SIMD loads. - return CrashReason::eInvalidAddress; // for lack of anything better + case SI_KERNEL: + // Some platforms will occasionally send nonstandard spurious SI_KERNEL + // codes. + // One way to get this is via unaligned SIMD loads. + return CrashReason::eInvalidAddress; // for lack of anything better #endif - case SEGV_MAPERR: - return CrashReason::eInvalidAddress; - case SEGV_ACCERR: - return CrashReason::ePrivilegedAddress; - } + case SEGV_MAPERR: + return CrashReason::eInvalidAddress; + case SEGV_ACCERR: + return CrashReason::ePrivilegedAddress; + } - assert(false && "unexpected si_code for SIGSEGV"); - return CrashReason::eInvalidCrashReason; + assert(false && "unexpected si_code for SIGSEGV"); + return CrashReason::eInvalidCrashReason; } -CrashReason -GetCrashReasonForSIGILL(const siginfo_t& info) -{ - assert(info.si_signo == SIGILL); +CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) { + assert(info.si_signo == SIGILL); - switch (info.si_code) - { - case ILL_ILLOPC: - return CrashReason::eIllegalOpcode; - case ILL_ILLOPN: - return CrashReason::eIllegalOperand; - case ILL_ILLADR: - return CrashReason::eIllegalAddressingMode; - case ILL_ILLTRP: - return CrashReason::eIllegalTrap; - case ILL_PRVOPC: - return CrashReason::ePrivilegedOpcode; - case ILL_PRVREG: - return CrashReason::ePrivilegedRegister; - case ILL_COPROC: - return CrashReason::eCoprocessorError; - case ILL_BADSTK: - return CrashReason::eInternalStackError; - } + switch (info.si_code) { + case ILL_ILLOPC: + return CrashReason::eIllegalOpcode; + case ILL_ILLOPN: + return CrashReason::eIllegalOperand; + case ILL_ILLADR: + return CrashReason::eIllegalAddressingMode; + case ILL_ILLTRP: + return CrashReason::eIllegalTrap; + case ILL_PRVOPC: + return CrashReason::ePrivilegedOpcode; + case ILL_PRVREG: + return CrashReason::ePrivilegedRegister; + case ILL_COPROC: + return CrashReason::eCoprocessorError; + case ILL_BADSTK: + return CrashReason::eInternalStackError; + } - assert(false && "unexpected si_code for SIGILL"); - return CrashReason::eInvalidCrashReason; + assert(false && "unexpected si_code for SIGILL"); + return CrashReason::eInvalidCrashReason; } -CrashReason -GetCrashReasonForSIGFPE(const siginfo_t& info) -{ - assert(info.si_signo == SIGFPE); +CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) { + assert(info.si_signo == SIGFPE); - switch (info.si_code) - { - case FPE_INTDIV: - return CrashReason::eIntegerDivideByZero; - case FPE_INTOVF: - return CrashReason::eIntegerOverflow; - case FPE_FLTDIV: - return CrashReason::eFloatDivideByZero; - case FPE_FLTOVF: - return CrashReason::eFloatOverflow; - case FPE_FLTUND: - return CrashReason::eFloatUnderflow; - case FPE_FLTRES: - return CrashReason::eFloatInexactResult; - case FPE_FLTINV: - return CrashReason::eFloatInvalidOperation; - case FPE_FLTSUB: - return CrashReason::eFloatSubscriptRange; - } + switch (info.si_code) { + case FPE_INTDIV: + return CrashReason::eIntegerDivideByZero; + case FPE_INTOVF: + return CrashReason::eIntegerOverflow; + case FPE_FLTDIV: + return CrashReason::eFloatDivideByZero; + case FPE_FLTOVF: + return CrashReason::eFloatOverflow; + case FPE_FLTUND: + return CrashReason::eFloatUnderflow; + case FPE_FLTRES: + return CrashReason::eFloatInexactResult; + case FPE_FLTINV: + return CrashReason::eFloatInvalidOperation; + case FPE_FLTSUB: + return CrashReason::eFloatSubscriptRange; + } - assert(false && "unexpected si_code for SIGFPE"); - return CrashReason::eInvalidCrashReason; + assert(false && "unexpected si_code for SIGFPE"); + return CrashReason::eInvalidCrashReason; } -CrashReason -GetCrashReasonForSIGBUS(const siginfo_t& info) -{ - assert(info.si_signo == SIGBUS); +CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) { + assert(info.si_signo == SIGBUS); - switch (info.si_code) - { - case BUS_ADRALN: - return CrashReason::eIllegalAlignment; - case BUS_ADRERR: - return CrashReason::eIllegalAddress; - case BUS_OBJERR: - return CrashReason::eHardwareError; - } + switch (info.si_code) { + case BUS_ADRALN: + return CrashReason::eIllegalAlignment; + case BUS_ADRERR: + return CrashReason::eIllegalAddress; + case BUS_OBJERR: + return CrashReason::eHardwareError; + } - assert(false && "unexpected si_code for SIGBUS"); - return CrashReason::eInvalidCrashReason; + assert(false && "unexpected si_code for SIGBUS"); + return CrashReason::eInvalidCrashReason; } - } -std::string -GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr) -{ - std::string str; +std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { + std::string str; - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; + switch (reason) { + default: + assert(false && "invalid CrashReason"); + break; - case CrashReason::eInvalidAddress: - str = "signal SIGSEGV: invalid address"; - AppendFaultAddr (str, fault_addr); - break; - case CrashReason::ePrivilegedAddress: - str = "signal SIGSEGV: address access protected"; - AppendFaultAddr (str, fault_addr); - break; - case CrashReason::eIllegalOpcode: - str = "signal SIGILL: illegal instruction"; - break; - case CrashReason::eIllegalOperand: - str = "signal SIGILL: illegal instruction operand"; - break; - case CrashReason::eIllegalAddressingMode: - str = "signal SIGILL: illegal addressing mode"; - break; - case CrashReason::eIllegalTrap: - str = "signal SIGILL: illegal trap"; - break; - case CrashReason::ePrivilegedOpcode: - str = "signal SIGILL: privileged instruction"; - break; - case CrashReason::ePrivilegedRegister: - str = "signal SIGILL: privileged register"; - break; - case CrashReason::eCoprocessorError: - str = "signal SIGILL: coprocessor error"; - break; - case CrashReason::eInternalStackError: - str = "signal SIGILL: internal stack error"; - break; - case CrashReason::eIllegalAlignment: - str = "signal SIGBUS: illegal alignment"; - break; - case CrashReason::eIllegalAddress: - str = "signal SIGBUS: illegal address"; - break; - case CrashReason::eHardwareError: - str = "signal SIGBUS: hardware error"; - break; - case CrashReason::eIntegerDivideByZero: - str = "signal SIGFPE: integer divide by zero"; - break; - case CrashReason::eIntegerOverflow: - str = "signal SIGFPE: integer overflow"; - break; - case CrashReason::eFloatDivideByZero: - str = "signal SIGFPE: floating point divide by zero"; - break; - case CrashReason::eFloatOverflow: - str = "signal SIGFPE: floating point overflow"; - break; - case CrashReason::eFloatUnderflow: - str = "signal SIGFPE: floating point underflow"; - break; - case CrashReason::eFloatInexactResult: - str = "signal SIGFPE: inexact floating point result"; - break; - case CrashReason::eFloatInvalidOperation: - str = "signal SIGFPE: invalid floating point operation"; - break; - case CrashReason::eFloatSubscriptRange: - str = "signal SIGFPE: invalid floating point subscript range"; - break; - } + case CrashReason::eInvalidAddress: + str = "signal SIGSEGV: invalid address"; + AppendFaultAddr(str, fault_addr); + break; + case CrashReason::ePrivilegedAddress: + str = "signal SIGSEGV: address access protected"; + AppendFaultAddr(str, fault_addr); + break; + case CrashReason::eIllegalOpcode: + str = "signal SIGILL: illegal instruction"; + break; + case CrashReason::eIllegalOperand: + str = "signal SIGILL: illegal instruction operand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "signal SIGILL: illegal addressing mode"; + break; + case CrashReason::eIllegalTrap: + str = "signal SIGILL: illegal trap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "signal SIGILL: privileged instruction"; + break; + case CrashReason::ePrivilegedRegister: + str = "signal SIGILL: privileged register"; + break; + case CrashReason::eCoprocessorError: + str = "signal SIGILL: coprocessor error"; + break; + case CrashReason::eInternalStackError: + str = "signal SIGILL: internal stack error"; + break; + case CrashReason::eIllegalAlignment: + str = "signal SIGBUS: illegal alignment"; + break; + case CrashReason::eIllegalAddress: + str = "signal SIGBUS: illegal address"; + break; + case CrashReason::eHardwareError: + str = "signal SIGBUS: hardware error"; + break; + case CrashReason::eIntegerDivideByZero: + str = "signal SIGFPE: integer divide by zero"; + break; + case CrashReason::eIntegerOverflow: + str = "signal SIGFPE: integer overflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "signal SIGFPE: floating point divide by zero"; + break; + case CrashReason::eFloatOverflow: + str = "signal SIGFPE: floating point overflow"; + break; + case CrashReason::eFloatUnderflow: + str = "signal SIGFPE: floating point underflow"; + break; + case CrashReason::eFloatInexactResult: + str = "signal SIGFPE: inexact floating point result"; + break; + case CrashReason::eFloatInvalidOperation: + str = "signal SIGFPE: invalid floating point operation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "signal SIGFPE: invalid floating point subscript range"; + break; + } - return str; + return str; } -const char * -CrashReasonAsString (CrashReason reason) -{ +const char *CrashReasonAsString(CrashReason reason) { #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); + // Just return the code in ascii for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); #else - const char *str = nullptr; + const char *str = nullptr; - switch (reason) - { - case CrashReason::eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; + switch (reason) { + case CrashReason::eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; - // SIGSEGV crash reasons. - case CrashReason::eInvalidAddress: - str = "eInvalidAddress"; - break; - case CrashReason::ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; + // SIGSEGV crash reasons. + case CrashReason::eInvalidAddress: + str = "eInvalidAddress"; + break; + case CrashReason::ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; - // SIGILL crash reasons. - case CrashReason::eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case CrashReason::eIllegalOperand: - str = "eIllegalOperand"; - break; - case CrashReason::eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case CrashReason::eIllegalTrap: - str = "eIllegalTrap"; - break; - case CrashReason::ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case CrashReason::ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case CrashReason::eCoprocessorError: - str = "eCoprocessorError"; - break; - case CrashReason::eInternalStackError: - str = "eInternalStackError"; - break; + // SIGILL crash reasons. + case CrashReason::eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case CrashReason::eIllegalOperand: + str = "eIllegalOperand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case CrashReason::eIllegalTrap: + str = "eIllegalTrap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case CrashReason::ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case CrashReason::eCoprocessorError: + str = "eCoprocessorError"; + break; + case CrashReason::eInternalStackError: + str = "eInternalStackError"; + break; - // SIGBUS crash reasons: - case CrashReason::eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case CrashReason::eIllegalAddress: - str = "eIllegalAddress"; - break; - case CrashReason::eHardwareError: - str = "eHardwareError"; - break; + // SIGBUS crash reasons: + case CrashReason::eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case CrashReason::eIllegalAddress: + str = "eIllegalAddress"; + break; + case CrashReason::eHardwareError: + str = "eHardwareError"; + break; - // SIGFPE crash reasons: - case CrashReason::eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case CrashReason::eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case CrashReason::eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case CrashReason::eFloatOverflow: - str = "eFloatOverflow"; - break; - case CrashReason::eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case CrashReason::eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case CrashReason::eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case CrashReason::eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } + // SIGFPE crash reasons: + case CrashReason::eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case CrashReason::eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case CrashReason::eFloatOverflow: + str = "eFloatOverflow"; + break; + case CrashReason::eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case CrashReason::eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case CrashReason::eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } #endif - return str; + return str; } -CrashReason -GetCrashReason(const siginfo_t& info) -{ - switch(info.si_signo) - { - case SIGSEGV: - return GetCrashReasonForSIGSEGV(info); - case SIGBUS: - return GetCrashReasonForSIGBUS(info); - case SIGFPE: - return GetCrashReasonForSIGFPE(info); - case SIGILL: - return GetCrashReasonForSIGILL(info); - } +CrashReason GetCrashReason(const siginfo_t &info) { + switch (info.si_signo) { + case SIGSEGV: + return GetCrashReasonForSIGSEGV(info); + case SIGBUS: + return GetCrashReasonForSIGBUS(info); + case SIGFPE: + return GetCrashReasonForSIGFPE(info); + case SIGILL: + return GetCrashReasonForSIGILL(info); + } - assert(false && "unexpected signal"); - return CrashReason::eInvalidCrashReason; + assert(false && "unexpected signal"); + return CrashReason::eInvalidCrashReason; } diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.h b/lldb/source/Plugins/Process/POSIX/CrashReason.h index f6d9ba553e4..1ef3e1a6998 100644 --- a/lldb/source/Plugins/Process/POSIX/CrashReason.h +++ b/lldb/source/Plugins/Process/POSIX/CrashReason.h @@ -16,47 +16,43 @@ #include <string> -enum class CrashReason -{ - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange +enum class CrashReason { + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange }; -std::string -GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr); +std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr); -const char * -CrashReasonAsString (CrashReason reason); +const char *CrashReasonAsString(CrashReason reason); -CrashReason -GetCrashReason(const siginfo_t& info); +CrashReason GetCrashReason(const siginfo_t &info); #endif // #ifndef liblldb_CrashReason_H_ diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp index 02049a2af95..48f2a7844cf 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -11,68 +11,59 @@ using namespace lldb_private; -const char * -ProcessMessage::PrintCrashReason() const -{ - return CrashReasonAsString(m_crash_reason); +const char *ProcessMessage::PrintCrashReason() const { + return CrashReasonAsString(m_crash_reason); } -const char * -ProcessMessage::PrintKind(Kind kind) -{ +const char *ProcessMessage::PrintKind(Kind kind) { #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); + // Just return the code in ascii for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); #else - const char *str = NULL; + const char *str = NULL; - switch (kind) - { - case eInvalidMessage: - str = "eInvalidMessage"; - break; - case eAttachMessage: - str = "eAttachMessage"; - break; - case eExitMessage: - str = "eExitMessage"; - break; - case eLimboMessage: - str = "eLimboMessage"; - break; - case eSignalMessage: - str = "eSignalMessage"; - break; - case eSignalDeliveredMessage: - str = "eSignalDeliveredMessage"; - break; - case eTraceMessage: - str = "eTraceMessage"; - break; - case eBreakpointMessage: - str = "eBreakpointMessage"; - break; - case eWatchpointMessage: - str = "eWatchpointMessage"; - break; - case eCrashMessage: - str = "eCrashMessage"; - break; - case eNewThreadMessage: - str = "eNewThreadMessage"; - break; - case eExecMessage: - str = "eExecMessage"; - break; - } + switch (kind) { + case eInvalidMessage: + str = "eInvalidMessage"; + break; + case eAttachMessage: + str = "eAttachMessage"; + break; + case eExitMessage: + str = "eExitMessage"; + break; + case eLimboMessage: + str = "eLimboMessage"; + break; + case eSignalMessage: + str = "eSignalMessage"; + break; + case eSignalDeliveredMessage: + str = "eSignalDeliveredMessage"; + break; + case eTraceMessage: + str = "eTraceMessage"; + break; + case eBreakpointMessage: + str = "eBreakpointMessage"; + break; + case eWatchpointMessage: + str = "eWatchpointMessage"; + break; + case eCrashMessage: + str = "eCrashMessage"; + break; + case eNewThreadMessage: + str = "eNewThreadMessage"; + break; + case eExecMessage: + str = "eExecMessage"; + break; + } #endif - return str; + return str; } -const char * -ProcessMessage::PrintKind() const -{ - return PrintKind(m_kind); -} +const char *ProcessMessage::PrintKind() const { return PrintKind(m_kind); } diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h index f932e9fff27..3c596ca6854 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h @@ -18,165 +18,152 @@ #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" -class ProcessMessage -{ +class ProcessMessage { public: - - /// The type of signal this message can correspond to. - enum Kind - { - eInvalidMessage, - eAttachMessage, - eExitMessage, - eLimboMessage, - eSignalMessage, - eSignalDeliveredMessage, - eTraceMessage, - eBreakpointMessage, - eWatchpointMessage, - eCrashMessage, - eNewThreadMessage, - eExecMessage - }; - - ProcessMessage() - : m_tid(LLDB_INVALID_PROCESS_ID), - m_kind(eInvalidMessage), - m_crash_reason(CrashReason::eInvalidCrashReason), - m_status(0), - m_addr(0) { } - - Kind GetKind() const { return m_kind; } - - lldb::tid_t GetTID() const { return m_tid; } - - /// Indicates that the process @p pid has successfully attached. - static ProcessMessage Attach(lldb::pid_t pid) { - return ProcessMessage(pid, eAttachMessage); - } - - /// Indicates that the thread @p tid is about to exit with status @p status. - static ProcessMessage Limbo(lldb::tid_t tid, int status) { - return ProcessMessage(tid, eLimboMessage, status); - } - - /// Indicates that the thread @p tid had the signal @p signum delivered. - static ProcessMessage Signal(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalMessage, signum); - } - - /// Indicates that a signal @p signum generated by the debugging process was - /// delivered to the thread @p tid. - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalDeliveredMessage, signum); - } - - /// Indicates that the thread @p tid encountered a trace point. - static ProcessMessage Trace(lldb::tid_t tid) { - return ProcessMessage(tid, eTraceMessage); - } - - /// Indicates that the thread @p tid encountered a break point. - static ProcessMessage Break(lldb::tid_t tid) { - return ProcessMessage(tid, eBreakpointMessage); - } - - static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) { - return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr); - } - - /// Indicates that the thread @p tid crashed. - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, - int signo, lldb::addr_t fault_addr) { - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); - message.m_crash_reason = reason; - return message; - } - - /// Indicates that the thread @p child_tid was spawned. - static ProcessMessage NewThread(lldb::tid_t parent_tid, lldb::tid_t child_tid) { - return ProcessMessage(parent_tid, eNewThreadMessage, child_tid); - } - - /// Indicates that the thread @p tid is about to exit with status @p status. - static ProcessMessage Exit(lldb::tid_t tid, int status) { - return ProcessMessage(tid, eExitMessage, status); - } - - /// Indicates that the thread @p pid has exec'd. - static ProcessMessage Exec(lldb::tid_t tid) { - return ProcessMessage(tid, eExecMessage); - } - - int GetExitStatus() const { - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); - return m_status; - } - - int GetSignal() const { - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || - GetKind() == eSignalDeliveredMessage); - return m_status; - } - - int GetStopStatus() const { - assert(GetKind() == eSignalMessage); - return m_status; - } - - CrashReason GetCrashReason() const { - assert(GetKind() == eCrashMessage); - return m_crash_reason; - } - - lldb::addr_t GetFaultAddress() const { - assert(GetKind() == eCrashMessage); - return m_addr; - } - - lldb::addr_t GetHWAddress() const { - assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage); - return m_addr; - } - - lldb::tid_t GetChildTID() const { - assert(GetKind() == eNewThreadMessage); - return m_child_tid; - } - - const char * - PrintCrashReason() const; - - const char * - PrintKind() const; - - static const char * - PrintKind(Kind); + /// The type of signal this message can correspond to. + enum Kind { + eInvalidMessage, + eAttachMessage, + eExitMessage, + eLimboMessage, + eSignalMessage, + eSignalDeliveredMessage, + eTraceMessage, + eBreakpointMessage, + eWatchpointMessage, + eCrashMessage, + eNewThreadMessage, + eExecMessage + }; + + ProcessMessage() + : m_tid(LLDB_INVALID_PROCESS_ID), m_kind(eInvalidMessage), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), + m_addr(0) {} + + Kind GetKind() const { return m_kind; } + + lldb::tid_t GetTID() const { return m_tid; } + + /// Indicates that the process @p pid has successfully attached. + static ProcessMessage Attach(lldb::pid_t pid) { + return ProcessMessage(pid, eAttachMessage); + } + + /// Indicates that the thread @p tid is about to exit with status @p status. + static ProcessMessage Limbo(lldb::tid_t tid, int status) { + return ProcessMessage(tid, eLimboMessage, status); + } + + /// Indicates that the thread @p tid had the signal @p signum delivered. + static ProcessMessage Signal(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalMessage, signum); + } + + /// Indicates that a signal @p signum generated by the debugging process was + /// delivered to the thread @p tid. + static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalDeliveredMessage, signum); + } + + /// Indicates that the thread @p tid encountered a trace point. + static ProcessMessage Trace(lldb::tid_t tid) { + return ProcessMessage(tid, eTraceMessage); + } + + /// Indicates that the thread @p tid encountered a break point. + static ProcessMessage Break(lldb::tid_t tid) { + return ProcessMessage(tid, eBreakpointMessage); + } + + static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) { + return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr); + } + + /// Indicates that the thread @p tid crashed. + static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, int signo, + lldb::addr_t fault_addr) { + ProcessMessage message(pid, eCrashMessage, signo, fault_addr); + message.m_crash_reason = reason; + return message; + } + + /// Indicates that the thread @p child_tid was spawned. + static ProcessMessage NewThread(lldb::tid_t parent_tid, + lldb::tid_t child_tid) { + return ProcessMessage(parent_tid, eNewThreadMessage, child_tid); + } + + /// Indicates that the thread @p tid is about to exit with status @p status. + static ProcessMessage Exit(lldb::tid_t tid, int status) { + return ProcessMessage(tid, eExitMessage, status); + } + + /// Indicates that the thread @p pid has exec'd. + static ProcessMessage Exec(lldb::tid_t tid) { + return ProcessMessage(tid, eExecMessage); + } + + int GetExitStatus() const { + assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); + return m_status; + } + + int GetSignal() const { + assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || + GetKind() == eSignalDeliveredMessage); + return m_status; + } + + int GetStopStatus() const { + assert(GetKind() == eSignalMessage); + return m_status; + } + + CrashReason GetCrashReason() const { + assert(GetKind() == eCrashMessage); + return m_crash_reason; + } + + lldb::addr_t GetFaultAddress() const { + assert(GetKind() == eCrashMessage); + return m_addr; + } + + lldb::addr_t GetHWAddress() const { + assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage); + return m_addr; + } + + lldb::tid_t GetChildTID() const { + assert(GetKind() == eNewThreadMessage); + return m_child_tid; + } + + const char *PrintCrashReason() const; + + const char *PrintKind() const; + + static const char *PrintKind(Kind); private: - ProcessMessage(lldb::tid_t tid, Kind kind, - int status = 0, lldb::addr_t addr = 0) - : m_tid(tid), - m_kind(kind), - m_crash_reason(CrashReason::eInvalidCrashReason), - m_status(status), - m_addr(addr), - m_child_tid(0) { } - - ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) - : m_tid(tid), - m_kind(kind), - m_crash_reason(CrashReason::eInvalidCrashReason), - m_status(0), - m_addr(0), - m_child_tid(child_tid) { } - - lldb::tid_t m_tid; - Kind m_kind : 8; - CrashReason m_crash_reason; - int m_status; - lldb::addr_t m_addr; - lldb::tid_t m_child_tid; + ProcessMessage(lldb::tid_t tid, Kind kind, int status = 0, + lldb::addr_t addr = 0) + : m_tid(tid), m_kind(kind), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(status), + m_addr(addr), m_child_tid(0) {} + + ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) + : m_tid(tid), m_kind(kind), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), + m_addr(0), m_child_tid(child_tid) {} + + lldb::tid_t m_tid; + Kind m_kind : 8; + CrashReason m_crash_reason; + int m_status; + lldb::addr_t m_addr; + lldb::tid_t m_child_tid; }; #endif // #ifndef liblldb_ProcessMessage_H_ diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp index b259804a3a2..7f07bd568a2 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -1,4 +1,5 @@ -//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// +//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -11,199 +12,185 @@ #include <mutex> -#include "lldb/Interpreter/Args.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" #include "ProcessPOSIXLog.h" using namespace lldb; using namespace lldb_private; - // We want to avoid global constructors where code needs to be run so here we // control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_log_sp the first time this function is +// that will construct the static g_log_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = NULL; -static Log * -GetLog () -{ - if (!g_log_enabled) - return NULL; - return g_log; +static Log *g_log = NULL; +static Log *GetLog() { + if (!g_log_enabled) + return NULL; + return g_log; } -void -ProcessPOSIXLog::Initialize(ConstString name) -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, [name](){ - Log::Callbacks log_callbacks = { - DisableLog, - EnableLog, - ListLogCategories - }; - - Log::RegisterLogChannel (name, log_callbacks); - RegisterPluginName(name); - }); -} +void ProcessPOSIXLog::Initialize(ConstString name) { + static std::once_flag g_once_flag; -Log * -ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; + std::call_once(g_once_flag, [name]() { + Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; + + Log::RegisterLogChannel(name, log_callbacks); + RegisterPluginName(name); + }); } -static uint32_t -GetFlagBits (const char *arg) -{ - if (::strcasecmp (arg, "all") == 0 ) return POSIX_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) return POSIX_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) return POSIX_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) return POSIX_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) return POSIX_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) return POSIX_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) return POSIX_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) return POSIX_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) return POSIX_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) return POSIX_LOG_PROCESS; - else if (::strcasecmp (arg, "ptrace") == 0 ) return POSIX_LOG_PTRACE; - else if (::strcasecmp (arg, "registers") == 0 ) return POSIX_LOG_REGISTERS; - else if (::strcasecmp (arg, "step") == 0 ) return POSIX_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) return POSIX_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) return POSIX_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) return POSIX_LOG_WATCHPOINTS; - return 0; +Log *ProcessPOSIXLog::GetLogIfAllCategoriesSet(uint32_t mask) { + Log *log(GetLog()); + if (log && mask) { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return NULL; + } + return log; } -void -ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm) -{ - Log *log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - flag_bits = log->GetMask().Get(); - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits &= ~bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - } - - log->GetMask().Reset (flag_bits); - if (flag_bits == 0) - g_log_enabled = false; - } - - return; +static uint32_t GetFlagBits(const char *arg) { + if (::strcasecmp(arg, "all") == 0) + return POSIX_LOG_ALL; + else if (::strcasecmp(arg, "async") == 0) + return POSIX_LOG_ASYNC; + else if (::strncasecmp(arg, "break", 5) == 0) + return POSIX_LOG_BREAKPOINTS; + else if (::strncasecmp(arg, "comm", 4) == 0) + return POSIX_LOG_COMM; + else if (::strcasecmp(arg, "default") == 0) + return POSIX_LOG_DEFAULT; + else if (::strcasecmp(arg, "packets") == 0) + return POSIX_LOG_PACKETS; + else if (::strcasecmp(arg, "memory") == 0) + return POSIX_LOG_MEMORY; + else if (::strcasecmp(arg, "data-short") == 0) + return POSIX_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp(arg, "data-long") == 0) + return POSIX_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp(arg, "process") == 0) + return POSIX_LOG_PROCESS; + else if (::strcasecmp(arg, "ptrace") == 0) + return POSIX_LOG_PTRACE; + else if (::strcasecmp(arg, "registers") == 0) + return POSIX_LOG_REGISTERS; + else if (::strcasecmp(arg, "step") == 0) + return POSIX_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + return POSIX_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + return POSIX_LOG_VERBOSE; + else if (::strncasecmp(arg, "watch", 5) == 0) + return POSIX_LOG_WATCHPOINTS; + return 0; } -Log * -ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. +void ProcessPOSIXLog::DisableLog(const char **args, Stream *feedback_strm) { + Log *log(GetLog()); + if (log) { uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); + + flag_bits = log->GetMask().Get(); + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits &= ~bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); + } } + log->GetMask().Reset(flag_bits); + if (flag_bits == 0) + g_log_enabled = false; + } + + return; +} + +Log *ProcessPOSIXLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, + const char **args, Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits = 0; + if (g_log) + flag_bits = g_log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log) - { - bool got_unknown_category = false; - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits |= bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } + + if (g_log) { + bool got_unknown_category = false; + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits |= bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListLogCategories(feedback_strm); } - if (flag_bits == 0) - flag_bits = POSIX_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - g_log_enabled = true; + } } - return g_log; + if (flag_bits == 0) + flag_bits = POSIX_LOG_DEFAULT; + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + g_log_enabled = true; + } + return g_log; } -void -ProcessPOSIXLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" +void ProcessPOSIXLog::ListLogCategories(Stream *strm) { + strm->Printf( + "Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " async - log asynchronous activity\n" + " break - log breakpoints\n" + " communication - log communication activity\n" + " default - enable the default set of logging categories for liblldb\n" + " packets - log gdb remote packets\n" + " memory - log memory reads and writes\n" + " data-short - log memory bytes for memory reads and writes for short " + "transactions only\n" + " data-long - log memory bytes for memory reads and writes for all " + "transactions\n" + " process - log process events and activities\n" #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - " ptrace - log all calls to ptrace\n" + " ptrace - log all calls to ptrace\n" #endif - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n", + ProcessPOSIXLog::m_pluginname); } - -void -ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } +void ProcessPOSIXLog::LogIf(uint32_t mask, const char *format, ...) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(mask)); + if (log) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } } int ProcessPOSIXLog::m_nestinglevel; diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h index 7edd839152e..7d187da4e48 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h @@ -1,4 +1,5 @@ -//===-- ProcessPOSIXLog.h -----------------------------------------*- C++ -*-===// +//===-- ProcessPOSIXLog.h -----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -17,101 +18,85 @@ // Project includes #include "lldb/Core/Log.h" -#define POSIX_LOG_VERBOSE (1u << 0) -#define POSIX_LOG_PROCESS (1u << 1) -#define POSIX_LOG_THREAD (1u << 2) -#define POSIX_LOG_PACKETS (1u << 3) -#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define POSIX_LOG_BREAKPOINTS (1u << 7) -#define POSIX_LOG_WATCHPOINTS (1u << 8) -#define POSIX_LOG_STEP (1u << 9) -#define POSIX_LOG_COMM (1u << 10) -#define POSIX_LOG_ASYNC (1u << 11) -#define POSIX_LOG_PTRACE (1u << 12) -#define POSIX_LOG_REGISTERS (1u << 13) -#define POSIX_LOG_ALL (UINT32_MAX) -#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS +#define POSIX_LOG_VERBOSE (1u << 0) +#define POSIX_LOG_PROCESS (1u << 1) +#define POSIX_LOG_THREAD (1u << 2) +#define POSIX_LOG_PACKETS (1u << 3) +#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define POSIX_LOG_MEMORY_DATA_SHORT \ + (1u << 5) // Log short memory reads/writes bytes +#define POSIX_LOG_MEMORY_DATA_LONG \ + (1u << 6) // Log all memory reads/writes bytes +#define POSIX_LOG_BREAKPOINTS (1u << 7) +#define POSIX_LOG_WATCHPOINTS (1u << 8) +#define POSIX_LOG_STEP (1u << 9) +#define POSIX_LOG_COMM (1u << 10) +#define POSIX_LOG_ASYNC (1u << 11) +#define POSIX_LOG_PTRACE (1u << 12) +#define POSIX_LOG_REGISTERS (1u << 13) +#define POSIX_LOG_ALL (UINT32_MAX) +#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS // The size which determines "short memory reads/writes". -#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) +#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) -class ProcessPOSIXLog -{ - static int m_nestinglevel; - static const char *m_pluginname; +class ProcessPOSIXLog { + static int m_nestinglevel; + static const char *m_pluginname; public: - // --------------------------------------------------------------------- - // Public Static Methods - // --------------------------------------------------------------------- - static void - Initialize(lldb_private::ConstString name); - - static void - RegisterPluginName(const char *pluginName) - { - m_pluginname = pluginName; - } - - static void - RegisterPluginName(lldb_private::ConstString pluginName) - { - m_pluginname = pluginName.GetCString(); - } - - static lldb_private::Log * - GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void - DisableLog (const char **args, lldb_private::Stream *feedback_strm); - - static lldb_private::Log * - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, - const char **args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories (lldb_private::Stream *strm); - - static void - LogIf (uint32_t mask, const char *format, ...); - - // The following functions can be used to enable the client to limit - // logging to only the top level function calls. This is useful for - // recursive functions. FIXME: not thread safe! - // Example: - // void NestingFunc() { - // LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); - // if (log) - // { - // ProcessPOSIXLog::IncNestLevel(); - // if (ProcessPOSIXLog::AtTopNestLevel()) - // log->Print(msg); - // } - // NestingFunc(); - // if (log) - // ProcessPOSIXLog::DecNestLevel(); - // } - - static bool - AtTopNestLevel() - { - return m_nestinglevel == 1; - } - - static void - IncNestLevel() - { - ++m_nestinglevel; - } - - static void - DecNestLevel() - { - --m_nestinglevel; - assert(m_nestinglevel >= 0); - } + // --------------------------------------------------------------------- + // Public Static Methods + // --------------------------------------------------------------------- + static void Initialize(lldb_private::ConstString name); + + static void RegisterPluginName(const char *pluginName) { + m_pluginname = pluginName; + } + + static void RegisterPluginName(lldb_private::ConstString pluginName) { + m_pluginname = pluginName.GetCString(); + } + + static lldb_private::Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); + + static void DisableLog(const char **args, + lldb_private::Stream *feedback_strm); + + static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, + uint32_t log_options, const char **args, + lldb_private::Stream *feedback_strm); + + static void ListLogCategories(lldb_private::Stream *strm); + + static void LogIf(uint32_t mask, const char *format, ...); + + // The following functions can be used to enable the client to limit + // logging to only the top level function calls. This is useful for + // recursive functions. FIXME: not thread safe! + // Example: + // void NestingFunc() { + // LogSP log + // (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); + // if (log) + // { + // ProcessPOSIXLog::IncNestLevel(); + // if (ProcessPOSIXLog::AtTopNestLevel()) + // log->Print(msg); + // } + // NestingFunc(); + // if (log) + // ProcessPOSIXLog::DecNestLevel(); + // } + + static bool AtTopNestLevel() { return m_nestinglevel == 1; } + + static void IncNestLevel() { ++m_nestinglevel; } + + static void DecNestLevel() { + --m_nestinglevel; + assert(m_nestinglevel >= 0); + } }; -#endif // liblldb_ProcessPOSIXLog_h_ +#endif // liblldb_ProcessPOSIXLog_h_ diff --git a/lldb/source/Plugins/Process/Utility/ARMDefines.h b/lldb/source/Plugins/Process/Utility/ARMDefines.h index 732c684acec..84c2cf19be7 100644 --- a/lldb/source/Plugins/Process/Utility/ARMDefines.h +++ b/lldb/source/Plugins/Process/Utility/ARMDefines.h @@ -18,96 +18,142 @@ namespace lldb_private { // ARM shifter types -typedef enum -{ - SRType_LSL, - SRType_LSR, - SRType_ASR, - SRType_ROR, - SRType_RRX, - SRType_Invalid +typedef enum { + SRType_LSL, + SRType_LSR, + SRType_ASR, + SRType_ROR, + SRType_RRX, + SRType_Invalid } ARM_ShifterType; -// ARM conditions // Meaning (integer) Meaning (floating-point) Condition flags -#define COND_EQ 0x0 // Equal Equal Z == 1 -#define COND_NE 0x1 // Not equal Not equal, or unordered Z == 0 -#define COND_CS 0x2 // Carry set >, ==, or unordered C == 1 -#define COND_HS 0x2 -#define COND_CC 0x3 // Carry clear Less than C == 0 -#define COND_LO 0x3 -#define COND_MI 0x4 // Minus, negative Less than N == 1 -#define COND_PL 0x5 // Plus, positive or zero >, ==, or unordered N == 0 -#define COND_VS 0x6 // Overflow Unordered V == 1 -#define COND_VC 0x7 // No overflow Not unordered V == 0 -#define COND_HI 0x8 // Unsigned higher Greater than, or unordered C == 1 and Z == 0 -#define COND_LS 0x9 // Unsigned lower or same Less than or equal C == 0 or Z == 1 -#define COND_GE 0xA // Greater than or equal Greater than or equal N == V -#define COND_LT 0xB // Less than Less than, or unordered N != V -#define COND_GT 0xC // Greater than Greater than Z == 0 and N == V -#define COND_LE 0xD // Less than or equal <, ==, or unordered Z == 1 or N != V -#define COND_AL 0xE // Always (unconditional) Always (unconditional) Any +// ARM conditions // Meaning (integer) Meaning (floating-point) +// Condition flags +#define COND_EQ \ + 0x0 // Equal Equal Z == 1 +#define COND_NE \ + 0x1 // Not equal Not equal, or unordered Z == 0 +#define COND_CS \ + 0x2 // Carry set >, ==, or unordered C == 1 +#define COND_HS 0x2 +#define COND_CC \ + 0x3 // Carry clear Less than C == 0 +#define COND_LO 0x3 +#define COND_MI \ + 0x4 // Minus, negative Less than N == 1 +#define COND_PL \ + 0x5 // Plus, positive or zero >, ==, or unordered N == 0 +#define COND_VS \ + 0x6 // Overflow Unordered V == 1 +#define COND_VC \ + 0x7 // No overflow Not unordered V == 0 +#define COND_HI \ + 0x8 // Unsigned higher Greater than, or unordered C == 1 and Z == + // 0 +#define COND_LS \ + 0x9 // Unsigned lower or same Less than or equal C == 0 or Z == + // 1 +#define COND_GE \ + 0xA // Greater than or equal Greater than or equal N == V +#define COND_LT \ + 0xB // Less than Less than, or unordered N != V +#define COND_GT \ + 0xC // Greater than Greater than Z == 0 and N == + // V +#define COND_LE \ + 0xD // Less than or equal <, ==, or unordered Z == 1 or N != + // V +#define COND_AL \ + 0xE // Always (unconditional) Always (unconditional) Any #define COND_UNCOND 0xF -static inline const char * -ARMCondCodeToString(uint32_t CC) -{ - switch (CC) { - default: assert(0 && "Unknown condition code"); - case COND_EQ: return "eq"; - case COND_NE: return "ne"; - case COND_HS: return "hs"; - case COND_LO: return "lo"; - case COND_MI: return "mi"; - case COND_PL: return "pl"; - case COND_VS: return "vs"; - case COND_VC: return "vc"; - case COND_HI: return "hi"; - case COND_LS: return "ls"; - case COND_GE: return "ge"; - case COND_LT: return "lt"; - case COND_GT: return "gt"; - case COND_LE: return "le"; - case COND_AL: return "al"; - } +static inline const char *ARMCondCodeToString(uint32_t CC) { + switch (CC) { + default: + assert(0 && "Unknown condition code"); + case COND_EQ: + return "eq"; + case COND_NE: + return "ne"; + case COND_HS: + return "hs"; + case COND_LO: + return "lo"; + case COND_MI: + return "mi"; + case COND_PL: + return "pl"; + case COND_VS: + return "vs"; + case COND_VC: + return "vc"; + case COND_HI: + return "hi"; + case COND_LS: + return "ls"; + case COND_GE: + return "ge"; + case COND_LT: + return "lt"; + case COND_GT: + return "gt"; + case COND_LE: + return "le"; + case COND_AL: + return "al"; + } } -static inline bool -ARMConditionPassed(const uint32_t condition, const uint32_t cpsr) -{ - const uint32_t cpsr_n = (cpsr >> 31) & 1u; // Negative condition code flag - const uint32_t cpsr_z = (cpsr >> 30) & 1u; // Zero condition code flag - const uint32_t cpsr_c = (cpsr >> 29) & 1u; // Carry condition code flag - const uint32_t cpsr_v = (cpsr >> 28) & 1u; // Overflow condition code flag +static inline bool ARMConditionPassed(const uint32_t condition, + const uint32_t cpsr) { + const uint32_t cpsr_n = (cpsr >> 31) & 1u; // Negative condition code flag + const uint32_t cpsr_z = (cpsr >> 30) & 1u; // Zero condition code flag + const uint32_t cpsr_c = (cpsr >> 29) & 1u; // Carry condition code flag + const uint32_t cpsr_v = (cpsr >> 28) & 1u; // Overflow condition code flag - switch (condition) { - case COND_EQ: return (cpsr_z == 1); - case COND_NE: return (cpsr_z == 0); - case COND_CS: return (cpsr_c == 1); - case COND_CC: return (cpsr_c == 0); - case COND_MI: return (cpsr_n == 1); - case COND_PL: return (cpsr_n == 0); - case COND_VS: return (cpsr_v == 1); - case COND_VC: return (cpsr_v == 0); - case COND_HI: return ((cpsr_c == 1) && (cpsr_z == 0)); - case COND_LS: return ((cpsr_c == 0) || (cpsr_z == 1)); - case COND_GE: return (cpsr_n == cpsr_v); - case COND_LT: return (cpsr_n != cpsr_v); - case COND_GT: return ((cpsr_z == 0) && (cpsr_n == cpsr_v)); - case COND_LE: return ((cpsr_z == 1) || (cpsr_n != cpsr_v)); - case COND_AL: - case COND_UNCOND: - default: - return true; - } - return false; + switch (condition) { + case COND_EQ: + return (cpsr_z == 1); + case COND_NE: + return (cpsr_z == 0); + case COND_CS: + return (cpsr_c == 1); + case COND_CC: + return (cpsr_c == 0); + case COND_MI: + return (cpsr_n == 1); + case COND_PL: + return (cpsr_n == 0); + case COND_VS: + return (cpsr_v == 1); + case COND_VC: + return (cpsr_v == 0); + case COND_HI: + return ((cpsr_c == 1) && (cpsr_z == 0)); + case COND_LS: + return ((cpsr_c == 0) || (cpsr_z == 1)); + case COND_GE: + return (cpsr_n == cpsr_v); + case COND_LT: + return (cpsr_n != cpsr_v); + case COND_GT: + return ((cpsr_z == 0) && (cpsr_n == cpsr_v)); + case COND_LE: + return ((cpsr_z == 1) || (cpsr_n != cpsr_v)); + case COND_AL: + case COND_UNCOND: + default: + return true; + } + return false; } // Bit positions for CPSR -#define CPSR_T_POS 5 -#define CPSR_F_POS 6 -#define CPSR_I_POS 7 -#define CPSR_A_POS 8 -#define CPSR_E_POS 9 +#define CPSR_T_POS 5 +#define CPSR_F_POS 6 +#define CPSR_I_POS 7 +#define CPSR_A_POS 8 +#define CPSR_E_POS 9 #define CPSR_J_POS 24 #define CPSR_Q_POS 27 #define CPSR_V_POS 28 @@ -116,30 +162,30 @@ ARMConditionPassed(const uint32_t condition, const uint32_t cpsr) #define CPSR_N_POS 31 // CPSR mode definitions -#define CPSR_MODE_USR 0x10u -#define CPSR_MODE_FIQ 0x11u -#define CPSR_MODE_IRQ 0x12u -#define CPSR_MODE_SVC 0x13u -#define CPSR_MODE_ABT 0x17u -#define CPSR_MODE_UND 0x1bu -#define CPSR_MODE_SYS 0x1fu - +#define CPSR_MODE_USR 0x10u +#define CPSR_MODE_FIQ 0x11u +#define CPSR_MODE_IRQ 0x12u +#define CPSR_MODE_SVC 0x13u +#define CPSR_MODE_ABT 0x17u +#define CPSR_MODE_UND 0x1bu +#define CPSR_MODE_SYS 0x1fu + // Masks for CPSR #define MASK_CPSR_MODE_MASK (0x0000001fu) -#define MASK_CPSR_IT_MASK (0x0600fc00u) -#define MASK_CPSR_T (1u << CPSR_T_POS) -#define MASK_CPSR_F (1u << CPSR_F_POS) -#define MASK_CPSR_I (1u << CPSR_I_POS) -#define MASK_CPSR_A (1u << CPSR_A_POS) -#define MASK_CPSR_E (1u << CPSR_E_POS) -#define MASK_CPSR_GE_MASK (0x000f0000u) -#define MASK_CPSR_J (1u << CPSR_J_POS) -#define MASK_CPSR_Q (1u << CPSR_Q_POS) -#define MASK_CPSR_V (1u << CPSR_V_POS) -#define MASK_CPSR_C (1u << CPSR_C_POS) -#define MASK_CPSR_Z (1u << CPSR_Z_POS) -#define MASK_CPSR_N (1u << CPSR_N_POS) +#define MASK_CPSR_IT_MASK (0x0600fc00u) +#define MASK_CPSR_T (1u << CPSR_T_POS) +#define MASK_CPSR_F (1u << CPSR_F_POS) +#define MASK_CPSR_I (1u << CPSR_I_POS) +#define MASK_CPSR_A (1u << CPSR_A_POS) +#define MASK_CPSR_E (1u << CPSR_E_POS) +#define MASK_CPSR_GE_MASK (0x000f0000u) +#define MASK_CPSR_J (1u << CPSR_J_POS) +#define MASK_CPSR_Q (1u << CPSR_Q_POS) +#define MASK_CPSR_V (1u << CPSR_V_POS) +#define MASK_CPSR_C (1u << CPSR_C_POS) +#define MASK_CPSR_Z (1u << CPSR_Z_POS) +#define MASK_CPSR_N (1u << CPSR_N_POS) -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_ARMDefines_h_ +#endif // lldb_ARMDefines_h_ diff --git a/lldb/source/Plugins/Process/Utility/ARMUtils.h b/lldb/source/Plugins/Process/Utility/ARMUtils.h index b6ba3fea692..2bbd519b246 100644 --- a/lldb/source/Plugins/Process/Utility/ARMUtils.h +++ b/lldb/source/Plugins/Process/Utility/ARMUtils.h @@ -18,352 +18,335 @@ namespace lldb_private { -static inline uint32_t Align(uint32_t val, uint32_t alignment) -{ - return alignment * (val / alignment); +static inline uint32_t Align(uint32_t val, uint32_t alignment) { + return alignment * (val / alignment); } -static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t) -{ - switch (type) - { - default: - //assert(0 && "Invalid shift type"); - case 0: - shift_t = SRType_LSL; - return imm5; - case 1: - shift_t = SRType_LSR; - return (imm5 == 0 ? 32 : imm5); - case 2: - shift_t = SRType_ASR; - return (imm5 == 0 ? 32 : imm5); - case 3: - if (imm5 == 0) - { - shift_t = SRType_RRX; - return 1; - } - else - { - shift_t = SRType_ROR; - return imm5; - } +static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, + ARM_ShifterType &shift_t) { + switch (type) { + default: + // assert(0 && "Invalid shift type"); + case 0: + shift_t = SRType_LSL; + return imm5; + case 1: + shift_t = SRType_LSR; + return (imm5 == 0 ? 32 : imm5); + case 2: + shift_t = SRType_ASR; + return (imm5 == 0 ? 32 : imm5); + case 3: + if (imm5 == 0) { + shift_t = SRType_RRX; + return 1; + } else { + shift_t = SRType_ROR; + return imm5; } - shift_t = SRType_Invalid; - return UINT32_MAX; - + } + shift_t = SRType_Invalid; + return UINT32_MAX; } // A8.6.35 CMP (register) -- Encoding T3 // Convenience function. -static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode, ARM_ShifterType &shift_t) -{ - return DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t); +static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode, + ARM_ShifterType &shift_t) { + return DecodeImmShift(Bits32(opcode, 5, 4), + Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6), + shift_t); } // A8.6.35 CMP (register) -- Encoding A1 // Convenience function. -static inline uint32_t DecodeImmShiftARM(const uint32_t opcode, ARM_ShifterType &shift_t) -{ - return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); +static inline uint32_t DecodeImmShiftARM(const uint32_t opcode, + ARM_ShifterType &shift_t) { + return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t); } -static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t, const uint32_t imm5) -{ - ARM_ShifterType dont_care; - return DecodeImmShift(shift_t, imm5, dont_care); +static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t, + const uint32_t imm5) { + ARM_ShifterType dont_care; + return DecodeImmShift(shift_t, imm5, dont_care); } -static inline ARM_ShifterType DecodeRegShift(const uint32_t type) -{ - switch (type) { - default: - //assert(0 && "Invalid shift type"); - return SRType_Invalid; - case 0: - return SRType_LSL; - case 1: - return SRType_LSR; - case 2: - return SRType_ASR; - case 3: - return SRType_ROR; - } +static inline ARM_ShifterType DecodeRegShift(const uint32_t type) { + switch (type) { + default: + // assert(0 && "Invalid shift type"); + return SRType_Invalid; + case 0: + return SRType_LSL; + case 1: + return SRType_LSR; + case 2: + return SRType_ASR; + case 3: + return SRType_ROR; + } } -static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success) -{ - if (amount == 0) { - *success = false; - return 0; - } - *success = true; - carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0; - return value << amount; +static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount, + uint32_t &carry_out, bool *success) { + if (amount == 0) { + *success = false; + return 0; + } + *success = true; + carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0; + return value << amount; } -static inline uint32_t LSL(const uint32_t value, const uint32_t amount, bool *success) -{ - *success = true; - if (amount == 0) - return value; - uint32_t dont_care; - uint32_t result = LSL_C(value, amount, dont_care, success); - if (*success) - return result; - else - return 0; -} - -static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success) -{ - if (amount == 0) { - *success = false; - return 0; - } - *success = true; - carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0; - return value >> amount; +static inline uint32_t LSL(const uint32_t value, const uint32_t amount, + bool *success) { + *success = true; + if (amount == 0) + return value; + uint32_t dont_care; + uint32_t result = LSL_C(value, amount, dont_care, success); + if (*success) + return result; + else + return 0; } -static inline uint32_t LSR(const uint32_t value, const uint32_t amount, bool *success) -{ - *success = true; - if (amount == 0) - return value; - uint32_t dont_care; - uint32_t result = LSR_C(value, amount, dont_care, success); - if (*success) - return result; - else - return 0; +static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount, + uint32_t &carry_out, bool *success) { + if (amount == 0) { + *success = false; + return 0; + } + *success = true; + carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0; + return value >> amount; } -static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success) -{ - if (amount == 0 || amount > 32) { - *success = false; - return 0; - } - *success = true; - bool negative = BitIsSet(value, 31); - if (amount <= 32) - { - carry_out = Bit32(value, amount - 1); - int64_t extended = llvm::SignExtend64<32>(value); - return UnsignedBits(extended, amount + 31, amount); - } - else - { - carry_out = (negative ? 1 : 0); - return (negative ? 0xffffffff : 0); - } +static inline uint32_t LSR(const uint32_t value, const uint32_t amount, + bool *success) { + *success = true; + if (amount == 0) + return value; + uint32_t dont_care; + uint32_t result = LSR_C(value, amount, dont_care, success); + if (*success) + return result; + else + return 0; } -static inline uint32_t ASR(const uint32_t value, const uint32_t amount, bool *success) -{ - *success = true; - if (amount == 0) - return value; - uint32_t dont_care; - uint32_t result = ASR_C(value, amount, dont_care, success); - if (*success) - return result; - else - return 0; +static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount, + uint32_t &carry_out, bool *success) { + if (amount == 0 || amount > 32) { + *success = false; + return 0; + } + *success = true; + bool negative = BitIsSet(value, 31); + if (amount <= 32) { + carry_out = Bit32(value, amount - 1); + int64_t extended = llvm::SignExtend64<32>(value); + return UnsignedBits(extended, amount + 31, amount); + } else { + carry_out = (negative ? 1 : 0); + return (negative ? 0xffffffff : 0); + } } -static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success) -{ - if (amount == 0) { - *success = false; - return 0; - } - *success = true; - uint32_t amt = amount % 32; - uint32_t result = Rotr32(value, amt); - carry_out = Bit32(value, 31); +static inline uint32_t ASR(const uint32_t value, const uint32_t amount, + bool *success) { + *success = true; + if (amount == 0) + return value; + uint32_t dont_care; + uint32_t result = ASR_C(value, amount, dont_care, success); + if (*success) return result; + else + return 0; } -static inline uint32_t ROR(const uint32_t value, const uint32_t amount, bool *success) -{ - *success = true; - if (amount == 0) - return value; - uint32_t dont_care; - uint32_t result = ROR_C(value, amount, dont_care, success); - if (*success) - return result; - else - return 0; +static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount, + uint32_t &carry_out, bool *success) { + if (amount == 0) { + *success = false; + return 0; + } + *success = true; + uint32_t amt = amount % 32; + uint32_t result = Rotr32(value, amt); + carry_out = Bit32(value, 31); + return result; } -static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in, uint32_t &carry_out, bool *success) -{ - *success = true; - carry_out = Bit32(value, 0); - return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1); +static inline uint32_t ROR(const uint32_t value, const uint32_t amount, + bool *success) { + *success = true; + if (amount == 0) + return value; + uint32_t dont_care; + uint32_t result = ROR_C(value, amount, dont_care, success); + if (*success) + return result; + else + return 0; } -static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, bool *success) -{ - *success = true; - uint32_t dont_care; - uint32_t result = RRX_C(value, carry_in, dont_care, success); - if (*success) - return result; - else - return 0; +static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in, + uint32_t &carry_out, bool *success) { + *success = true; + carry_out = Bit32(value, 0); + return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1); } -static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, const uint32_t amount, - const uint32_t carry_in, uint32_t &carry_out, bool *success) -{ - if (type == SRType_RRX && amount != 1) { - *success = false; - return 0; - } - *success = true; +static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, + bool *success) { + *success = true; + uint32_t dont_care; + uint32_t result = RRX_C(value, carry_in, dont_care, success); + if (*success) + return result; + else + return 0; +} - if (amount == 0) { - carry_out = carry_in; - return value; - } - uint32_t result; - switch (type) { - case SRType_LSL: - result = LSL_C(value, amount, carry_out, success); - break; - case SRType_LSR: - result = LSR_C(value, amount, carry_out, success); - break; - case SRType_ASR: - result = ASR_C(value, amount, carry_out, success); - break; - case SRType_ROR: - result = ROR_C(value, amount, carry_out, success); - break; - case SRType_RRX: - result = RRX_C(value, carry_in, carry_out, success); - break; - default: - *success = false; - break; - } - if (*success) - return result; - else - return 0; +static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, + const uint32_t amount, const uint32_t carry_in, + uint32_t &carry_out, bool *success) { + if (type == SRType_RRX && amount != 1) { + *success = false; + return 0; + } + *success = true; + + if (amount == 0) { + carry_out = carry_in; + return value; + } + uint32_t result; + switch (type) { + case SRType_LSL: + result = LSL_C(value, amount, carry_out, success); + break; + case SRType_LSR: + result = LSR_C(value, amount, carry_out, success); + break; + case SRType_ASR: + result = ASR_C(value, amount, carry_out, success); + break; + case SRType_ROR: + result = ROR_C(value, amount, carry_out, success); + break; + case SRType_RRX: + result = RRX_C(value, carry_in, carry_out, success); + break; + default: + *success = false; + break; + } + if (*success) + return result; + else + return 0; } -static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, const uint32_t amount, - const uint32_t carry_in, bool *success) -{ - // Don't care about carry out in this case. - uint32_t dont_care; - uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success); - if (*success) - return result; - else - return 0; +static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, + const uint32_t amount, const uint32_t carry_in, + bool *success) { + // Don't care about carry out in this case. + uint32_t dont_care; + uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success); + if (*success) + return result; + else + return 0; } -static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit) -{ - return Bits32(val, msbit, lsbit); +static inline uint32_t bits(const uint32_t val, const uint32_t msbit, + const uint32_t lsbit) { + return Bits32(val, msbit, lsbit); } -static inline uint32_t bit(const uint32_t val, const uint32_t msbit) -{ - return bits(val, msbit, msbit); +static inline uint32_t bit(const uint32_t val, const uint32_t msbit) { + return bits(val, msbit, msbit); } -static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift) -{ - uint32_t m = shift % N; - return (val >> m) | (val << (N - m)); +static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift) { + uint32_t m = shift % N; + return (val >> m) | (val << (N - m)); } // (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in) -static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out) -{ - uint32_t imm32; // the expanded result - uint32_t imm = bits(opcode, 7, 0); // immediate value - uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount - if (amt == 0) - { - imm32 = imm; - carry_out = carry_in; - } - else - { - imm32 = ror(imm, 32, amt); - carry_out = Bit32(imm32, 31); - } - return imm32; +static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, + uint32_t &carry_out) { + uint32_t imm32; // the expanded result + uint32_t imm = bits(opcode, 7, 0); // immediate value + uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount + if (amt == 0) { + imm32 = imm; + carry_out = carry_in; + } else { + imm32 = ror(imm, 32, amt); + carry_out = Bit32(imm32, 31); + } + return imm32; } -static inline uint32_t ARMExpandImm(uint32_t opcode) -{ - // 'carry_in' argument to following function call does not affect the imm32 result. - uint32_t carry_in = 0; - uint32_t carry_out; - return ARMExpandImm_C(opcode, carry_in, carry_out); +static inline uint32_t ARMExpandImm(uint32_t opcode) { + // 'carry_in' argument to following function call does not affect the imm32 + // result. + uint32_t carry_in = 0; + uint32_t carry_out; + return ARMExpandImm_C(opcode, carry_in, carry_out); } // (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in) -static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out) -{ - uint32_t imm32; // the expanded result - const uint32_t i = bit(opcode, 26); - const uint32_t imm3 = bits(opcode, 14, 12); - const uint32_t abcdefgh = bits(opcode, 7, 0); - const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh; - - if (bits(imm12, 11, 10) == 0) - { - switch (bits(imm12, 9, 8)) { - default: // Keep static analyzer happy with a default case - case 0: - imm32 = abcdefgh; - break; - - case 1: - imm32 = abcdefgh << 16 | abcdefgh; - break; - - case 2: - imm32 = abcdefgh << 24 | abcdefgh << 8; - break; - - case 3: - imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh; - break; - } - carry_out = carry_in; - } - else - { - const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0); - imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7)); - carry_out = Bit32(imm32, 31); +static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, + uint32_t &carry_out) { + uint32_t imm32; // the expanded result + const uint32_t i = bit(opcode, 26); + const uint32_t imm3 = bits(opcode, 14, 12); + const uint32_t abcdefgh = bits(opcode, 7, 0); + const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh; + + if (bits(imm12, 11, 10) == 0) { + switch (bits(imm12, 9, 8)) { + default: // Keep static analyzer happy with a default case + case 0: + imm32 = abcdefgh; + break; + + case 1: + imm32 = abcdefgh << 16 | abcdefgh; + break; + + case 2: + imm32 = abcdefgh << 24 | abcdefgh << 8; + break; + + case 3: + imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh; + break; } - return imm32; + carry_out = carry_in; + } else { + const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0); + imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7)); + carry_out = Bit32(imm32, 31); + } + return imm32; } -static inline uint32_t ThumbExpandImm(uint32_t opcode) -{ - // 'carry_in' argument to following function call does not affect the imm32 result. - uint32_t carry_in = 0; - uint32_t carry_out; - return ThumbExpandImm_C(opcode, carry_in, carry_out); +static inline uint32_t ThumbExpandImm(uint32_t opcode) { + // 'carry_in' argument to following function call does not affect the imm32 + // result. + uint32_t carry_in = 0; + uint32_t carry_out; + return ThumbExpandImm_C(opcode, carry_in, carry_out); } // imm32 = ZeroExtend(i:imm3:imm8, 32) -static inline uint32_t ThumbImm12(uint32_t opcode) -{ +static inline uint32_t ThumbImm12(uint32_t opcode) { const uint32_t i = bit(opcode, 26); const uint32_t imm3 = bits(opcode, 14, 12); const uint32_t imm8 = bits(opcode, 7, 0); @@ -372,15 +355,13 @@ static inline uint32_t ThumbImm12(uint32_t opcode) } // imm32 = ZeroExtend(imm7:'00', 32) -static inline uint32_t ThumbImm7Scaled(uint32_t opcode) -{ +static inline uint32_t ThumbImm7Scaled(uint32_t opcode) { const uint32_t imm7 = bits(opcode, 6, 0); return imm7 * 4; } // imm32 = ZeroExtend(imm8:'00', 32) -static inline uint32_t ThumbImm8Scaled(uint32_t opcode) -{ +static inline uint32_t ThumbImm8Scaled(uint32_t opcode) { const uint32_t imm8 = bits(opcode, 7, 0); return imm8 * 4; } @@ -389,6 +370,6 @@ static inline uint32_t ThumbImm8Scaled(uint32_t opcode) // not permitted for many Thumb register specifiers. static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; } -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_ARMUtils_h_ +#endif // lldb_ARMUtils_h_ diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 86c62f72db5..dfb60e1ddc9 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -24,787 +24,726 @@ using namespace lldb; using namespace lldb_private; -DynamicRegisterInfo::DynamicRegisterInfo () : - m_regs (), - m_sets (), - m_set_reg_nums (), - m_set_names (), - m_value_regs_map (), - m_invalidate_regs_map (), - m_dynamic_reg_size_map (), - m_reg_data_byte_size (0), - m_finalized (false) -{ +DynamicRegisterInfo::DynamicRegisterInfo() + : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(), + m_invalidate_regs_map(), m_dynamic_reg_size_map(), + m_reg_data_byte_size(0), m_finalized(false) {} + +DynamicRegisterInfo::DynamicRegisterInfo( + const lldb_private::StructuredData::Dictionary &dict, + const lldb_private::ArchSpec &arch) + : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(), + m_invalidate_regs_map(), m_dynamic_reg_size_map(), + m_reg_data_byte_size(0), m_finalized(false) { + SetRegisterInfo(dict, arch); } -DynamicRegisterInfo::DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, - const lldb_private::ArchSpec &arch) : - m_regs (), - m_sets (), - m_set_reg_nums (), - m_set_names (), - m_value_regs_map (), - m_invalidate_regs_map (), - m_dynamic_reg_size_map (), - m_reg_data_byte_size (0), - m_finalized (false) -{ - SetRegisterInfo (dict, arch); -} - -DynamicRegisterInfo::~DynamicRegisterInfo () -{ -} +DynamicRegisterInfo::~DynamicRegisterInfo() {} size_t -DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, const ArchSpec &arch) -{ - assert(!m_finalized); - StructuredData::Array *sets = nullptr; - if (dict.GetValueForKeyAsArray("sets", sets)) - { - const uint32_t num_sets = sets->GetSize(); - for (uint32_t i=0; i<num_sets; ++i) - { - std::string set_name_str; - ConstString set_name; - if (sets->GetItemAtIndexAsString(i, set_name_str)) - set_name.SetCString(set_name_str.c_str()); - if (set_name) - { - RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; - m_sets.push_back (new_set); - } - else - { - Clear(); - printf("error: register sets must have valid names\n"); - return 0; - } - } - m_set_reg_nums.resize(m_sets.size()); - } - StructuredData::Array *regs = nullptr; - if (!dict.GetValueForKeyAsArray("registers", regs)) +DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, + const ArchSpec &arch) { + assert(!m_finalized); + StructuredData::Array *sets = nullptr; + if (dict.GetValueForKeyAsArray("sets", sets)) { + const uint32_t num_sets = sets->GetSize(); + for (uint32_t i = 0; i < num_sets; ++i) { + std::string set_name_str; + ConstString set_name; + if (sets->GetItemAtIndexAsString(i, set_name_str)) + set_name.SetCString(set_name_str.c_str()); + if (set_name) { + RegisterSet new_set = {set_name.AsCString(), NULL, 0, NULL}; + m_sets.push_back(new_set); + } else { + Clear(); + printf("error: register sets must have valid names\n"); return 0; + } + } + m_set_reg_nums.resize(m_sets.size()); + } + StructuredData::Array *regs = nullptr; + if (!dict.GetValueForKeyAsArray("registers", regs)) + return 0; + + const uint32_t num_regs = regs->GetSize(); + // typedef std::map<std::string, std::vector<std::string> > + // InvalidateNameMap; + // InvalidateNameMap invalidate_map; + for (uint32_t i = 0; i < num_regs; ++i) { + StructuredData::Dictionary *reg_info_dict = nullptr; + if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) { + Clear(); + printf("error: items in the 'registers' array must be dictionaries\n"); + regs->DumpToStdout(); + return 0; + } - const uint32_t num_regs = regs->GetSize(); -// typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap; -// InvalidateNameMap invalidate_map; - for (uint32_t i = 0; i < num_regs; ++i) - { - StructuredData::Dictionary *reg_info_dict = nullptr; - if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) - { - Clear(); - printf("error: items in the 'registers' array must be dictionaries\n"); - regs->DumpToStdout(); - return 0; - } - - // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2, - // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, - RegisterInfo reg_info; - std::vector<uint32_t> value_regs; - std::vector<uint32_t> invalidate_regs; - memset(®_info, 0, sizeof(reg_info)); - - ConstString name_val; - ConstString alt_name_val; - if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) - { - Clear(); - printf("error: registers must have valid names and offsets\n"); - reg_info_dict->DumpToStdout(); - return 0; - } - reg_info.name = name_val.GetCString(); - reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr); - reg_info.alt_name = alt_name_val.GetCString(); - - reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset, UINT32_MAX); - - const ByteOrder byte_order = arch.GetByteOrder(); - - if (reg_info.byte_offset == UINT32_MAX) - { - // No offset for this register, see if the register has a value expression - // which indicates this register is part of another register. Value expressions - // are things like "rax[31:0]" which state that the current register's value - // is in a concrete register "rax" in bits 31:0. If there is a value expression - // we can calculate the offset - bool success = false; - std::string slice_str; - if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) - { - // Slices use the following format: - // REGNAME[MSBIT:LSBIT] - // REGNAME - name of the register to grab a slice of - // MSBIT - the most significant bit at which the current register value starts at - // LSBIT - the least significant bit at which the current register value ends at - static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"); - RegularExpression::Match regex_match(3); - if (g_bitfield_regex.Execute(slice_str.c_str(), ®ex_match)) - { - llvm::StringRef reg_name_str; - std::string msbit_str; - std::string lsbit_str; - if (regex_match.GetMatchAtIndex(slice_str.c_str(), 1, reg_name_str) && - regex_match.GetMatchAtIndex(slice_str.c_str(), 2, msbit_str) && - regex_match.GetMatchAtIndex(slice_str.c_str(), 3, lsbit_str)) - { - const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); - if (msbit != UINT32_MAX && lsbit != UINT32_MAX) - { - if (msbit > lsbit) - { - const uint32_t msbyte = msbit / 8; - const uint32_t lsbyte = lsbit / 8; - - ConstString containing_reg_name(reg_name_str); - - RegisterInfo *containing_reg_info = GetRegisterInfo(containing_reg_name); - if (containing_reg_info) - { - const uint32_t max_bit = containing_reg_info->byte_size * 8; - if (msbit < max_bit && lsbit < max_bit) - { - m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i); - m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); - m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); - - if (byte_order == eByteOrderLittle) - { - success = true; - reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte; - } - else if (byte_order == eByteOrderBig) - { - success = true; - reg_info.byte_offset = containing_reg_info->byte_offset + msbyte; - } - else - { - assert(!"Invalid byte order"); - } - } - else - { - if (msbit > max_bit) - printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, - max_bit); - else - printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, - max_bit); - } - } - else - { - printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString()); - } - } - else - { - printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit); - } - } - else - { - printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit); - } + // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' + // , 'format':'hex' , 'set': 0, 'ehframe' : 2, + // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, + RegisterInfo reg_info; + std::vector<uint32_t> value_regs; + std::vector<uint32_t> invalidate_regs; + memset(®_info, 0, sizeof(reg_info)); + + ConstString name_val; + ConstString alt_name_val; + if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) { + Clear(); + printf("error: registers must have valid names and offsets\n"); + reg_info_dict->DumpToStdout(); + return 0; + } + reg_info.name = name_val.GetCString(); + reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr); + reg_info.alt_name = alt_name_val.GetCString(); + + reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset, + UINT32_MAX); + + const ByteOrder byte_order = arch.GetByteOrder(); + + if (reg_info.byte_offset == UINT32_MAX) { + // No offset for this register, see if the register has a value expression + // which indicates this register is part of another register. Value + // expressions + // are things like "rax[31:0]" which state that the current register's + // value + // is in a concrete register "rax" in bits 31:0. If there is a value + // expression + // we can calculate the offset + bool success = false; + std::string slice_str; + if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) { + // Slices use the following format: + // REGNAME[MSBIT:LSBIT] + // REGNAME - name of the register to grab a slice of + // MSBIT - the most significant bit at which the current register value + // starts at + // LSBIT - the least significant bit at which the current register value + // ends at + static RegularExpression g_bitfield_regex( + "([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"); + RegularExpression::Match regex_match(3); + if (g_bitfield_regex.Execute(slice_str.c_str(), ®ex_match)) { + llvm::StringRef reg_name_str; + std::string msbit_str; + std::string lsbit_str; + if (regex_match.GetMatchAtIndex(slice_str.c_str(), 1, reg_name_str) && + regex_match.GetMatchAtIndex(slice_str.c_str(), 2, msbit_str) && + regex_match.GetMatchAtIndex(slice_str.c_str(), 3, lsbit_str)) { + const uint32_t msbit = + StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = + StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); + if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { + if (msbit > lsbit) { + const uint32_t msbyte = msbit / 8; + const uint32_t lsbyte = lsbit / 8; + + ConstString containing_reg_name(reg_name_str); + + RegisterInfo *containing_reg_info = + GetRegisterInfo(containing_reg_name); + if (containing_reg_info) { + const uint32_t max_bit = containing_reg_info->byte_size * 8; + if (msbit < max_bit && lsbit < max_bit) { + m_invalidate_regs_map[containing_reg_info + ->kinds[eRegisterKindLLDB]] + .push_back(i); + m_value_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + m_invalidate_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + + if (byte_order == eByteOrderLittle) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + lsbyte; + } else if (byte_order == eByteOrderBig) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + msbyte; + } else { + assert(!"Invalid byte order"); } + } else { + if (msbit > max_bit) + printf("error: msbit (%u) must be less than the bitsize " + "of the register (%u)\n", + msbit, max_bit); else - { - // TODO: print error invalid slice string that doesn't follow the format - printf("error: failed to extract regex matches for parsing the register bitfield regex\n"); - } - } - else - { - // TODO: print error invalid slice string that doesn't follow the format - printf("error: failed to match against register bitfield regex\n"); + printf("error: lsbit (%u) must be less than the bitsize " + "of the register (%u)\n", + lsbit, max_bit); + } + } else { + printf("error: invalid concrete register \"%s\"\n", + containing_reg_name.GetCString()); } + } else { + printf("error: msbit (%u) must be greater than lsbit (%u)\n", + msbit, lsbit); + } + } else { + printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, + lsbit); } - else - { - StructuredData::Array *composite_reg_list = nullptr; - if (reg_info_dict->GetValueForKeyAsArray("composite", composite_reg_list)) - { - const size_t num_composite_regs = composite_reg_list->GetSize(); - if (num_composite_regs > 0) - { - uint32_t composite_offset = UINT32_MAX; - for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; ++composite_idx) - { - ConstString composite_reg_name; - if (composite_reg_list->GetItemAtIndexAsString(composite_idx, composite_reg_name, nullptr)) - { - RegisterInfo *composite_reg_info = GetRegisterInfo(composite_reg_name); - if (composite_reg_info) - { - composite_offset = std::min(composite_offset, composite_reg_info->byte_offset); - m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); - m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i); - m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); - } - else - { - // TODO: print error invalid slice string that doesn't follow the format - printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString()); - } - } - else - { - printf("error: 'composite' list value wasn't a python string\n"); - } - } - if (composite_offset != UINT32_MAX) - { - reg_info.byte_offset = composite_offset; - success = m_value_regs_map.find(i) != m_value_regs_map.end(); - } - else - { - printf("error: 'composite' registers must specify at least one real register\n"); - } - } - else - { - printf("error: 'composite' list was empty\n"); - } + } else { + // TODO: print error invalid slice string that doesn't follow the + // format + printf("error: failed to extract regex matches for parsing the " + "register bitfield regex\n"); + } + } else { + // TODO: print error invalid slice string that doesn't follow the + // format + printf("error: failed to match against register bitfield regex\n"); + } + } else { + StructuredData::Array *composite_reg_list = nullptr; + if (reg_info_dict->GetValueForKeyAsArray("composite", + composite_reg_list)) { + const size_t num_composite_regs = composite_reg_list->GetSize(); + if (num_composite_regs > 0) { + uint32_t composite_offset = UINT32_MAX; + for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; + ++composite_idx) { + ConstString composite_reg_name; + if (composite_reg_list->GetItemAtIndexAsString( + composite_idx, composite_reg_name, nullptr)) { + RegisterInfo *composite_reg_info = + GetRegisterInfo(composite_reg_name); + if (composite_reg_info) { + composite_offset = std::min(composite_offset, + composite_reg_info->byte_offset); + m_value_regs_map[i].push_back( + composite_reg_info->kinds[eRegisterKindLLDB]); + m_invalidate_regs_map[composite_reg_info + ->kinds[eRegisterKindLLDB]] + .push_back(i); + m_invalidate_regs_map[i].push_back( + composite_reg_info->kinds[eRegisterKindLLDB]); + } else { + // TODO: print error invalid slice string that doesn't follow + // the format + printf("error: failed to find composite register by name: " + "\"%s\"\n", + composite_reg_name.GetCString()); } + } else { + printf( + "error: 'composite' list value wasn't a python string\n"); + } } - - if (!success) - { - Clear(); - reg_info_dict->DumpToStdout(); - return 0; + if (composite_offset != UINT32_MAX) { + reg_info.byte_offset = composite_offset; + success = m_value_regs_map.find(i) != m_value_regs_map.end(); + } else { + printf("error: 'composite' registers must specify at least one " + "real register\n"); } + } else { + printf("error: 'composite' list was empty\n"); + } } + } - int64_t bitsize = 0; - if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) - { - Clear(); - printf("error: invalid or missing 'bitsize' key/value pair in register dictionary\n"); - reg_info_dict->DumpToStdout(); - return 0; - } - - reg_info.byte_size = bitsize / 8; - - std::string dwarf_opcode_string; - if (reg_info_dict->GetValueForKeyAsString ("dynamic_size_dwarf_expr_bytes", dwarf_opcode_string)) - { - reg_info.dynamic_size_dwarf_len = dwarf_opcode_string.length () / 2; - assert (reg_info.dynamic_size_dwarf_len > 0); - - std::vector<uint8_t> dwarf_opcode_bytes(reg_info.dynamic_size_dwarf_len); - uint32_t j; - StringExtractor opcode_extractor; - // Swap "dwarf_opcode_string" over into "opcode_extractor" - opcode_extractor.GetStringRef ().swap (dwarf_opcode_string); - uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes); - assert (ret_val == reg_info.dynamic_size_dwarf_len); - - for (j = 0; j < reg_info.dynamic_size_dwarf_len; ++j) - m_dynamic_reg_size_map[i].push_back(dwarf_opcode_bytes[j]); + if (!success) { + Clear(); + reg_info_dict->DumpToStdout(); + return 0; + } + } - reg_info.dynamic_size_dwarf_expr_bytes = m_dynamic_reg_size_map[i].data (); - } + int64_t bitsize = 0; + if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) { + Clear(); + printf("error: invalid or missing 'bitsize' key/value pair in register " + "dictionary\n"); + reg_info_dict->DumpToStdout(); + return 0; + } - std::string format_str; - if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) - { - if (Args::StringToFormat(format_str.c_str(), reg_info.format, NULL).Fail()) - { - Clear(); - printf("error: invalid 'format' value in register dictionary\n"); - reg_info_dict->DumpToStdout(); - return 0; - } - } - else - { - reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format, eFormatHex); - } + reg_info.byte_size = bitsize / 8; - std::string encoding_str; - if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str)) - reg_info.encoding = Args::StringToEncoding(encoding_str.c_str(), eEncodingUint); - else - reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding, eEncodingUint); - - size_t set = 0; - if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) || set >= m_sets.size()) - { - Clear(); - printf("error: invalid 'set' value in register dictionary, valid values are 0 - %i\n", (int)set); - reg_info_dict->DumpToStdout(); - return 0; - } + std::string dwarf_opcode_string; + if (reg_info_dict->GetValueForKeyAsString("dynamic_size_dwarf_expr_bytes", + dwarf_opcode_string)) { + reg_info.dynamic_size_dwarf_len = dwarf_opcode_string.length() / 2; + assert(reg_info.dynamic_size_dwarf_len > 0); - // Fill in the register numbers - reg_info.kinds[lldb::eRegisterKindLLDB] = i; - reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i; - uint32_t eh_frame_regno = LLDB_INVALID_REGNUM; - reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno, LLDB_INVALID_REGNUM); - if (eh_frame_regno == LLDB_INVALID_REGNUM) - reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno, LLDB_INVALID_REGNUM); - reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno; - reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM); - std::string generic_str; - if (reg_info_dict->GetValueForKeyAsString("generic", generic_str)) - reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister(generic_str.c_str()); - else - reg_info_dict->GetValueForKeyAsInteger("generic", reg_info.kinds[lldb::eRegisterKindGeneric], LLDB_INVALID_REGNUM); - - // Check if this register invalidates any other register values when it is modified - StructuredData::Array *invalidate_reg_list = nullptr; - if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs", invalidate_reg_list)) - { - const size_t num_regs = invalidate_reg_list->GetSize(); - if (num_regs > 0) - { - for (uint32_t idx = 0; idx < num_regs; ++idx) - { - ConstString invalidate_reg_name; - uint64_t invalidate_reg_num; - if (invalidate_reg_list->GetItemAtIndexAsString(idx, invalidate_reg_name)) - { - RegisterInfo *invalidate_reg_info = GetRegisterInfo(invalidate_reg_name); - if (invalidate_reg_info) - { - m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]); - } - else - { - // TODO: print error invalid slice string that doesn't follow the format - printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", - invalidate_reg_name.GetCString(), reg_info.name); - } - } - else if (invalidate_reg_list->GetItemAtIndexAsInteger(idx, invalidate_reg_num)) - { - if (invalidate_reg_num != UINT64_MAX) - m_invalidate_regs_map[i].push_back(invalidate_reg_num); - else - printf("error: 'invalidate-regs' list value wasn't a valid integer\n"); - } - else - { - printf("error: 'invalidate-regs' list value wasn't a python string or integer\n"); - } - } - } - else - { - printf("error: 'invalidate-regs' contained an empty list\n"); - } - } + std::vector<uint8_t> dwarf_opcode_bytes(reg_info.dynamic_size_dwarf_len); + uint32_t j; + StringExtractor opcode_extractor; + // Swap "dwarf_opcode_string" over into "opcode_extractor" + opcode_extractor.GetStringRef().swap(dwarf_opcode_string); + uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); + assert(ret_val == reg_info.dynamic_size_dwarf_len); - // Calculate the register offset - const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; - if (m_reg_data_byte_size < end_reg_offset) - m_reg_data_byte_size = end_reg_offset; + for (j = 0; j < reg_info.dynamic_size_dwarf_len; ++j) + m_dynamic_reg_size_map[i].push_back(dwarf_opcode_bytes[j]); - m_regs.push_back(reg_info); - m_set_reg_nums[set].push_back(i); + reg_info.dynamic_size_dwarf_expr_bytes = m_dynamic_reg_size_map[i].data(); } - Finalize(arch); - return m_regs.size(); -} - -void -DynamicRegisterInfo::AddRegister (RegisterInfo ®_info, - ConstString ®_name, - ConstString ®_alt_name, - ConstString &set_name) -{ - assert(!m_finalized); - const uint32_t reg_num = m_regs.size(); - reg_info.name = reg_name.AsCString(); - assert (reg_info.name); - reg_info.alt_name = reg_alt_name.AsCString(NULL); - uint32_t i; - if (reg_info.value_regs) - { - for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i) - m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]); + std::string format_str; + if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) { + if (Args::StringToFormat(format_str.c_str(), reg_info.format, NULL) + .Fail()) { + Clear(); + printf("error: invalid 'format' value in register dictionary\n"); + reg_info_dict->DumpToStdout(); + return 0; + } + } else { + reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format, + eFormatHex); } - if (reg_info.invalidate_regs) - { - for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i) - m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]); + + std::string encoding_str; + if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str)) + reg_info.encoding = + Args::StringToEncoding(encoding_str.c_str(), eEncodingUint); + else + reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding, + eEncodingUint); + + size_t set = 0; + if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) || + set >= m_sets.size()) { + Clear(); + printf("error: invalid 'set' value in register dictionary, valid values " + "are 0 - %i\n", + (int)set); + reg_info_dict->DumpToStdout(); + return 0; } - if (reg_info.dynamic_size_dwarf_expr_bytes) - { - for (i = 0; i < reg_info.dynamic_size_dwarf_len; ++i) - m_dynamic_reg_size_map[reg_num].push_back(reg_info.dynamic_size_dwarf_expr_bytes[i]); - reg_info.dynamic_size_dwarf_expr_bytes = m_dynamic_reg_size_map[reg_num].data (); + // Fill in the register numbers + reg_info.kinds[lldb::eRegisterKindLLDB] = i; + reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i; + uint32_t eh_frame_regno = LLDB_INVALID_REGNUM; + reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno, + LLDB_INVALID_REGNUM); + if (eh_frame_regno == LLDB_INVALID_REGNUM) + reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno, + LLDB_INVALID_REGNUM); + reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno; + reg_info_dict->GetValueForKeyAsInteger( + "dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM); + std::string generic_str; + if (reg_info_dict->GetValueForKeyAsString("generic", generic_str)) + reg_info.kinds[lldb::eRegisterKindGeneric] = + Args::StringToGenericRegister(generic_str.c_str()); + else + reg_info_dict->GetValueForKeyAsInteger( + "generic", reg_info.kinds[lldb::eRegisterKindGeneric], + LLDB_INVALID_REGNUM); + + // Check if this register invalidates any other register values when it is + // modified + StructuredData::Array *invalidate_reg_list = nullptr; + if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs", + invalidate_reg_list)) { + const size_t num_regs = invalidate_reg_list->GetSize(); + if (num_regs > 0) { + for (uint32_t idx = 0; idx < num_regs; ++idx) { + ConstString invalidate_reg_name; + uint64_t invalidate_reg_num; + if (invalidate_reg_list->GetItemAtIndexAsString( + idx, invalidate_reg_name)) { + RegisterInfo *invalidate_reg_info = + GetRegisterInfo(invalidate_reg_name); + if (invalidate_reg_info) { + m_invalidate_regs_map[i].push_back( + invalidate_reg_info->kinds[eRegisterKindLLDB]); + } else { + // TODO: print error invalid slice string that doesn't follow the + // format + printf("error: failed to find a 'invalidate-regs' register for " + "\"%s\" while parsing register \"%s\"\n", + invalidate_reg_name.GetCString(), reg_info.name); + } + } else if (invalidate_reg_list->GetItemAtIndexAsInteger( + idx, invalidate_reg_num)) { + if (invalidate_reg_num != UINT64_MAX) + m_invalidate_regs_map[i].push_back(invalidate_reg_num); + else + printf("error: 'invalidate-regs' list value wasn't a valid " + "integer\n"); + } else { + printf("error: 'invalidate-regs' list value wasn't a python string " + "or integer\n"); + } + } + } else { + printf("error: 'invalidate-regs' contained an empty list\n"); + } } - m_regs.push_back (reg_info); - uint32_t set = GetRegisterSetIndexByName (set_name, true); - assert (set < m_sets.size()); - assert (set < m_set_reg_nums.size()); - assert (set < m_set_names.size()); - m_set_reg_nums[set].push_back(reg_num); - size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; + // Calculate the register offset + const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; if (m_reg_data_byte_size < end_reg_offset) - m_reg_data_byte_size = end_reg_offset; + m_reg_data_byte_size = end_reg_offset; + + m_regs.push_back(reg_info); + m_set_reg_nums[set].push_back(i); + } + Finalize(arch); + return m_regs.size(); } -void -DynamicRegisterInfo::Finalize (const ArchSpec &arch) -{ - if (m_finalized) - return; - - m_finalized = true; - const size_t num_sets = m_sets.size(); - for (size_t set = 0; set < num_sets; ++set) - { - assert (m_sets.size() == m_set_reg_nums.size()); - m_sets[set].num_registers = m_set_reg_nums[set].size(); - m_sets[set].registers = &m_set_reg_nums[set][0]; - } - - // sort and unique all value registers and make sure each is terminated with - // LLDB_INVALID_REGNUM - - for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), end = m_value_regs_map.end(); - pos != end; - ++pos) - { - if (pos->second.size() > 1) - { - std::sort (pos->second.begin(), pos->second.end()); - reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end()); - if (unique_end != pos->second.end()) - pos->second.erase(unique_end, pos->second.end()); - } - assert (!pos->second.empty()); - if (pos->second.back() != LLDB_INVALID_REGNUM) - pos->second.push_back(LLDB_INVALID_REGNUM); - } - - // Now update all value_regs with each register info as needed - const size_t num_regs = m_regs.size(); - for (size_t i=0; i<num_regs; ++i) - { - if (m_value_regs_map.find(i) != m_value_regs_map.end()) - m_regs[i].value_regs = m_value_regs_map[i].data(); - else - m_regs[i].value_regs = NULL; - } +void DynamicRegisterInfo::AddRegister(RegisterInfo ®_info, + ConstString ®_name, + ConstString ®_alt_name, + ConstString &set_name) { + assert(!m_finalized); + const uint32_t reg_num = m_regs.size(); + reg_info.name = reg_name.AsCString(); + assert(reg_info.name); + reg_info.alt_name = reg_alt_name.AsCString(NULL); + uint32_t i; + if (reg_info.value_regs) { + for (i = 0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i) + m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]); + } + if (reg_info.invalidate_regs) { + for (i = 0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i) + m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]); + } + if (reg_info.dynamic_size_dwarf_expr_bytes) { + for (i = 0; i < reg_info.dynamic_size_dwarf_len; ++i) + m_dynamic_reg_size_map[reg_num].push_back( + reg_info.dynamic_size_dwarf_expr_bytes[i]); + + reg_info.dynamic_size_dwarf_expr_bytes = + m_dynamic_reg_size_map[reg_num].data(); + } + + m_regs.push_back(reg_info); + uint32_t set = GetRegisterSetIndexByName(set_name, true); + assert(set < m_sets.size()); + assert(set < m_set_reg_nums.size()); + assert(set < m_set_names.size()); + m_set_reg_nums[set].push_back(reg_num); + size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; + if (m_reg_data_byte_size < end_reg_offset) + m_reg_data_byte_size = end_reg_offset; +} - // Expand all invalidation dependencies - for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end(); - pos != end; - ++pos) - { - const uint32_t reg_num = pos->first; - - if (m_regs[reg_num].value_regs) - { - reg_num_collection extra_invalid_regs; - for (const uint32_t invalidate_reg_num : pos->second) - { - reg_to_regs_map::iterator invalidate_pos = m_invalidate_regs_map.find(invalidate_reg_num); - if (invalidate_pos != m_invalidate_regs_map.end()) - { - for (const uint32_t concrete_invalidate_reg_num : invalidate_pos->second) - { - if (concrete_invalidate_reg_num != reg_num) - extra_invalid_regs.push_back(concrete_invalidate_reg_num); - } - } - } - pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), extra_invalid_regs.end()); - } +void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { + if (m_finalized) + return; + + m_finalized = true; + const size_t num_sets = m_sets.size(); + for (size_t set = 0; set < num_sets; ++set) { + assert(m_sets.size() == m_set_reg_nums.size()); + m_sets[set].num_registers = m_set_reg_nums[set].size(); + m_sets[set].registers = &m_set_reg_nums[set][0]; + } + + // sort and unique all value registers and make sure each is terminated with + // LLDB_INVALID_REGNUM + + for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), + end = m_value_regs_map.end(); + pos != end; ++pos) { + if (pos->second.size() > 1) { + std::sort(pos->second.begin(), pos->second.end()); + reg_num_collection::iterator unique_end = + std::unique(pos->second.begin(), pos->second.end()); + if (unique_end != pos->second.end()) + pos->second.erase(unique_end, pos->second.end()); } - - // sort and unique all invalidate registers and make sure each is terminated with - // LLDB_INVALID_REGNUM - for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end(); - pos != end; - ++pos) - { - if (pos->second.size() > 1) - { - std::sort (pos->second.begin(), pos->second.end()); - reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end()); - if (unique_end != pos->second.end()) - pos->second.erase(unique_end, pos->second.end()); + assert(!pos->second.empty()); + if (pos->second.back() != LLDB_INVALID_REGNUM) + pos->second.push_back(LLDB_INVALID_REGNUM); + } + + // Now update all value_regs with each register info as needed + const size_t num_regs = m_regs.size(); + for (size_t i = 0; i < num_regs; ++i) { + if (m_value_regs_map.find(i) != m_value_regs_map.end()) + m_regs[i].value_regs = m_value_regs_map[i].data(); + else + m_regs[i].value_regs = NULL; + } + + // Expand all invalidation dependencies + for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), + end = m_invalidate_regs_map.end(); + pos != end; ++pos) { + const uint32_t reg_num = pos->first; + + if (m_regs[reg_num].value_regs) { + reg_num_collection extra_invalid_regs; + for (const uint32_t invalidate_reg_num : pos->second) { + reg_to_regs_map::iterator invalidate_pos = + m_invalidate_regs_map.find(invalidate_reg_num); + if (invalidate_pos != m_invalidate_regs_map.end()) { + for (const uint32_t concrete_invalidate_reg_num : + invalidate_pos->second) { + if (concrete_invalidate_reg_num != reg_num) + extra_invalid_regs.push_back(concrete_invalidate_reg_num); + } } - assert (!pos->second.empty()); - if (pos->second.back() != LLDB_INVALID_REGNUM) - pos->second.push_back(LLDB_INVALID_REGNUM); + } + pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), + extra_invalid_regs.end()); } - - // Now update all invalidate_regs with each register info as needed - for (size_t i=0; i<num_regs; ++i) - { - if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end()) - m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data(); - else - m_regs[i].invalidate_regs = NULL; + } + + // sort and unique all invalidate registers and make sure each is terminated + // with + // LLDB_INVALID_REGNUM + for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), + end = m_invalidate_regs_map.end(); + pos != end; ++pos) { + if (pos->second.size() > 1) { + std::sort(pos->second.begin(), pos->second.end()); + reg_num_collection::iterator unique_end = + std::unique(pos->second.begin(), pos->second.end()); + if (unique_end != pos->second.end()) + pos->second.erase(unique_end, pos->second.end()); } - - // Check if we need to automatically set the generic registers in case - // they weren't set - bool generic_regs_specified = false; - for (const auto ®: m_regs) - { - if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) - { - generic_regs_specified = true; - break; - } + assert(!pos->second.empty()); + if (pos->second.back() != LLDB_INVALID_REGNUM) + pos->second.push_back(LLDB_INVALID_REGNUM); + } + + // Now update all invalidate_regs with each register info as needed + for (size_t i = 0; i < num_regs; ++i) { + if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end()) + m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data(); + else + m_regs[i].invalidate_regs = NULL; + } + + // Check if we need to automatically set the generic registers in case + // they weren't set + bool generic_regs_specified = false; + for (const auto ® : m_regs) { + if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { + generic_regs_specified = true; + break; } - - if (!generic_regs_specified) - { - switch (arch.GetMachine()) - { - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - for (auto ®: m_regs) - { - if (strcmp(reg.name, "pc") == 0) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - else if ((strcmp(reg.name, "fp") == 0) || (strcmp(reg.name, "x29") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if ((strcmp(reg.name, "lr") == 0) || (strcmp(reg.name, "x30") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; - else if ((strcmp(reg.name, "sp") == 0) || (strcmp(reg.name, "x31") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; - else if (strcmp(reg.name, "cpsr") == 0) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - } - break; - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - for (auto ®: m_regs) - { - if ((strcmp(reg.name, "pc") == 0) || (strcmp(reg.name, "r15") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - else if ((strcmp(reg.name, "sp") == 0) || (strcmp(reg.name, "r13") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; - else if ((strcmp(reg.name, "lr") == 0) || (strcmp(reg.name, "r14") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; - else if ((strcmp(reg.name, "r7") == 0) && arch.GetTriple().getVendor() == llvm::Triple::Apple) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if ((strcmp(reg.name, "r11") == 0) && arch.GetTriple().getVendor() != llvm::Triple::Apple) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if (strcmp(reg.name, "fp") == 0) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if (strcmp(reg.name, "cpsr") == 0) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - } - break; - - case llvm::Triple::x86: - for (auto ®: m_regs) - { - if ((strcmp(reg.name, "eip") == 0) || (strcmp(reg.name, "pc") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - else if ((strcmp(reg.name, "esp") == 0) || (strcmp(reg.name, "sp") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; - else if ((strcmp(reg.name, "ebp") == 0) || (strcmp(reg.name, "fp") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if ((strcmp(reg.name, "eflags") == 0) || (strcmp(reg.name, "flags") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - } - break; - - case llvm::Triple::x86_64: - for (auto ®: m_regs) - { - if ((strcmp(reg.name, "rip") == 0) || (strcmp(reg.name, "pc") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - else if ((strcmp(reg.name, "rsp") == 0) || (strcmp(reg.name, "sp") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; - else if ((strcmp(reg.name, "rbp") == 0) || (strcmp(reg.name, "fp") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; - else if ((strcmp(reg.name, "rflags") == 0) || (strcmp(reg.name, "flags") == 0)) - reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - } - break; - - default: - break; - } + } + + if (!generic_regs_specified) { + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + for (auto ® : m_regs) { + if (strcmp(reg.name, "pc") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + else if ((strcmp(reg.name, "fp") == 0) || + (strcmp(reg.name, "x29") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if ((strcmp(reg.name, "lr") == 0) || + (strcmp(reg.name, "x30") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; + else if ((strcmp(reg.name, "sp") == 0) || + (strcmp(reg.name, "x31") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + else if (strcmp(reg.name, "cpsr") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + } + break; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + for (auto ® : m_regs) { + if ((strcmp(reg.name, "pc") == 0) || (strcmp(reg.name, "r15") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + else if ((strcmp(reg.name, "sp") == 0) || + (strcmp(reg.name, "r13") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + else if ((strcmp(reg.name, "lr") == 0) || + (strcmp(reg.name, "r14") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; + else if ((strcmp(reg.name, "r7") == 0) && + arch.GetTriple().getVendor() == llvm::Triple::Apple) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if ((strcmp(reg.name, "r11") == 0) && + arch.GetTriple().getVendor() != llvm::Triple::Apple) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if (strcmp(reg.name, "fp") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if (strcmp(reg.name, "cpsr") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + } + break; + + case llvm::Triple::x86: + for (auto ® : m_regs) { + if ((strcmp(reg.name, "eip") == 0) || (strcmp(reg.name, "pc") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + else if ((strcmp(reg.name, "esp") == 0) || + (strcmp(reg.name, "sp") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + else if ((strcmp(reg.name, "ebp") == 0) || + (strcmp(reg.name, "fp") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if ((strcmp(reg.name, "eflags") == 0) || + (strcmp(reg.name, "flags") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + } + break; + + case llvm::Triple::x86_64: + for (auto ® : m_regs) { + if ((strcmp(reg.name, "rip") == 0) || (strcmp(reg.name, "pc") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + else if ((strcmp(reg.name, "rsp") == 0) || + (strcmp(reg.name, "sp") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + else if ((strcmp(reg.name, "rbp") == 0) || + (strcmp(reg.name, "fp") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if ((strcmp(reg.name, "rflags") == 0) || + (strcmp(reg.name, "flags") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + } + break; + + default: + break; } + } } -size_t -DynamicRegisterInfo::GetNumRegisters() const -{ - return m_regs.size(); -} +size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); } -size_t -DynamicRegisterInfo::GetNumRegisterSets() const -{ - return m_sets.size(); -} +size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); } -size_t -DynamicRegisterInfo::GetRegisterDataByteSize() const -{ - return m_reg_data_byte_size; +size_t DynamicRegisterInfo::GetRegisterDataByteSize() const { + return m_reg_data_byte_size; } const RegisterInfo * -DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const -{ - if (i < m_regs.size()) - return &m_regs[i]; - return NULL; +DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const { + if (i < m_regs.size()) + return &m_regs[i]; + return NULL; } -RegisterInfo * -DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) -{ - if (i < m_regs.size()) - return &m_regs[i]; - return NULL; +RegisterInfo *DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) { + if (i < m_regs.size()) + return &m_regs[i]; + return NULL; } -const RegisterSet * -DynamicRegisterInfo::GetRegisterSet (uint32_t i) const -{ - if (i < m_sets.size()) - return &m_sets[i]; - return NULL; +const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const { + if (i < m_sets.size()) + return &m_sets[i]; + return NULL; } -uint32_t -DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create) -{ - name_collection::iterator pos, end = m_set_names.end(); - for (pos = m_set_names.begin(); pos != end; ++pos) - { - if (*pos == set_name) - return std::distance (m_set_names.begin(), pos); - } - - m_set_names.push_back(set_name); - m_set_reg_nums.resize(m_set_reg_nums.size()+1); - RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; - m_sets.push_back (new_set); - return m_sets.size() - 1; +uint32_t DynamicRegisterInfo::GetRegisterSetIndexByName(ConstString &set_name, + bool can_create) { + name_collection::iterator pos, end = m_set_names.end(); + for (pos = m_set_names.begin(); pos != end; ++pos) { + if (*pos == set_name) + return std::distance(m_set_names.begin(), pos); + } + + m_set_names.push_back(set_name); + m_set_reg_nums.resize(m_set_reg_nums.size() + 1); + RegisterSet new_set = {set_name.AsCString(), NULL, 0, NULL}; + m_sets.push_back(new_set); + return m_sets.size() - 1; } uint32_t -DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const -{ - reg_collection::const_iterator pos, end = m_regs.end(); - for (pos = m_regs.begin(); pos != end; ++pos) - { - if (pos->kinds[kind] == num) - return std::distance (m_regs.begin(), pos); - } - - return LLDB_INVALID_REGNUM; +DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) const { + reg_collection::const_iterator pos, end = m_regs.end(); + for (pos = m_regs.begin(); pos != end; ++pos) { + if (pos->kinds[kind] == num) + return std::distance(m_regs.begin(), pos); + } + + return LLDB_INVALID_REGNUM; } -void -DynamicRegisterInfo::Clear() -{ - m_regs.clear(); - m_sets.clear(); - m_set_reg_nums.clear(); - m_set_names.clear(); - m_value_regs_map.clear(); - m_invalidate_regs_map.clear(); - m_dynamic_reg_size_map.clear(); - m_reg_data_byte_size = 0; - m_finalized = false; +void DynamicRegisterInfo::Clear() { + m_regs.clear(); + m_sets.clear(); + m_set_reg_nums.clear(); + m_set_names.clear(); + m_value_regs_map.clear(); + m_invalidate_regs_map.clear(); + m_dynamic_reg_size_map.clear(); + m_reg_data_byte_size = 0; + m_finalized = false; } -void -DynamicRegisterInfo::Dump () const -{ - StreamFile s(stdout, false); - const size_t num_regs = m_regs.size(); - s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n", - static_cast<const void*>(this), static_cast<uint64_t>(num_regs)); - for (size_t i=0; i<num_regs; ++i) - { - s.Printf("[%3" PRIu64 "] name = %-10s", (uint64_t)i, m_regs[i].name); - s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s", - m_regs[i].byte_size, - m_regs[i].byte_offset, - m_regs[i].encoding, - FormatManager::GetFormatAsCString (m_regs[i].format)); - if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM) - s.Printf(", process plugin = %3u", m_regs[i].kinds[eRegisterKindProcessPlugin]); - if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) - s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]); - if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) - s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]); - if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) - s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]); - if (m_regs[i].alt_name) - s.Printf(", alt-name = %s", m_regs[i].alt_name); - if (m_regs[i].value_regs) - { - s.Printf(", value_regs = [ "); - for (size_t j=0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) - { - s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name); - } - s.Printf("]"); - } - if (m_regs[i].invalidate_regs) - { - s.Printf(", invalidate_regs = [ "); - for (size_t j=0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; ++j) - { - s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name); - } - s.Printf("]"); - } - s.EOL(); +void DynamicRegisterInfo::Dump() const { + StreamFile s(stdout, false); + const size_t num_regs = m_regs.size(); + s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n", + static_cast<const void *>(this), static_cast<uint64_t>(num_regs)); + for (size_t i = 0; i < num_regs; ++i) { + s.Printf("[%3" PRIu64 "] name = %-10s", (uint64_t)i, m_regs[i].name); + s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s", + m_regs[i].byte_size, m_regs[i].byte_offset, m_regs[i].encoding, + FormatManager::GetFormatAsCString(m_regs[i].format)); + if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM) + s.Printf(", process plugin = %3u", + m_regs[i].kinds[eRegisterKindProcessPlugin]); + if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) + s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]); + if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) + s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]); + if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) + s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]); + if (m_regs[i].alt_name) + s.Printf(", alt-name = %s", m_regs[i].alt_name); + if (m_regs[i].value_regs) { + s.Printf(", value_regs = [ "); + for (size_t j = 0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) { + s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name); + } + s.Printf("]"); } - - const size_t num_sets = m_sets.size(); - s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n", - static_cast<const void*>(this), static_cast<uint64_t>(num_sets)); - for (size_t i=0; i<num_sets; ++i) - { - s.Printf("set[%" PRIu64 "] name = %s, regs = [", (uint64_t)i, m_sets[i].name); - for (size_t idx=0; idx<m_sets[i].num_registers; ++idx) - { - s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name); - } - s.Printf("]\n"); + if (m_regs[i].invalidate_regs) { + s.Printf(", invalidate_regs = [ "); + for (size_t j = 0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; + ++j) { + s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name); + } + s.Printf("]"); + } + s.EOL(); + } + + const size_t num_sets = m_sets.size(); + s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n", + static_cast<const void *>(this), static_cast<uint64_t>(num_sets)); + for (size_t i = 0; i < num_sets; ++i) { + s.Printf("set[%" PRIu64 "] name = %s, regs = [", (uint64_t)i, + m_sets[i].name); + for (size_t idx = 0; idx < m_sets[i].num_registers; ++idx) { + s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name); } + s.Printf("]\n"); + } } - - -lldb_private::RegisterInfo * -DynamicRegisterInfo::GetRegisterInfo (const lldb_private::ConstString ®_name) -{ - for (auto ®_info : m_regs) - { - // We can use pointer comparison since we used a ConstString to set - // the "name" member in AddRegister() - if (reg_info.name == reg_name.GetCString()) - { - return ®_info; - } +lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo( + const lldb_private::ConstString ®_name) { + for (auto ®_info : m_regs) { + // We can use pointer comparison since we used a ConstString to set + // the "name" member in AddRegister() + if (reg_info.name == reg_name.GetCString()) { + return ®_info; } - return NULL; + } + return NULL; } diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h index d97dc136bd6..e5c22fe484e 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -12,93 +12,82 @@ // C Includes // C++ Includes -#include <vector> #include <map> +#include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/StructuredData.h" +#include "lldb/lldb-private.h" -class DynamicRegisterInfo -{ +class DynamicRegisterInfo { public: - DynamicRegisterInfo (); + DynamicRegisterInfo(); - DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, - const lldb_private::ArchSpec &arch); + DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, + const lldb_private::ArchSpec &arch); - virtual - ~DynamicRegisterInfo (); + virtual ~DynamicRegisterInfo(); - size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, - const lldb_private::ArchSpec &arch); + size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, + const lldb_private::ArchSpec &arch); - void - AddRegister (lldb_private::RegisterInfo ®_info, - lldb_private::ConstString ®_name, - lldb_private::ConstString ®_alt_name, - lldb_private::ConstString &set_name); + void AddRegister(lldb_private::RegisterInfo ®_info, + lldb_private::ConstString ®_name, + lldb_private::ConstString ®_alt_name, + lldb_private::ConstString &set_name); - void - Finalize (const lldb_private::ArchSpec &arch); + void Finalize(const lldb_private::ArchSpec &arch); - size_t - GetNumRegisters() const; + size_t GetNumRegisters() const; - size_t - GetNumRegisterSets() const; + size_t GetNumRegisterSets() const; - size_t - GetRegisterDataByteSize() const; + size_t GetRegisterDataByteSize() const; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex (uint32_t i) const; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(uint32_t i) const; - lldb_private::RegisterInfo * - GetRegisterInfoAtIndex (uint32_t i); + lldb_private::RegisterInfo *GetRegisterInfoAtIndex(uint32_t i); - const lldb_private::RegisterSet * - GetRegisterSet (uint32_t i) const; + const lldb_private::RegisterSet *GetRegisterSet(uint32_t i) const; - uint32_t - GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create); + uint32_t GetRegisterSetIndexByName(lldb_private::ConstString &set_name, + bool can_create); - uint32_t - ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const; + uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) const; - void - Dump () const; + void Dump() const; - void - Clear(); + void Clear(); protected: - //------------------------------------------------------------------ - // Classes that inherit from DynamicRegisterInfo can see and modify these - //------------------------------------------------------------------ - typedef std::vector <lldb_private::RegisterInfo> reg_collection; - typedef std::vector <lldb_private::RegisterSet> set_collection; - typedef std::vector <uint32_t> reg_num_collection; - typedef std::vector <reg_num_collection> set_reg_num_collection; - typedef std::vector <lldb_private::ConstString> name_collection; - typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map; - typedef std::vector <uint8_t> dwarf_opcode; - typedef std::map<uint32_t, dwarf_opcode> dynamic_reg_size_map; - - lldb_private::RegisterInfo * - GetRegisterInfo (const lldb_private::ConstString ®_name); - - reg_collection m_regs; - set_collection m_sets; - set_reg_num_collection m_set_reg_nums; - name_collection m_set_names; - reg_to_regs_map m_value_regs_map; - reg_to_regs_map m_invalidate_regs_map; - dynamic_reg_size_map m_dynamic_reg_size_map; - size_t m_reg_data_byte_size; // The number of bytes required to store all registers - bool m_finalized; + //------------------------------------------------------------------ + // Classes that inherit from DynamicRegisterInfo can see and modify these + //------------------------------------------------------------------ + typedef std::vector<lldb_private::RegisterInfo> reg_collection; + typedef std::vector<lldb_private::RegisterSet> set_collection; + typedef std::vector<uint32_t> reg_num_collection; + typedef std::vector<reg_num_collection> set_reg_num_collection; + typedef std::vector<lldb_private::ConstString> name_collection; + typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map; + typedef std::vector<uint8_t> dwarf_opcode; + typedef std::map<uint32_t, dwarf_opcode> dynamic_reg_size_map; + + lldb_private::RegisterInfo * + GetRegisterInfo(const lldb_private::ConstString ®_name); + + reg_collection m_regs; + set_collection m_sets; + set_reg_num_collection m_set_reg_nums; + name_collection m_set_names; + reg_to_regs_map m_value_regs_map; + reg_to_regs_map m_invalidate_regs_map; + dynamic_reg_size_map m_dynamic_reg_size_map; + size_t m_reg_data_byte_size; // The number of bytes required to store all + // registers + bool m_finalized; }; -#endif // lldb_DynamicRegisterInfo_h_ +#endif // lldb_DynamicRegisterInfo_h_ diff --git a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp index e575e2c6a49..f695a11c975 100644 --- a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp @@ -15,81 +15,77 @@ using namespace lldb_private; -FreeBSDSignals::FreeBSDSignals() - : UnixSignals() -{ - Reset(); -} +FreeBSDSignals::FreeBSDSignals() : UnixSignals() { Reset(); } -void -FreeBSDSignals::Reset() -{ - UnixSignals::Reset(); +void FreeBSDSignals::Reset() { + UnixSignals::Reset(); - // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION - // ====== ============ ======== ====== ====== =================================================== - AddSignal (32, "SIGTHR", false, false, false, "thread interrupt"); - AddSignal (33, "SIGLIBRT", false, false, false, "reserved by real-time library"); - AddSignal (65, "SIGRTMIN", false, false, false, "real time signal 0"); - AddSignal (66, "SIGRTMIN+1", false, false, false, "real time signal 1"); - AddSignal (67, "SIGRTMIN+2", false, false, false, "real time signal 2"); - AddSignal (68, "SIGRTMIN+3", false, false, false, "real time signal 3"); - AddSignal (69, "SIGRTMIN+4", false, false, false, "real time signal 4"); - AddSignal (70, "SIGRTMIN+5", false, false, false, "real time signal 5"); - AddSignal (71, "SIGRTMIN+6", false, false, false, "real time signal 6"); - AddSignal (72, "SIGRTMIN+7", false, false, false, "real time signal 7"); - AddSignal (73, "SIGRTMIN+8", false, false, false, "real time signal 8"); - AddSignal (74, "SIGRTMIN+9", false, false, false, "real time signal 9"); - AddSignal (75, "SIGRTMIN+10", false, false, false, "real time signal 10"); - AddSignal (76, "SIGRTMIN+11", false, false, false, "real time signal 11"); - AddSignal (77, "SIGRTMIN+12", false, false, false, "real time signal 12"); - AddSignal (78, "SIGRTMIN+13", false, false, false, "real time signal 13"); - AddSignal (79, "SIGRTMIN+14", false, false, false, "real time signal 14"); - AddSignal (80, "SIGRTMIN+15", false, false, false, "real time signal 15"); - AddSignal (81, "SIGRTMIN+16", false, false, false, "real time signal 16"); - AddSignal (82, "SIGRTMIN+17", false, false, false, "real time signal 17"); - AddSignal (83, "SIGRTMIN+18", false, false, false, "real time signal 18"); - AddSignal (84, "SIGRTMIN+19", false, false, false, "real time signal 19"); - AddSignal (85, "SIGRTMIN+20", false, false, false, "real time signal 20"); - AddSignal (86, "SIGRTMIN+21", false, false, false, "real time signal 21"); - AddSignal (87, "SIGRTMIN+22", false, false, false, "real time signal 22"); - AddSignal (88, "SIGRTMIN+23", false, false, false, "real time signal 23"); - AddSignal (89, "SIGRTMIN+24", false, false, false, "real time signal 24"); - AddSignal (90, "SIGRTMIN+25", false, false, false, "real time signal 25"); - AddSignal (91, "SIGRTMIN+26", false, false, false, "real time signal 26"); - AddSignal (92, "SIGRTMIN+27", false, false, false, "real time signal 27"); - AddSignal (93, "SIGRTMIN+28", false, false, false, "real time signal 28"); - AddSignal (94, "SIGRTMIN+29", false, false, false, "real time signal 29"); - AddSignal (95, "SIGRTMIN+30", false, false, false, "real time signal 30"); - AddSignal (96, "SIGRTMAX-30", false, false, false, "real time signal 31"); - AddSignal (97, "SIGRTMAX-29", false, false, false, "real time signal 32"); - AddSignal (98, "SIGRTMAX-28", false, false, false, "real time signal 33"); - AddSignal (99, "SIGRTMAX-27", false, false, false, "real time signal 34"); - AddSignal (100, "SIGRTMAX-26", false, false, false, "real time signal 35"); - AddSignal (101, "SIGRTMAX-25", false, false, false, "real time signal 36"); - AddSignal (102, "SIGRTMAX-24", false, false, false, "real time signal 37"); - AddSignal (103, "SIGRTMAX-23", false, false, false, "real time signal 38"); - AddSignal (104, "SIGRTMAX-22", false, false, false, "real time signal 39"); - AddSignal (105, "SIGRTMAX-21", false, false, false, "real time signal 40"); - AddSignal (106, "SIGRTMAX-20", false, false, false, "real time signal 41"); - AddSignal (107, "SIGRTMAX-19", false, false, false, "real time signal 42"); - AddSignal (108, "SIGRTMAX-18", false, false, false, "real time signal 43"); - AddSignal (109, "SIGRTMAX-17", false, false, false, "real time signal 44"); - AddSignal (110, "SIGRTMAX-16", false, false, false, "real time signal 45"); - AddSignal (111, "SIGRTMAX-15", false, false, false, "real time signal 46"); - AddSignal (112, "SIGRTMAX-14", false, false, false, "real time signal 47"); - AddSignal (113, "SIGRTMAX-13", false, false, false, "real time signal 48"); - AddSignal (114, "SIGRTMAX-12", false, false, false, "real time signal 49"); - AddSignal (115, "SIGRTMAX-11", false, false, false, "real time signal 50"); - AddSignal (116, "SIGRTMAX-10", false, false, false, "real time signal 51"); - AddSignal (117, "SIGRTMAX-9", false, false, false, "real time signal 52"); - AddSignal (118, "SIGRTMAX-8", false, false, false, "real time signal 53"); - AddSignal (119, "SIGRTMAX-7", false, false, false, "real time signal 54"); - AddSignal (120, "SIGRTMAX-6", false, false, false, "real time signal 55"); - AddSignal (121, "SIGRTMAX-5", false, false, false, "real time signal 56"); - AddSignal (122, "SIGRTMAX-4", false, false, false, "real time signal 57"); - AddSignal (123, "SIGRTMAX-3", false, false, false, "real time signal 58"); - AddSignal (124, "SIGRTMAX-2", false, false, false, "real time signal 59"); - AddSignal (125, "SIGRTMAX-1", false, false, false, "real time signal 60"); - AddSignal (126, "SIGRTMAX", false, false, false, "real time signal 61"); + // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION + // ====== ============ ======== ====== ====== + // =================================================== + AddSignal(32, "SIGTHR", false, false, false, "thread interrupt"); + AddSignal(33, "SIGLIBRT", false, false, false, + "reserved by real-time library"); + AddSignal(65, "SIGRTMIN", false, false, false, "real time signal 0"); + AddSignal(66, "SIGRTMIN+1", false, false, false, "real time signal 1"); + AddSignal(67, "SIGRTMIN+2", false, false, false, "real time signal 2"); + AddSignal(68, "SIGRTMIN+3", false, false, false, "real time signal 3"); + AddSignal(69, "SIGRTMIN+4", false, false, false, "real time signal 4"); + AddSignal(70, "SIGRTMIN+5", false, false, false, "real time signal 5"); + AddSignal(71, "SIGRTMIN+6", false, false, false, "real time signal 6"); + AddSignal(72, "SIGRTMIN+7", false, false, false, "real time signal 7"); + AddSignal(73, "SIGRTMIN+8", false, false, false, "real time signal 8"); + AddSignal(74, "SIGRTMIN+9", false, false, false, "real time signal 9"); + AddSignal(75, "SIGRTMIN+10", false, false, false, "real time signal 10"); + AddSignal(76, "SIGRTMIN+11", false, false, false, "real time signal 11"); + AddSignal(77, "SIGRTMIN+12", false, false, false, "real time signal 12"); + AddSignal(78, "SIGRTMIN+13", false, false, false, "real time signal 13"); + AddSignal(79, "SIGRTMIN+14", false, false, false, "real time signal 14"); + AddSignal(80, "SIGRTMIN+15", false, false, false, "real time signal 15"); + AddSignal(81, "SIGRTMIN+16", false, false, false, "real time signal 16"); + AddSignal(82, "SIGRTMIN+17", false, false, false, "real time signal 17"); + AddSignal(83, "SIGRTMIN+18", false, false, false, "real time signal 18"); + AddSignal(84, "SIGRTMIN+19", false, false, false, "real time signal 19"); + AddSignal(85, "SIGRTMIN+20", false, false, false, "real time signal 20"); + AddSignal(86, "SIGRTMIN+21", false, false, false, "real time signal 21"); + AddSignal(87, "SIGRTMIN+22", false, false, false, "real time signal 22"); + AddSignal(88, "SIGRTMIN+23", false, false, false, "real time signal 23"); + AddSignal(89, "SIGRTMIN+24", false, false, false, "real time signal 24"); + AddSignal(90, "SIGRTMIN+25", false, false, false, "real time signal 25"); + AddSignal(91, "SIGRTMIN+26", false, false, false, "real time signal 26"); + AddSignal(92, "SIGRTMIN+27", false, false, false, "real time signal 27"); + AddSignal(93, "SIGRTMIN+28", false, false, false, "real time signal 28"); + AddSignal(94, "SIGRTMIN+29", false, false, false, "real time signal 29"); + AddSignal(95, "SIGRTMIN+30", false, false, false, "real time signal 30"); + AddSignal(96, "SIGRTMAX-30", false, false, false, "real time signal 31"); + AddSignal(97, "SIGRTMAX-29", false, false, false, "real time signal 32"); + AddSignal(98, "SIGRTMAX-28", false, false, false, "real time signal 33"); + AddSignal(99, "SIGRTMAX-27", false, false, false, "real time signal 34"); + AddSignal(100, "SIGRTMAX-26", false, false, false, "real time signal 35"); + AddSignal(101, "SIGRTMAX-25", false, false, false, "real time signal 36"); + AddSignal(102, "SIGRTMAX-24", false, false, false, "real time signal 37"); + AddSignal(103, "SIGRTMAX-23", false, false, false, "real time signal 38"); + AddSignal(104, "SIGRTMAX-22", false, false, false, "real time signal 39"); + AddSignal(105, "SIGRTMAX-21", false, false, false, "real time signal 40"); + AddSignal(106, "SIGRTMAX-20", false, false, false, "real time signal 41"); + AddSignal(107, "SIGRTMAX-19", false, false, false, "real time signal 42"); + AddSignal(108, "SIGRTMAX-18", false, false, false, "real time signal 43"); + AddSignal(109, "SIGRTMAX-17", false, false, false, "real time signal 44"); + AddSignal(110, "SIGRTMAX-16", false, false, false, "real time signal 45"); + AddSignal(111, "SIGRTMAX-15", false, false, false, "real time signal 46"); + AddSignal(112, "SIGRTMAX-14", false, false, false, "real time signal 47"); + AddSignal(113, "SIGRTMAX-13", false, false, false, "real time signal 48"); + AddSignal(114, "SIGRTMAX-12", false, false, false, "real time signal 49"); + AddSignal(115, "SIGRTMAX-11", false, false, false, "real time signal 50"); + AddSignal(116, "SIGRTMAX-10", false, false, false, "real time signal 51"); + AddSignal(117, "SIGRTMAX-9", false, false, false, "real time signal 52"); + AddSignal(118, "SIGRTMAX-8", false, false, false, "real time signal 53"); + AddSignal(119, "SIGRTMAX-7", false, false, false, "real time signal 54"); + AddSignal(120, "SIGRTMAX-6", false, false, false, "real time signal 55"); + AddSignal(121, "SIGRTMAX-5", false, false, false, "real time signal 56"); + AddSignal(122, "SIGRTMAX-4", false, false, false, "real time signal 57"); + AddSignal(123, "SIGRTMAX-3", false, false, false, "real time signal 58"); + AddSignal(124, "SIGRTMAX-2", false, false, false, "real time signal 59"); + AddSignal(125, "SIGRTMAX-1", false, false, false, "real time signal 60"); + AddSignal(126, "SIGRTMAX", false, false, false, "real time signal 61"); } diff --git a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h index b715c62c81e..8ec96e824f7 100644 --- a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h +++ b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h @@ -16,14 +16,12 @@ namespace lldb_private { /// FreeBSD specific set of Unix signals. -class FreeBSDSignals : public UnixSignals -{ +class FreeBSDSignals : public UnixSignals { public: - FreeBSDSignals(); + FreeBSDSignals(); private: - void - Reset() override; + void Reset() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp index 4e355c63b3a..abcc8a38669 100644 --- a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp @@ -14,19 +14,9 @@ using namespace lldb_private; -GDBRemoteSignals::GDBRemoteSignals() - : UnixSignals() -{ - Reset(); -} +GDBRemoteSignals::GDBRemoteSignals() : UnixSignals() { Reset(); } GDBRemoteSignals::GDBRemoteSignals(const lldb::UnixSignalsSP &rhs) - : UnixSignals(*rhs) -{ -} + : UnixSignals(*rhs) {} -void -GDBRemoteSignals::Reset() -{ - m_signals.clear(); -} +void GDBRemoteSignals::Reset() { m_signals.clear(); } diff --git a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h index bbb631a1409..5900fa75d6f 100644 --- a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h +++ b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h @@ -19,16 +19,14 @@ namespace lldb_private { /// Empty set of Unix signals to be filled by PlatformRemoteGDBServer -class GDBRemoteSignals : public UnixSignals -{ +class GDBRemoteSignals : public UnixSignals { public: - GDBRemoteSignals(); + GDBRemoteSignals(); - GDBRemoteSignals(const lldb::UnixSignalsSP &rhs); + GDBRemoteSignals(const lldb::UnixSignalsSP &rhs); private: - void - Reset() override; + void Reset() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp index 956539da219..d27a7b0da94 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp @@ -9,91 +9,75 @@ #include "lldb/lldb-private.h" -#include "Plugins/Process/Utility/HistoryUnwind.h" #include "Plugins/Process/Utility/HistoryThread.h" +#include "Plugins/Process/Utility/HistoryUnwind.h" #include "Plugins/Process/Utility/RegisterContextHistory.h" #include "lldb/Core/Log.h" -#include "lldb/Target/StackFrameList.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StackFrameList.h" using namespace lldb; using namespace lldb_private; // Constructor -HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, - uint32_t stop_id, bool stop_id_is_valid) - : Thread(process, tid, true), - m_framelist_mutex(), - m_framelist(), - m_pcs(pcs), - m_stop_id(stop_id), - m_stop_id_is_valid(stop_id_is_valid), - m_extended_unwind_token(LLDB_INVALID_ADDRESS), - m_queue_name(), - m_thread_name(), - m_originating_unique_thread_id(tid), - m_queue_id(LLDB_INVALID_QUEUE_ID) -{ - m_unwinder_ap.reset(new HistoryUnwind(*this, pcs, stop_id_is_valid)); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p HistoryThread::HistoryThread", static_cast<void *>(this)); +HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, + std::vector<lldb::addr_t> pcs, uint32_t stop_id, + bool stop_id_is_valid) + : Thread(process, tid, true), m_framelist_mutex(), m_framelist(), + m_pcs(pcs), m_stop_id(stop_id), m_stop_id_is_valid(stop_id_is_valid), + m_extended_unwind_token(LLDB_INVALID_ADDRESS), m_queue_name(), + m_thread_name(), m_originating_unique_thread_id(tid), + m_queue_id(LLDB_INVALID_QUEUE_ID) { + m_unwinder_ap.reset(new HistoryUnwind(*this, pcs, stop_id_is_valid)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p HistoryThread::HistoryThread", static_cast<void *>(this)); } // Destructor -HistoryThread::~HistoryThread () -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", - static_cast<void*>(this), GetID()); - DestroyThread(); +HistoryThread::~HistoryThread() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", + static_cast<void *>(this), GetID()); + DestroyThread(); } -lldb::RegisterContextSP -HistoryThread::GetRegisterContext () -{ - RegisterContextSP rctx ; - if (m_pcs.size() > 0) - { - rctx.reset (new RegisterContextHistory (*this, 0, GetProcess()->GetAddressByteSize(), m_pcs[0])); - } - return rctx; - +lldb::RegisterContextSP HistoryThread::GetRegisterContext() { + RegisterContextSP rctx; + if (m_pcs.size() > 0) { + rctx.reset(new RegisterContextHistory( + *this, 0, GetProcess()->GetAddressByteSize(), m_pcs[0])); + } + return rctx; } lldb::RegisterContextSP -HistoryThread::CreateRegisterContextForFrame (StackFrame *frame) -{ - return m_unwinder_ap->CreateRegisterContextForFrame (frame); +HistoryThread::CreateRegisterContextForFrame(StackFrame *frame) { + return m_unwinder_ap->CreateRegisterContextForFrame(frame); } -lldb::StackFrameListSP -HistoryThread::GetStackFrameList () -{ - // FIXME do not throw away the lock after we acquire it.. - std::unique_lock<std::mutex> lock(m_framelist_mutex); - lock.unlock(); - if (m_framelist.get() == NULL) - { - m_framelist.reset (new StackFrameList (*this, StackFrameListSP(), true)); - } +lldb::StackFrameListSP HistoryThread::GetStackFrameList() { + // FIXME do not throw away the lock after we acquire it.. + std::unique_lock<std::mutex> lock(m_framelist_mutex); + lock.unlock(); + if (m_framelist.get() == NULL) { + m_framelist.reset(new StackFrameList(*this, StackFrameListSP(), true)); + } - return m_framelist; + return m_framelist; } -uint32_t -HistoryThread::GetExtendedBacktraceOriginatingIndexID () -{ - if (m_originating_unique_thread_id != LLDB_INVALID_THREAD_ID) - { - if (GetProcess()->HasAssignedIndexIDToThread (m_originating_unique_thread_id)) - { - return GetProcess()->AssignIndexIDToThread (m_originating_unique_thread_id); - } +uint32_t HistoryThread::GetExtendedBacktraceOriginatingIndexID() { + if (m_originating_unique_thread_id != LLDB_INVALID_THREAD_ID) { + if (GetProcess()->HasAssignedIndexIDToThread( + m_originating_unique_thread_id)) { + return GetProcess()->AssignIndexIDToThread( + m_originating_unique_thread_id); } - return LLDB_INVALID_THREAD_ID; + } + return LLDB_INVALID_THREAD_ID; } diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.h b/lldb/source/Plugins/Process/Utility/HistoryThread.h index 43ac13c2d8b..1a4898a95b7 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.h +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.h @@ -16,7 +16,6 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" #include "lldb/Core/UserID.h" @@ -24,119 +23,78 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/StackFrameList.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" namespace lldb_private { //---------------------------------------------------------------------- /// @class HistoryThread HistoryThread.h "HistoryThread.h" -/// @brief A thread object representing a backtrace from a previous point in the process execution +/// @brief A thread object representing a backtrace from a previous point in the +/// process execution /// /// This subclass of Thread is used to provide a backtrace from earlier in -/// process execution. It is given a backtrace list of pc addresses and +/// process execution. It is given a backtrace list of pc addresses and /// optionally a stop_id of when those pc addresses were collected, and it will /// create stack frames for them. //---------------------------------------------------------------------- -class HistoryThread : public lldb_private::Thread -{ +class HistoryThread : public lldb_private::Thread { public: - HistoryThread (lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid); - - ~HistoryThread() override; - - lldb::RegisterContextSP - GetRegisterContext() override; - - lldb::RegisterContextSP - CreateRegisterContextForFrame(StackFrame *frame) override; - - void - RefreshStateAfterStop() override { } - - bool - CalculateStopInfo() override - { - return false; - } - - void - SetExtendedBacktraceToken(uint64_t token) override - { - m_extended_unwind_token = token; - } - - uint64_t - GetExtendedBacktraceToken() override - { - return m_extended_unwind_token; - } - - const char * - GetQueueName() override - { - return m_queue_name.c_str(); - } - - void - SetQueueName(const char *name) override - { - m_queue_name = name; - } - - lldb::queue_id_t - GetQueueID() override - { - return m_queue_id; - } - - void - SetQueueID(lldb::queue_id_t queue) override - { - m_queue_id = queue; - } - - const char * - GetThreadName () - { - return m_thread_name.c_str(); - } - - uint32_t - GetExtendedBacktraceOriginatingIndexID() override; - - void - SetThreadName (const char *name) - { - m_thread_name = name; - } - - const char * - GetName() override - { - return m_thread_name.c_str(); - } - - void - SetName(const char *name) override - { - m_thread_name = name; - } + HistoryThread(lldb_private::Process &process, lldb::tid_t tid, + std::vector<lldb::addr_t> pcs, uint32_t stop_id, + bool stop_id_is_valid); + + ~HistoryThread() override; + + lldb::RegisterContextSP GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + + void RefreshStateAfterStop() override {} + + bool CalculateStopInfo() override { return false; } + + void SetExtendedBacktraceToken(uint64_t token) override { + m_extended_unwind_token = token; + } + + uint64_t GetExtendedBacktraceToken() override { + return m_extended_unwind_token; + } + + const char *GetQueueName() override { return m_queue_name.c_str(); } + + void SetQueueName(const char *name) override { m_queue_name = name; } + + lldb::queue_id_t GetQueueID() override { return m_queue_id; } + + void SetQueueID(lldb::queue_id_t queue) override { m_queue_id = queue; } + + const char *GetThreadName() { return m_thread_name.c_str(); } + + uint32_t GetExtendedBacktraceOriginatingIndexID() override; + + void SetThreadName(const char *name) { m_thread_name = name; } + + const char *GetName() override { return m_thread_name.c_str(); } + + void SetName(const char *name) override { m_thread_name = name; } protected: - virtual lldb::StackFrameListSP - GetStackFrameList (); - - mutable std::mutex m_framelist_mutex; - lldb::StackFrameListSP m_framelist; - std::vector<lldb::addr_t> m_pcs; - uint32_t m_stop_id; - bool m_stop_id_is_valid; - - uint64_t m_extended_unwind_token; - std::string m_queue_name; - std::string m_thread_name; - lldb::tid_t m_originating_unique_thread_id; - lldb::queue_id_t m_queue_id; + virtual lldb::StackFrameListSP GetStackFrameList(); + + mutable std::mutex m_framelist_mutex; + lldb::StackFrameListSP m_framelist; + std::vector<lldb::addr_t> m_pcs; + uint32_t m_stop_id; + bool m_stop_id_is_valid; + + uint64_t m_extended_unwind_token; + std::string m_queue_name; + std::string m_thread_name; + lldb::tid_t m_originating_unique_thread_id; + lldb::queue_id_t m_queue_id; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp index 01d8c3ebdcd..4f0ecba613b 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -9,75 +9,59 @@ #include "lldb/lldb-private.h" -#include "Plugins/Process/Utility/RegisterContextHistory.h" #include "Plugins/Process/Utility/HistoryUnwind.h" +#include "Plugins/Process/Utility/RegisterContextHistory.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; -// Constructor +// Constructor -HistoryUnwind::HistoryUnwind (Thread &thread, - std::vector<lldb::addr_t> pcs, - bool stop_id_is_valid) : - Unwind (thread), - m_pcs (pcs), - m_stop_id_is_valid (stop_id_is_valid) -{ -} +HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool stop_id_is_valid) + : Unwind(thread), m_pcs(pcs), m_stop_id_is_valid(stop_id_is_valid) {} // Destructor -HistoryUnwind::~HistoryUnwind () -{ -} +HistoryUnwind::~HistoryUnwind() {} -void -HistoryUnwind::DoClear () -{ - std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex); - m_pcs.clear(); - m_stop_id_is_valid = false; +void HistoryUnwind::DoClear() { + std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex); + m_pcs.clear(); + m_stop_id_is_valid = false; } lldb::RegisterContextSP -HistoryUnwind::DoCreateRegisterContextForFrame (StackFrame *frame) -{ - RegisterContextSP rctx; - if (frame) - { - addr_t pc = frame->GetFrameCodeAddress().GetLoadAddress (&frame->GetThread()->GetProcess()->GetTarget()); - if (pc != LLDB_INVALID_ADDRESS) - { - rctx.reset (new RegisterContextHistory (*frame->GetThread().get(), frame->GetConcreteFrameIndex(), - frame->GetThread()->GetProcess()->GetAddressByteSize(), pc)); - } +HistoryUnwind::DoCreateRegisterContextForFrame(StackFrame *frame) { + RegisterContextSP rctx; + if (frame) { + addr_t pc = frame->GetFrameCodeAddress().GetLoadAddress( + &frame->GetThread()->GetProcess()->GetTarget()); + if (pc != LLDB_INVALID_ADDRESS) { + rctx.reset(new RegisterContextHistory( + *frame->GetThread().get(), frame->GetConcreteFrameIndex(), + frame->GetThread()->GetProcess()->GetAddressByteSize(), pc)); } - return rctx; + } + return rctx; } -bool -HistoryUnwind::DoGetFrameInfoAtIndex (uint32_t frame_idx, lldb::addr_t& cfa, lldb::addr_t& pc) -{ - // FIXME do not throw away the lock after we acquire it.. - std::unique_lock<std::recursive_mutex> guard(m_unwind_mutex); - guard.unlock(); - if (frame_idx < m_pcs.size()) - { - cfa = frame_idx; - pc = m_pcs[frame_idx]; - return true; - } - return false; +bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &pc) { + // FIXME do not throw away the lock after we acquire it.. + std::unique_lock<std::recursive_mutex> guard(m_unwind_mutex); + guard.unlock(); + if (frame_idx < m_pcs.size()) { + cfa = frame_idx; + pc = m_pcs[frame_idx]; + return true; + } + return false; } -uint32_t -HistoryUnwind::DoGetFrameCount () -{ - return m_pcs.size(); -} +uint32_t HistoryUnwind::DoGetFrameCount() { return m_pcs.size(); } diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h index 890604fcb68..3b64e38bfaa 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h @@ -16,36 +16,31 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/Unwind.h" +#include "lldb/lldb-private.h" namespace lldb_private { -class HistoryUnwind : public lldb_private::Unwind -{ +class HistoryUnwind : public lldb_private::Unwind { public: - HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, bool stop_id_is_valid); + HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool stop_id_is_valid); - ~HistoryUnwind() override; + ~HistoryUnwind() override; protected: - void - DoClear() override; + void DoClear() override; - lldb::RegisterContextSP - DoCreateRegisterContextForFrame(StackFrame *frame) override; + lldb::RegisterContextSP + DoCreateRegisterContextForFrame(StackFrame *frame) override; - bool - DoGetFrameInfoAtIndex(uint32_t frame_idx, - lldb::addr_t& cfa, - lldb::addr_t& pc) override; - uint32_t - DoGetFrameCount() override; + bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &pc) override; + uint32_t DoGetFrameCount() override; private: - - std::vector<lldb::addr_t> m_pcs; - bool m_stop_id_is_valid; + std::vector<lldb::addr_t> m_pcs; + bool m_stop_id_is_valid; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index b694b833cb4..e10e9a2e4b3 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -34,225 +34,207 @@ using namespace lldb; using namespace lldb_private; -bool -lldb_private::InferiorCallMmap (Process *process, - addr_t &allocated_addr, - addr_t addr, - addr_t length, - unsigned prot, - unsigned flags, - addr_t fd, - addr_t offset) -{ - Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL) - return false; - - const bool append = true; - const bool include_symbols = true; - const bool include_inlines = false; - SymbolContextList sc_list; - const uint32_t count - = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), - eFunctionNameTypeFull, - include_symbols, - include_inlines, - append, - sc_list); - if (count > 0) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(0, sc)) - { - const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; - const bool use_inline_block_range = false; - EvaluateExpressionOptions options; - options.SetStopOthers(true); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetTryAllThreads(true); - options.SetDebug (false); - options.SetTimeoutUsec(500000); - options.SetTrapExceptions(false); - - addr_t prot_arg, flags_arg = 0; - if (prot == eMmapProtNone) - prot_arg = PROT_NONE; - else { - prot_arg = 0; - if (prot & eMmapProtExec) - prot_arg |= PROT_EXEC; - if (prot & eMmapProtRead) - prot_arg |= PROT_READ; - if (prot & eMmapProtWrite) - prot_arg |= PROT_WRITE; - } - - const ArchSpec arch = process->GetTarget().GetArchitecture(); - flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags); - - AddressRange mmap_range; - if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) - { - ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; - lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), - clang_void_ptr_type, args, options)); - if (call_plan_sp) - { - DiagnosticManager diagnostics; - - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - if (frame) - { - ExecutionContext exe_ctx; - frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - if (result == eExpressionCompleted) - { +bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, + addr_t addr, addr_t length, unsigned prot, + unsigned flags, addr_t fd, addr_t offset) { + Thread *thread = + process->GetThreadList().GetExpressionExecutionThread().get(); + if (thread == NULL) + return false; - allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - if (process->GetAddressByteSize() == 4) - { - if (allocated_addr == UINT32_MAX) - return false; - } - else if (process->GetAddressByteSize() == 8) - { - if (allocated_addr == UINT64_MAX) - return false; - } - return true; - } - } - } + const bool append = true; + const bool include_symbols = true; + const bool include_inlines = false; + SymbolContextList sc_list; + const uint32_t count = process->GetTarget().GetImages().FindFunctions( + ConstString("mmap"), eFunctionNameTypeFull, include_symbols, + include_inlines, append, sc_list); + if (count > 0) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) { + const uint32_t range_scope = + eSymbolContextFunction | eSymbolContextSymbol; + const bool use_inline_block_range = false; + EvaluateExpressionOptions options; + options.SetStopOthers(true); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetTryAllThreads(true); + options.SetDebug(false); + options.SetTimeoutUsec(500000); + options.SetTrapExceptions(false); + + addr_t prot_arg, flags_arg = 0; + if (prot == eMmapProtNone) + prot_arg = PROT_NONE; + else { + prot_arg = 0; + if (prot & eMmapProtExec) + prot_arg |= PROT_EXEC; + if (prot & eMmapProtRead) + prot_arg |= PROT_READ; + if (prot & eMmapProtWrite) + prot_arg |= PROT_WRITE; + } + + const ArchSpec arch = process->GetTarget().GetArchitecture(); + flags_arg = + process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch, + flags); + + AddressRange mmap_range; + if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, + mmap_range)) { + ClangASTContext *clang_ast_context = + process->GetTarget().GetScratchClangASTContext(); + CompilerType clang_void_ptr_type = + clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + lldb::addr_t args[] = {addr, length, prot_arg, flags_arg, fd, offset}; + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), + clang_void_ptr_type, args, options)); + if (call_plan_sp) { + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + if (frame) { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext(exe_ctx); + ExpressionResults result = process->RunThreadPlan( + exe_ctx, call_plan_sp, options, diagnostics); + if (result == eExpressionCompleted) { + + allocated_addr = + call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( + LLDB_INVALID_ADDRESS); + if (process->GetAddressByteSize() == 4) { + if (allocated_addr == UINT32_MAX) + return false; + } else if (process->GetAddressByteSize() == 8) { + if (allocated_addr == UINT64_MAX) + return false; + } + return true; } + } } + } } + } - return false; + return false; } -bool -lldb_private::InferiorCallMunmap (Process *process, - addr_t addr, - addr_t length) -{ - Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL) - return false; - - const bool append = true; - const bool include_symbols = true; - const bool include_inlines = false; - SymbolContextList sc_list; - const uint32_t count - = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), - eFunctionNameTypeFull, - include_symbols, - include_inlines, - append, - sc_list); - if (count > 0) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(0, sc)) - { - const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; - const bool use_inline_block_range = false; - EvaluateExpressionOptions options; - options.SetStopOthers(true); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetTryAllThreads(true); - options.SetDebug (false); - options.SetTimeoutUsec(500000); - options.SetTrapExceptions(false); - - AddressRange munmap_range; - if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) - { - lldb::addr_t args[] = { addr, length }; - lldb::ThreadPlanSP call_plan_sp( - new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options)); - if (call_plan_sp) - { - DiagnosticManager diagnostics; +bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, + addr_t length) { + Thread *thread = + process->GetThreadList().GetExpressionExecutionThread().get(); + if (thread == NULL) + return false; - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - if (frame) - { - ExecutionContext exe_ctx; - frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - if (result == eExpressionCompleted) - { - return true; - } - } - } + const bool append = true; + const bool include_symbols = true; + const bool include_inlines = false; + SymbolContextList sc_list; + const uint32_t count = process->GetTarget().GetImages().FindFunctions( + ConstString("munmap"), eFunctionNameTypeFull, include_symbols, + include_inlines, append, sc_list); + if (count > 0) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) { + const uint32_t range_scope = + eSymbolContextFunction | eSymbolContextSymbol; + const bool use_inline_block_range = false; + EvaluateExpressionOptions options; + options.SetStopOthers(true); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetTryAllThreads(true); + options.SetDebug(false); + options.SetTimeoutUsec(500000); + options.SetTrapExceptions(false); + + AddressRange munmap_range; + if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, + munmap_range)) { + lldb::addr_t args[] = {addr, length}; + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), + CompilerType(), args, options)); + if (call_plan_sp) { + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + if (frame) { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext(exe_ctx); + ExpressionResults result = process->RunThreadPlan( + exe_ctx, call_plan_sp, options, diagnostics); + if (result == eExpressionCompleted) { + return true; } + } } + } } + } - return false; + return false; } -// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a -// function of the form "void * (*)(void)". We should find a better place to put this. - -bool -lldb_private::InferiorCall (Process *process, - const Address *address, - addr_t &returned_func, - bool trap_exceptions) -{ - Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL || address == NULL) - return false; - - EvaluateExpressionOptions options; - options.SetStopOthers(true); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetTryAllThreads(true); - options.SetDebug (false); - options.SetTimeoutUsec(500000); - options.SetTrapExceptions(trap_exceptions); - - ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::ThreadPlanSP call_plan_sp( - new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, llvm::ArrayRef<addr_t>(), options)); - if (call_plan_sp) - { - DiagnosticManager diagnostics; +// FIXME: This has nothing to do with Posix, it is just a convenience function +// that calls a +// function of the form "void * (*)(void)". We should find a better place to +// put this. - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - if (frame) - { - ExecutionContext exe_ctx; - frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - if (result == eExpressionCompleted) - { - returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +bool lldb_private::InferiorCall(Process *process, const Address *address, + addr_t &returned_func, bool trap_exceptions) { + Thread *thread = + process->GetThreadList().GetExpressionExecutionThread().get(); + if (thread == NULL || address == NULL) + return false; - if (process->GetAddressByteSize() == 4) - { - if (returned_func == UINT32_MAX) - return false; - } - else if (process->GetAddressByteSize() == 8) - { - if (returned_func == UINT64_MAX) - return false; - } - return true; - } + EvaluateExpressionOptions options; + options.SetStopOthers(true); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetTryAllThreads(true); + options.SetDebug(false); + options.SetTimeoutUsec(500000); + options.SetTrapExceptions(trap_exceptions); + + ClangASTContext *clang_ast_context = + process->GetTarget().GetScratchClangASTContext(); + CompilerType clang_void_ptr_type = + clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, + llvm::ArrayRef<addr_t>(), options)); + if (call_plan_sp) { + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + if (frame) { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext(exe_ctx); + ExpressionResults result = + process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); + if (result == eExpressionCompleted) { + returned_func = + call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( + LLDB_INVALID_ADDRESS); + + if (process->GetAddressByteSize() == 4) { + if (returned_func == UINT32_MAX) + return false; + } else if (process->GetAddressByteSize() == 8) { + if (returned_func == UINT64_MAX) + return false; } + return true; + } } + } - return false; + return false; } diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h index d10e8490d80..07bde5bf09b 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h @@ -31,9 +31,9 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr, bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length); -bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func, - bool trap_exceptions = false); +bool InferiorCall(Process *proc, const Address *address, + lldb::addr_t &returned_func, bool trap_exceptions = false); -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_InferiorCallPOSIX_h_ +#endif // lldb_InferiorCallPOSIX_h_ diff --git a/lldb/source/Plugins/Process/Utility/InstructionUtils.h b/lldb/source/Plugins/Process/Utility/InstructionUtils.h index 6226fbc04b0..e422a96200c 100644 --- a/lldb/source/Plugins/Process/Utility/InstructionUtils.h +++ b/lldb/source/Plugins/Process/Utility/InstructionUtils.h @@ -16,123 +16,99 @@ namespace lldb_private { // Return the bit field(s) from the most significant bit (msbit) to the // least significant bit (lsbit) of a 64-bit unsigned value. -static inline uint64_t -Bits64 (const uint64_t bits, const uint32_t msbit, const uint32_t lsbit) -{ - assert(msbit < 64 && lsbit <= msbit); - return (bits >> lsbit) & ((1ull << (msbit - lsbit + 1)) - 1); +static inline uint64_t Bits64(const uint64_t bits, const uint32_t msbit, + const uint32_t lsbit) { + assert(msbit < 64 && lsbit <= msbit); + return (bits >> lsbit) & ((1ull << (msbit - lsbit + 1)) - 1); } // Return the bit field(s) from the most significant bit (msbit) to the // least significant bit (lsbit) of a 32-bit unsigned value. -static inline uint32_t -Bits32 (const uint32_t bits, const uint32_t msbit, const uint32_t lsbit) -{ - assert(msbit < 32 && lsbit <= msbit); - return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1); +static inline uint32_t Bits32(const uint32_t bits, const uint32_t msbit, + const uint32_t lsbit) { + assert(msbit < 32 && lsbit <= msbit); + return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1); } // Return the bit value from the 'bit' position of a 32-bit unsigned value. -static inline uint32_t -Bit32 (const uint32_t bits, const uint32_t bit) -{ - return (bits >> bit) & 1u; +static inline uint32_t Bit32(const uint32_t bits, const uint32_t bit) { + return (bits >> bit) & 1u; } -static inline uint64_t -Bit64 (const uint64_t bits, const uint32_t bit) -{ - return (bits >> bit) & 1ull; +static inline uint64_t Bit64(const uint64_t bits, const uint32_t bit) { + return (bits >> bit) & 1ull; } // Set the bit field(s) from the most significant bit (msbit) to the // least significant bit (lsbit) of a 32-bit unsigned value to 'val'. -static inline void -SetBits32(uint32_t &bits, const uint32_t msbit, const uint32_t lsbit, const uint32_t val) -{ - assert(msbit < 32 && lsbit < 32 && msbit >= lsbit); - uint32_t mask = ((1u << (msbit - lsbit + 1)) - 1); - bits &= ~(mask << lsbit); - bits |= (val & mask) << lsbit; +static inline void SetBits32(uint32_t &bits, const uint32_t msbit, + const uint32_t lsbit, const uint32_t val) { + assert(msbit < 32 && lsbit < 32 && msbit >= lsbit); + uint32_t mask = ((1u << (msbit - lsbit + 1)) - 1); + bits &= ~(mask << lsbit); + bits |= (val & mask) << lsbit; } // Set the 'bit' position of a 32-bit unsigned value to 'val'. -static inline void -SetBit32(uint32_t &bits, const uint32_t bit, const uint32_t val) -{ - SetBits32(bits, bit, bit, val); +static inline void SetBit32(uint32_t &bits, const uint32_t bit, + const uint32_t val) { + SetBits32(bits, bit, bit, val); } // Rotate a 32-bit unsigned value right by the specified amount. -static inline uint32_t -Rotr32 (uint32_t bits, uint32_t amt) -{ - assert(amt < 32 && "Invalid rotate amount"); - return (bits >> amt) | (bits << ((32-amt)&31)); +static inline uint32_t Rotr32(uint32_t bits, uint32_t amt) { + assert(amt < 32 && "Invalid rotate amount"); + return (bits >> amt) | (bits << ((32 - amt) & 31)); } // Rotate a 32-bit unsigned value left by the specified amount. -static inline uint32_t -Rotl32 (uint32_t bits, uint32_t amt) -{ - assert(amt < 32 && "Invalid rotate amount"); - return (bits << amt) | (bits >> ((32-amt)&31)); +static inline uint32_t Rotl32(uint32_t bits, uint32_t amt) { + assert(amt < 32 && "Invalid rotate amount"); + return (bits << amt) | (bits >> ((32 - amt) & 31)); } // Create a mask that starts at bit zero and includes "bit" -static inline uint64_t -MaskUpToBit (const uint64_t bit) -{ - if (bit >= 63) - return -1ll; - return (1ull << (bit + 1ull)) - 1ull; +static inline uint64_t MaskUpToBit(const uint64_t bit) { + if (bit >= 63) + return -1ll; + return (1ull << (bit + 1ull)) - 1ull; } // Return an integer result equal to the number of bits of x that are ones. -static inline uint32_t -BitCount (uint64_t x) -{ - // c accumulates the total bits set in x - uint32_t c; - for (c = 0; x; ++c) - { - x &= x - 1; // clear the least significant bit set - } - return c; +static inline uint32_t BitCount(uint64_t x) { + // c accumulates the total bits set in x + uint32_t c; + for (c = 0; x; ++c) { + x &= x - 1; // clear the least significant bit set + } + return c; } -static inline bool -BitIsSet (const uint64_t value, const uint64_t bit) -{ - return (value & (1ull << bit)) != 0; +static inline bool BitIsSet(const uint64_t value, const uint64_t bit) { + return (value & (1ull << bit)) != 0; } -static inline bool -BitIsClear (const uint64_t value, const uint64_t bit) -{ - return (value & (1ull << bit)) == 0; +static inline bool BitIsClear(const uint64_t value, const uint64_t bit) { + return (value & (1ull << bit)) == 0; } -static inline uint64_t -UnsignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit) -{ - uint64_t result = value >> lsbit; - result &= MaskUpToBit (msbit - lsbit); - return result; +static inline uint64_t UnsignedBits(const uint64_t value, const uint64_t msbit, + const uint64_t lsbit) { + uint64_t result = value >> lsbit; + result &= MaskUpToBit(msbit - lsbit); + return result; } -static inline int64_t -SignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit) -{ - uint64_t result = UnsignedBits (value, msbit, lsbit); - if (BitIsSet(value, msbit)) - { - // Sign extend - result |= ~MaskUpToBit (msbit - lsbit); - } - return result; +static inline int64_t SignedBits(const uint64_t value, const uint64_t msbit, + const uint64_t lsbit) { + uint64_t result = UnsignedBits(value, msbit, lsbit); + if (BitIsSet(value, msbit)) { + // Sign extend + result |= ~MaskUpToBit(msbit - lsbit); + } + return result; } -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_InstructionUtils_h_ +#endif // lldb_InstructionUtils_h_ diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp index 5687577f9d1..eb01075ed13 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp @@ -14,80 +14,83 @@ using namespace lldb_private; -LinuxSignals::LinuxSignals() - : UnixSignals() -{ - Reset(); -} +LinuxSignals::LinuxSignals() : UnixSignals() { Reset(); } -void -LinuxSignals::Reset() -{ - m_signals.clear(); - // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS - // ===== =========== ======== ===== ====== ====================================== ====== - AddSignal (1, "SIGHUP", false, true , true , "hangup" ); - AddSignal (2, "SIGINT", true , true , true , "interrupt" ); - AddSignal (3, "SIGQUIT", false, true , true , "quit" ); - AddSignal (4, "SIGILL", false, true , true , "illegal instruction" ); - AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" ); - AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT"); - AddSignal (7, "SIGBUS", false, true , true , "bus error" ); - AddSignal (8, "SIGFPE", false, true , true , "floating point exception" ); - AddSignal (9, "SIGKILL", false, true , true , "kill" ); - AddSignal (10, "SIGUSR1", false, true , true , "user defined signal 1" ); - AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" ); - AddSignal (12, "SIGUSR2", false, true , true , "user defined signal 2" ); - AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" ); - AddSignal (14, "SIGALRM", false, false, false, "alarm" ); - AddSignal (15, "SIGTERM", false, true , true , "termination requested" ); - AddSignal (16, "SIGSTKFLT", false, true , true , "stack fault" ); - AddSignal (17, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD"); - AddSignal (18, "SIGCONT", false, true , true , "process continue" ); - AddSignal (19, "SIGSTOP", true , true , true , "process stop" ); - AddSignal (20, "SIGTSTP", false, true , true , "tty stop" ); - AddSignal (21, "SIGTTIN", false, true , true , "background tty read" ); - AddSignal (22, "SIGTTOU", false, true , true , "background tty write" ); - AddSignal (23, "SIGURG", false, true , true , "urgent data on socket" ); - AddSignal (24, "SIGXCPU", false, true , true , "CPU resource exceeded" ); - AddSignal (25, "SIGXFSZ", false, true , true , "file size limit exceeded" ); - AddSignal (26, "SIGVTALRM", false, true , true , "virtual time alarm" ); - AddSignal (27, "SIGPROF", false, false, false, "profiling time alarm" ); - AddSignal (28, "SIGWINCH", false, true , true , "window size changes" ); - AddSignal (29, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL"); - AddSignal (30, "SIGPWR", false, true , true , "power failure" ); - AddSignal (31, "SIGSYS", false, true , true , "invalid system call" ); - AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" ); - AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" ); - AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" ); - AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" ); - AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" ); - AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" ); - AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" ); - AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" ); - AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" ); - AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" ); - AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" ); - AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" ); - AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" ); - AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" ); - AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" ); - AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" ); - AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" ); - AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" ); - AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output - AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" ); - AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" ); - AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" ); - AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" ); - AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" ); - AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" ); - AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" ); - AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" ); - AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" ); - AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" ); - AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" ); - AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" ); - AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" ); - AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" ); +void LinuxSignals::Reset() { + m_signals.clear(); + // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS + // ===== =========== ======== ===== ====== + // ====================================== ====== + AddSignal(1, "SIGHUP", false, true, true, "hangup"); + AddSignal(2, "SIGINT", true, true, true, "interrupt"); + AddSignal(3, "SIGQUIT", false, true, true, "quit"); + AddSignal(4, "SIGILL", false, true, true, "illegal instruction"); + AddSignal(5, "SIGTRAP", true, true, true, + "trace trap (not reset when caught)"); + AddSignal(6, "SIGABRT", false, true, true, "abort()/IOT trap", "SIGIOT"); + AddSignal(7, "SIGBUS", false, true, true, "bus error"); + AddSignal(8, "SIGFPE", false, true, true, "floating point exception"); + AddSignal(9, "SIGKILL", false, true, true, "kill"); + AddSignal(10, "SIGUSR1", false, true, true, "user defined signal 1"); + AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation"); + AddSignal(12, "SIGUSR2", false, true, true, "user defined signal 2"); + AddSignal(13, "SIGPIPE", false, true, true, + "write to pipe with reading end closed"); + AddSignal(14, "SIGALRM", false, false, false, "alarm"); + AddSignal(15, "SIGTERM", false, true, true, "termination requested"); + AddSignal(16, "SIGSTKFLT", false, true, true, "stack fault"); + AddSignal(17, "SIGCHLD", false, false, true, "child status has changed", + "SIGCLD"); + AddSignal(18, "SIGCONT", false, true, true, "process continue"); + AddSignal(19, "SIGSTOP", true, true, true, "process stop"); + AddSignal(20, "SIGTSTP", false, true, true, "tty stop"); + AddSignal(21, "SIGTTIN", false, true, true, "background tty read"); + AddSignal(22, "SIGTTOU", false, true, true, "background tty write"); + AddSignal(23, "SIGURG", false, true, true, "urgent data on socket"); + AddSignal(24, "SIGXCPU", false, true, true, "CPU resource exceeded"); + AddSignal(25, "SIGXFSZ", false, true, true, "file size limit exceeded"); + AddSignal(26, "SIGVTALRM", false, true, true, "virtual time alarm"); + AddSignal(27, "SIGPROF", false, false, false, "profiling time alarm"); + AddSignal(28, "SIGWINCH", false, true, true, "window size changes"); + AddSignal(29, "SIGIO", false, true, true, "input/output ready/Pollable event", + "SIGPOLL"); + AddSignal(30, "SIGPWR", false, true, true, "power failure"); + AddSignal(31, "SIGSYS", false, true, true, "invalid system call"); + AddSignal(32, "SIG32", false, false, false, + "threading library internal signal 1"); + AddSignal(33, "SIG33", false, false, false, + "threading library internal signal 2"); + AddSignal(34, "SIGRTMIN", false, false, false, "real time signal 0"); + AddSignal(35, "SIGRTMIN+1", false, false, false, "real time signal 1"); + AddSignal(36, "SIGRTMIN+2", false, false, false, "real time signal 2"); + AddSignal(37, "SIGRTMIN+3", false, false, false, "real time signal 3"); + AddSignal(38, "SIGRTMIN+4", false, false, false, "real time signal 4"); + AddSignal(39, "SIGRTMIN+5", false, false, false, "real time signal 5"); + AddSignal(40, "SIGRTMIN+6", false, false, false, "real time signal 6"); + AddSignal(41, "SIGRTMIN+7", false, false, false, "real time signal 7"); + AddSignal(42, "SIGRTMIN+8", false, false, false, "real time signal 8"); + AddSignal(43, "SIGRTMIN+9", false, false, false, "real time signal 9"); + AddSignal(44, "SIGRTMIN+10", false, false, false, "real time signal 10"); + AddSignal(45, "SIGRTMIN+11", false, false, false, "real time signal 11"); + AddSignal(46, "SIGRTMIN+12", false, false, false, "real time signal 12"); + AddSignal(47, "SIGRTMIN+13", false, false, false, "real time signal 13"); + AddSignal(48, "SIGRTMIN+14", false, false, false, "real time signal 14"); + AddSignal(49, "SIGRTMIN+15", false, false, false, "real time signal 15"); + AddSignal(50, "SIGRTMAX-14", false, false, false, + "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill + // -l" output + AddSignal(51, "SIGRTMAX-13", false, false, false, "real time signal 17"); + AddSignal(52, "SIGRTMAX-12", false, false, false, "real time signal 18"); + AddSignal(53, "SIGRTMAX-11", false, false, false, "real time signal 19"); + AddSignal(54, "SIGRTMAX-10", false, false, false, "real time signal 20"); + AddSignal(55, "SIGRTMAX-9", false, false, false, "real time signal 21"); + AddSignal(56, "SIGRTMAX-8", false, false, false, "real time signal 22"); + AddSignal(57, "SIGRTMAX-7", false, false, false, "real time signal 23"); + AddSignal(58, "SIGRTMAX-6", false, false, false, "real time signal 24"); + AddSignal(59, "SIGRTMAX-5", false, false, false, "real time signal 25"); + AddSignal(60, "SIGRTMAX-4", false, false, false, "real time signal 26"); + AddSignal(61, "SIGRTMAX-3", false, false, false, "real time signal 27"); + AddSignal(62, "SIGRTMAX-2", false, false, false, "real time signal 28"); + AddSignal(63, "SIGRTMAX-1", false, false, false, "real time signal 29"); + AddSignal(64, "SIGRTMAX", false, false, false, "real time signal 30"); } diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.h b/lldb/source/Plugins/Process/Utility/LinuxSignals.h index dd9062f040a..e41126225ce 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxSignals.h +++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.h @@ -19,14 +19,12 @@ namespace lldb_private { /// Linux specific set of Unix signals. -class LinuxSignals : public UnixSignals -{ +class LinuxSignals : public UnixSignals { public: - LinuxSignals(); + LinuxSignals(); private: - void - Reset() override; + void Reset() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp index 422fc9b642d..36231023aa3 100644 --- a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp @@ -1,4 +1,5 @@ -//===-- MipsLinuxSignals.cpp ----------------------------------------*- C++ -*-===// +//===-- MipsLinuxSignals.cpp ----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,80 +15,83 @@ using namespace lldb_private; -MipsLinuxSignals::MipsLinuxSignals() - : UnixSignals() -{ - Reset(); -} +MipsLinuxSignals::MipsLinuxSignals() : UnixSignals() { Reset(); } -void -MipsLinuxSignals::Reset() -{ - m_signals.clear(); - // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS - // ===== =========== ======== ===== ====== ====================================== ======== - AddSignal (1, "SIGHUP", false, true , true , "hangup" ); - AddSignal (2, "SIGINT", true , true , true , "interrupt" ); - AddSignal (3, "SIGQUIT", false, true , true , "quit" ); - AddSignal (4, "SIGILL", false, true , true , "illegal instruction" ); - AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" ); - AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT"); - AddSignal (7, "SIGEMT", false, true , true , "terminate process with core dump" ); - AddSignal (8, "SIGFPE", false, true , true , "floating point exception" ); - AddSignal (9, "SIGKILL", false, true , true , "kill" ); - AddSignal (10, "SIGBUS", false, true , true , "bus error" ); - AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" ); - AddSignal (12, "SIGSYS", false, true , true , "invalid system call" ); - AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" ); - AddSignal (14, "SIGALRM", false, false, false, "alarm" ); - AddSignal (15, "SIGTERM", false, true , true , "termination requested" ); - AddSignal (16, "SIGUSR1", false, true , true , "user defined signal 1" ); - AddSignal (17, "SIGUSR2", false, true , true , "user defined signal 2" ); - AddSignal (18, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD"); - AddSignal (19, "SIGPWR", false, true , true , "power failure" ); - AddSignal (20, "SIGWINCH", false, true , true , "window size changes" ); - AddSignal (21, "SIGURG", false, true , true , "urgent data on socket" ); - AddSignal (22, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL"); - AddSignal (23, "SIGSTOP", true , true , true , "process stop" ); - AddSignal (24, "SIGTSTP", false, true , true , "tty stop" ); - AddSignal (25, "SIGCONT", false, true , true , "process continue" ); - AddSignal (26, "SIGTTIN", false, true , true , "background tty read" ); - AddSignal (27, "SIGTTOU", false, true , true , "background tty write" ); - AddSignal (28, "SIGVTALRM", false, true , true , "virtual time alarm" ); - AddSignal (29, "SIGPROF", false, false, false, "profiling time alarm" ); - AddSignal (30, "SIGXCPU", false, true , true , "CPU resource exceeded" ); - AddSignal (31, "SIGXFSZ", false, true , true , "file size limit exceeded" ); - AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" ); - AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" ); - AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" ); - AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" ); - AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" ); - AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" ); - AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" ); - AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" ); - AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" ); - AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" ); - AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" ); - AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" ); - AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" ); - AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" ); - AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" ); - AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" ); - AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" ); - AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" ); - AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output - AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" ); - AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" ); - AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" ); - AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" ); - AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" ); - AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" ); - AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" ); - AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" ); - AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" ); - AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" ); - AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" ); - AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" ); - AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" ); - AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" ); +void MipsLinuxSignals::Reset() { + m_signals.clear(); + // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS + // ===== =========== ======== ===== ====== + // ====================================== ======== + AddSignal(1, "SIGHUP", false, true, true, "hangup"); + AddSignal(2, "SIGINT", true, true, true, "interrupt"); + AddSignal(3, "SIGQUIT", false, true, true, "quit"); + AddSignal(4, "SIGILL", false, true, true, "illegal instruction"); + AddSignal(5, "SIGTRAP", true, true, true, + "trace trap (not reset when caught)"); + AddSignal(6, "SIGABRT", false, true, true, "abort()/IOT trap", "SIGIOT"); + AddSignal(7, "SIGEMT", false, true, true, "terminate process with core dump"); + AddSignal(8, "SIGFPE", false, true, true, "floating point exception"); + AddSignal(9, "SIGKILL", false, true, true, "kill"); + AddSignal(10, "SIGBUS", false, true, true, "bus error"); + AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation"); + AddSignal(12, "SIGSYS", false, true, true, "invalid system call"); + AddSignal(13, "SIGPIPE", false, true, true, + "write to pipe with reading end closed"); + AddSignal(14, "SIGALRM", false, false, false, "alarm"); + AddSignal(15, "SIGTERM", false, true, true, "termination requested"); + AddSignal(16, "SIGUSR1", false, true, true, "user defined signal 1"); + AddSignal(17, "SIGUSR2", false, true, true, "user defined signal 2"); + AddSignal(18, "SIGCHLD", false, false, true, "child status has changed", + "SIGCLD"); + AddSignal(19, "SIGPWR", false, true, true, "power failure"); + AddSignal(20, "SIGWINCH", false, true, true, "window size changes"); + AddSignal(21, "SIGURG", false, true, true, "urgent data on socket"); + AddSignal(22, "SIGIO", false, true, true, "input/output ready/Pollable event", + "SIGPOLL"); + AddSignal(23, "SIGSTOP", true, true, true, "process stop"); + AddSignal(24, "SIGTSTP", false, true, true, "tty stop"); + AddSignal(25, "SIGCONT", false, true, true, "process continue"); + AddSignal(26, "SIGTTIN", false, true, true, "background tty read"); + AddSignal(27, "SIGTTOU", false, true, true, "background tty write"); + AddSignal(28, "SIGVTALRM", false, true, true, "virtual time alarm"); + AddSignal(29, "SIGPROF", false, false, false, "profiling time alarm"); + AddSignal(30, "SIGXCPU", false, true, true, "CPU resource exceeded"); + AddSignal(31, "SIGXFSZ", false, true, true, "file size limit exceeded"); + AddSignal(32, "SIG32", false, false, false, + "threading library internal signal 1"); + AddSignal(33, "SIG33", false, false, false, + "threading library internal signal 2"); + AddSignal(34, "SIGRTMIN", false, false, false, "real time signal 0"); + AddSignal(35, "SIGRTMIN+1", false, false, false, "real time signal 1"); + AddSignal(36, "SIGRTMIN+2", false, false, false, "real time signal 2"); + AddSignal(37, "SIGRTMIN+3", false, false, false, "real time signal 3"); + AddSignal(38, "SIGRTMIN+4", false, false, false, "real time signal 4"); + AddSignal(39, "SIGRTMIN+5", false, false, false, "real time signal 5"); + AddSignal(40, "SIGRTMIN+6", false, false, false, "real time signal 6"); + AddSignal(41, "SIGRTMIN+7", false, false, false, "real time signal 7"); + AddSignal(42, "SIGRTMIN+8", false, false, false, "real time signal 8"); + AddSignal(43, "SIGRTMIN+9", false, false, false, "real time signal 9"); + AddSignal(44, "SIGRTMIN+10", false, false, false, "real time signal 10"); + AddSignal(45, "SIGRTMIN+11", false, false, false, "real time signal 11"); + AddSignal(46, "SIGRTMIN+12", false, false, false, "real time signal 12"); + AddSignal(47, "SIGRTMIN+13", false, false, false, "real time signal 13"); + AddSignal(48, "SIGRTMIN+14", false, false, false, "real time signal 14"); + AddSignal(49, "SIGRTMIN+15", false, false, false, "real time signal 15"); + AddSignal(50, "SIGRTMAX-14", false, false, false, + "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill + // -l" output + AddSignal(51, "SIGRTMAX-13", false, false, false, "real time signal 17"); + AddSignal(52, "SIGRTMAX-12", false, false, false, "real time signal 18"); + AddSignal(53, "SIGRTMAX-11", false, false, false, "real time signal 19"); + AddSignal(54, "SIGRTMAX-10", false, false, false, "real time signal 20"); + AddSignal(55, "SIGRTMAX-9", false, false, false, "real time signal 21"); + AddSignal(56, "SIGRTMAX-8", false, false, false, "real time signal 22"); + AddSignal(57, "SIGRTMAX-7", false, false, false, "real time signal 23"); + AddSignal(58, "SIGRTMAX-6", false, false, false, "real time signal 24"); + AddSignal(59, "SIGRTMAX-5", false, false, false, "real time signal 25"); + AddSignal(60, "SIGRTMAX-4", false, false, false, "real time signal 26"); + AddSignal(61, "SIGRTMAX-3", false, false, false, "real time signal 27"); + AddSignal(62, "SIGRTMAX-2", false, false, false, "real time signal 28"); + AddSignal(63, "SIGRTMAX-1", false, false, false, "real time signal 29"); + AddSignal(64, "SIGRTMAX", false, false, false, "real time signal 30"); } diff --git a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h index a5041b50eea..e48ea5943f2 100644 --- a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h +++ b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h @@ -1,4 +1,5 @@ -//===-- MipsLinuxSignals.h ------------------------------------------*- C++ -*-===// +//===-- MipsLinuxSignals.h ------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -19,14 +20,12 @@ namespace lldb_private { /// Linux specific set of Unix signals. -class MipsLinuxSignals : public UnixSignals -{ +class MipsLinuxSignals : public UnixSignals { public: - MipsLinuxSignals(); + MipsLinuxSignals(); private: - void - Reset() override; + void Reset() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp b/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp index 5dce51616c4..9b9db51e516 100644 --- a/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp @@ -15,20 +15,16 @@ using namespace lldb_private; -NetBSDSignals::NetBSDSignals() - : UnixSignals() -{ - Reset(); -} +NetBSDSignals::NetBSDSignals() : UnixSignals() { Reset(); } -void -NetBSDSignals::Reset() -{ - UnixSignals::Reset(); - // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION - // ====== ============ ======== ====== ====== =================================================== - AddSignal (32, "SIGPWR", false, true , true , "power fail/restart (not reset when caught)"); +void NetBSDSignals::Reset() { + UnixSignals::Reset(); + // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION + // ====== ============ ======== ====== ====== + // =================================================== + AddSignal(32, "SIGPWR", false, true, true, + "power fail/restart (not reset when caught)"); #ifdef SIGRTMIN /* SIGRTMAX */ - /* Kernel only; not exposed to userland yet */ + /* Kernel only; not exposed to userland yet */ #endif } diff --git a/lldb/source/Plugins/Process/Utility/NetBSDSignals.h b/lldb/source/Plugins/Process/Utility/NetBSDSignals.h index 441402b056d..4338f881645 100644 --- a/lldb/source/Plugins/Process/Utility/NetBSDSignals.h +++ b/lldb/source/Plugins/Process/Utility/NetBSDSignals.h @@ -16,14 +16,12 @@ namespace lldb_private { /// NetBSD specific set of Unix signals. -class NetBSDSignals : public UnixSignals -{ +class NetBSDSignals : public UnixSignals { public: - NetBSDSignals(); + NetBSDSignals(); private: - void - Reset() override; + void Reset() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 11b84ddfe16..52ace5602f4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -42,403 +42,926 @@ using namespace lldb; using namespace lldb_private; -enum -{ - gpr_r0 = 0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, gpr_sp = gpr_r13, - gpr_r14, gpr_lr = gpr_r14, - gpr_r15, gpr_pc = gpr_r15, - gpr_cpsr, - - fpu_s0, - fpu_s1, - fpu_s2, - fpu_s3, - fpu_s4, - fpu_s5, - fpu_s6, - fpu_s7, - fpu_s8, - fpu_s9, - fpu_s10, - fpu_s11, - fpu_s12, - fpu_s13, - fpu_s14, - fpu_s15, - fpu_s16, - fpu_s17, - fpu_s18, - fpu_s19, - fpu_s20, - fpu_s21, - fpu_s22, - fpu_s23, - fpu_s24, - fpu_s25, - fpu_s26, - fpu_s27, - fpu_s28, - fpu_s29, - fpu_s30, - fpu_s31, - fpu_fpscr, - - exc_exception, - exc_fsr, - exc_far, - - dbg_bvr0, - dbg_bvr1, - dbg_bvr2, - dbg_bvr3, - dbg_bvr4, - dbg_bvr5, - dbg_bvr6, - dbg_bvr7, - dbg_bvr8, - dbg_bvr9, - dbg_bvr10, - dbg_bvr11, - dbg_bvr12, - dbg_bvr13, - dbg_bvr14, - dbg_bvr15, - - dbg_bcr0, - dbg_bcr1, - dbg_bcr2, - dbg_bcr3, - dbg_bcr4, - dbg_bcr5, - dbg_bcr6, - dbg_bcr7, - dbg_bcr8, - dbg_bcr9, - dbg_bcr10, - dbg_bcr11, - dbg_bcr12, - dbg_bcr13, - dbg_bcr14, - dbg_bcr15, - - dbg_wvr0, - dbg_wvr1, - dbg_wvr2, - dbg_wvr3, - dbg_wvr4, - dbg_wvr5, - dbg_wvr6, - dbg_wvr7, - dbg_wvr8, - dbg_wvr9, - dbg_wvr10, - dbg_wvr11, - dbg_wvr12, - dbg_wvr13, - dbg_wvr14, - dbg_wvr15, - - dbg_wcr0, - dbg_wcr1, - dbg_wcr2, - dbg_wcr3, - dbg_wcr4, - dbg_wcr5, - dbg_wcr6, - dbg_wcr7, - dbg_wcr8, - dbg_wcr9, - dbg_wcr10, - dbg_wcr11, - dbg_wcr12, - dbg_wcr13, - dbg_wcr14, - dbg_wcr15, - - k_num_registers +enum { + gpr_r0 = 0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_sp = gpr_r13, + gpr_r14, + gpr_lr = gpr_r14, + gpr_r15, + gpr_pc = gpr_r15, + gpr_cpsr, + + fpu_s0, + fpu_s1, + fpu_s2, + fpu_s3, + fpu_s4, + fpu_s5, + fpu_s6, + fpu_s7, + fpu_s8, + fpu_s9, + fpu_s10, + fpu_s11, + fpu_s12, + fpu_s13, + fpu_s14, + fpu_s15, + fpu_s16, + fpu_s17, + fpu_s18, + fpu_s19, + fpu_s20, + fpu_s21, + fpu_s22, + fpu_s23, + fpu_s24, + fpu_s25, + fpu_s26, + fpu_s27, + fpu_s28, + fpu_s29, + fpu_s30, + fpu_s31, + fpu_fpscr, + + exc_exception, + exc_fsr, + exc_far, + + dbg_bvr0, + dbg_bvr1, + dbg_bvr2, + dbg_bvr3, + dbg_bvr4, + dbg_bvr5, + dbg_bvr6, + dbg_bvr7, + dbg_bvr8, + dbg_bvr9, + dbg_bvr10, + dbg_bvr11, + dbg_bvr12, + dbg_bvr13, + dbg_bvr14, + dbg_bvr15, + + dbg_bcr0, + dbg_bcr1, + dbg_bcr2, + dbg_bcr3, + dbg_bcr4, + dbg_bcr5, + dbg_bcr6, + dbg_bcr7, + dbg_bcr8, + dbg_bcr9, + dbg_bcr10, + dbg_bcr11, + dbg_bcr12, + dbg_bcr13, + dbg_bcr14, + dbg_bcr15, + + dbg_wvr0, + dbg_wvr1, + dbg_wvr2, + dbg_wvr3, + dbg_wvr4, + dbg_wvr5, + dbg_wvr6, + dbg_wvr7, + dbg_wvr8, + dbg_wvr9, + dbg_wvr10, + dbg_wvr11, + dbg_wvr12, + dbg_wvr13, + dbg_wvr14, + dbg_wvr15, + + dbg_wcr0, + dbg_wcr1, + dbg_wcr2, + dbg_wcr3, + dbg_wcr4, + dbg_wcr5, + dbg_wcr6, + dbg_wcr7, + dbg_wcr8, + dbg_wcr9, + dbg_wcr10, + dbg_wcr11, + dbg_wcr12, + dbg_wcr13, + dbg_wcr14, + dbg_wcr15, + + k_num_registers }; - -#define GPR_OFFSET(idx) ((idx) * 4) -#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR)) -#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU)) -#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))) - -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr, nullptr, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)) +#define GPR_OFFSET(idx) ((idx)*4) +#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR)) +#define EXC_OFFSET(idx) \ + ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR) + \ + sizeof(RegisterContextDarwin_arm::FPU)) +#define DBG_OFFSET(reg) \ + ((LLVM_EXTENSION offsetof(RegisterContextDarwin_arm::DBG, reg) + \ + sizeof(RegisterContextDarwin_arm::GPR) + \ + sizeof(RegisterContextDarwin_arm::FPU) + \ + sizeof(RegisterContextDarwin_arm::EXC))) + +#define DEFINE_DBG(reg, i) \ + #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *) NULL)->reg[i]), \ + DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM }, \ + nullptr, nullptr, nullptr, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextDarwin_arm::GPR) + \ + sizeof(RegisterContextDarwin_arm::FPU) + \ + sizeof(RegisterContextDarwin_arm::EXC)) static RegisterInfo g_register_infos[] = { -// General purpose registers -// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE -// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= -{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0 }, nullptr, nullptr, nullptr, 0 }, -{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1 }, nullptr, nullptr, nullptr, 0 }, -{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2 }, nullptr, nullptr, nullptr, 0 }, -{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3 }, nullptr, nullptr, nullptr, 0 }, -{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, nullptr, nullptr, nullptr, 0 }, -{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, nullptr, nullptr, nullptr, 0 }, -{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, nullptr, nullptr, nullptr, 0 }, -{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r7 }, nullptr, nullptr, nullptr, 0 }, -{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, nullptr, nullptr, nullptr, 0 }, -{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, nullptr, nullptr, nullptr, 0 }, -{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, nullptr, nullptr, nullptr, 0 }, -{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r11 }, nullptr, nullptr, nullptr, 0 }, -{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, nullptr, nullptr, nullptr, 0 }, -{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr, nullptr, 0 }, -{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr, nullptr, 0 }, -{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr, nullptr, 0 }, -{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr, nullptr, 0 }, - -{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, nullptr, nullptr, nullptr, 0 }, -{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, nullptr, nullptr, nullptr, 0 }, -{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, nullptr, nullptr, nullptr, 0 }, -{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, nullptr, nullptr, nullptr, 0 }, -{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, nullptr, nullptr, nullptr, 0 }, -{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, nullptr, nullptr, nullptr, 0 }, -{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, nullptr, nullptr, nullptr, 0 }, -{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, nullptr, nullptr, nullptr, 0 }, -{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, nullptr, nullptr, nullptr, 0 }, -{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, nullptr, nullptr, nullptr, 0 }, -{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, nullptr, nullptr, nullptr, 0 }, -{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, nullptr, nullptr, nullptr, 0 }, -{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, nullptr, nullptr, nullptr, 0 }, -{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, nullptr, nullptr, nullptr, 0 }, -{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, nullptr, nullptr, nullptr, 0 }, -{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, nullptr, nullptr, nullptr, 0 }, -{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, nullptr, nullptr, nullptr, 0 }, -{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, nullptr, nullptr, nullptr, 0 }, -{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, nullptr, nullptr, nullptr, 0 }, -{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, nullptr, nullptr, nullptr, 0 }, -{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, nullptr, nullptr, nullptr, 0 }, -{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, nullptr, nullptr, nullptr, 0 }, -{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, nullptr, nullptr, nullptr, 0 }, -{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, nullptr, nullptr, nullptr, 0 }, -{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, nullptr, nullptr, nullptr, 0 }, -{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, nullptr, nullptr, nullptr, 0 }, -{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, nullptr, nullptr, nullptr, 0 }, -{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, nullptr, nullptr, nullptr, 0 }, -{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, nullptr, nullptr, nullptr, 0 }, -{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, nullptr, nullptr, nullptr, 0 }, -{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, nullptr, nullptr, nullptr, 0 }, -{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, nullptr, nullptr, nullptr, 0 }, -{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, nullptr, nullptr, nullptr, 0 }, - -{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr, nullptr, 0 }, -{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, nullptr, nullptr, nullptr, 0 }, -{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr, nullptr, 0 }, - -{ DEFINE_DBG (bvr, 0) }, -{ DEFINE_DBG (bvr, 1) }, -{ DEFINE_DBG (bvr, 2) }, -{ DEFINE_DBG (bvr, 3) }, -{ DEFINE_DBG (bvr, 4) }, -{ DEFINE_DBG (bvr, 5) }, -{ DEFINE_DBG (bvr, 6) }, -{ DEFINE_DBG (bvr, 7) }, -{ DEFINE_DBG (bvr, 8) }, -{ DEFINE_DBG (bvr, 9) }, -{ DEFINE_DBG (bvr, 10) }, -{ DEFINE_DBG (bvr, 11) }, -{ DEFINE_DBG (bvr, 12) }, -{ DEFINE_DBG (bvr, 13) }, -{ DEFINE_DBG (bvr, 14) }, -{ DEFINE_DBG (bvr, 15) }, - -{ DEFINE_DBG (bcr, 0) }, -{ DEFINE_DBG (bcr, 1) }, -{ DEFINE_DBG (bcr, 2) }, -{ DEFINE_DBG (bcr, 3) }, -{ DEFINE_DBG (bcr, 4) }, -{ DEFINE_DBG (bcr, 5) }, -{ DEFINE_DBG (bcr, 6) }, -{ DEFINE_DBG (bcr, 7) }, -{ DEFINE_DBG (bcr, 8) }, -{ DEFINE_DBG (bcr, 9) }, -{ DEFINE_DBG (bcr, 10) }, -{ DEFINE_DBG (bcr, 11) }, -{ DEFINE_DBG (bcr, 12) }, -{ DEFINE_DBG (bcr, 13) }, -{ DEFINE_DBG (bcr, 14) }, -{ DEFINE_DBG (bcr, 15) }, - -{ DEFINE_DBG (wvr, 0) }, -{ DEFINE_DBG (wvr, 1) }, -{ DEFINE_DBG (wvr, 2) }, -{ DEFINE_DBG (wvr, 3) }, -{ DEFINE_DBG (wvr, 4) }, -{ DEFINE_DBG (wvr, 5) }, -{ DEFINE_DBG (wvr, 6) }, -{ DEFINE_DBG (wvr, 7) }, -{ DEFINE_DBG (wvr, 8) }, -{ DEFINE_DBG (wvr, 9) }, -{ DEFINE_DBG (wvr, 10) }, -{ DEFINE_DBG (wvr, 11) }, -{ DEFINE_DBG (wvr, 12) }, -{ DEFINE_DBG (wvr, 13) }, -{ DEFINE_DBG (wvr, 14) }, -{ DEFINE_DBG (wvr, 15) }, - -{ DEFINE_DBG (wcr, 0) }, -{ DEFINE_DBG (wcr, 1) }, -{ DEFINE_DBG (wcr, 2) }, -{ DEFINE_DBG (wcr, 3) }, -{ DEFINE_DBG (wcr, 4) }, -{ DEFINE_DBG (wcr, 5) }, -{ DEFINE_DBG (wcr, 6) }, -{ DEFINE_DBG (wcr, 7) }, -{ DEFINE_DBG (wcr, 8) }, -{ DEFINE_DBG (wcr, 9) }, -{ DEFINE_DBG (wcr, 10) }, -{ DEFINE_DBG (wcr, 11) }, -{ DEFINE_DBG (wcr, 12) }, -{ DEFINE_DBG (wcr, 13) }, -{ DEFINE_DBG (wcr, 14) }, -{ DEFINE_DBG (wcr, 15) } -}; + // General purpose registers + // NAME ALT SZ OFFSET ENCODING FORMAT + // EH_FRAME DWARF GENERIC + // PROCESS PLUGIN LLDB NATIVE + // ====== ======= == ============= ============= ============ + // =============== =============== ========================= + // ===================== ============= + {"r0", + NULL, + 4, + GPR_OFFSET(0), + eEncodingUint, + eFormatHex, + {ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0}, + nullptr, + nullptr, + nullptr, + 0}, + {"r1", + NULL, + 4, + GPR_OFFSET(1), + eEncodingUint, + eFormatHex, + {ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1}, + nullptr, + nullptr, + nullptr, + 0}, + {"r2", + NULL, + 4, + GPR_OFFSET(2), + eEncodingUint, + eFormatHex, + {ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2}, + nullptr, + nullptr, + nullptr, + 0}, + {"r3", + NULL, + 4, + GPR_OFFSET(3), + eEncodingUint, + eFormatHex, + {ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3}, + nullptr, + nullptr, + nullptr, + 0}, + {"r4", + NULL, + 4, + GPR_OFFSET(4), + eEncodingUint, + eFormatHex, + {ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4}, + nullptr, + nullptr, + nullptr, + 0}, + {"r5", + NULL, + 4, + GPR_OFFSET(5), + eEncodingUint, + eFormatHex, + {ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5}, + nullptr, + nullptr, + nullptr, + 0}, + {"r6", + NULL, + 4, + GPR_OFFSET(6), + eEncodingUint, + eFormatHex, + {ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6}, + nullptr, + nullptr, + nullptr, + 0}, + {"r7", + NULL, + 4, + GPR_OFFSET(7), + eEncodingUint, + eFormatHex, + {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, + gpr_r7}, + nullptr, + nullptr, + nullptr, + 0}, + {"r8", + NULL, + 4, + GPR_OFFSET(8), + eEncodingUint, + eFormatHex, + {ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8}, + nullptr, + nullptr, + nullptr, + 0}, + {"r9", + NULL, + 4, + GPR_OFFSET(9), + eEncodingUint, + eFormatHex, + {ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9}, + nullptr, + nullptr, + nullptr, + 0}, + {"r10", + NULL, + 4, + GPR_OFFSET(10), + eEncodingUint, + eFormatHex, + {ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_r10}, + nullptr, + nullptr, + nullptr, + 0}, + {"r11", + NULL, + 4, + GPR_OFFSET(11), + eEncodingUint, + eFormatHex, + {ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_r11}, + nullptr, + nullptr, + nullptr, + 0}, + {"r12", + NULL, + 4, + GPR_OFFSET(12), + eEncodingUint, + eFormatHex, + {ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_r12}, + nullptr, + nullptr, + nullptr, + 0}, + {"sp", + "r13", + 4, + GPR_OFFSET(13), + eEncodingUint, + eFormatHex, + {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, + gpr_sp}, + nullptr, + nullptr, + nullptr, + 0}, + {"lr", + "r14", + 4, + GPR_OFFSET(14), + eEncodingUint, + eFormatHex, + {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, + gpr_lr}, + nullptr, + nullptr, + nullptr, + 0}, + {"pc", + "r15", + 4, + GPR_OFFSET(15), + eEncodingUint, + eFormatHex, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + gpr_pc}, + nullptr, + nullptr, + nullptr, + 0}, + {"cpsr", + "psr", + 4, + GPR_OFFSET(16), + eEncodingUint, + eFormatHex, + {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, + gpr_cpsr}, + nullptr, + nullptr, + nullptr, + 0}, + + {"s0", + NULL, + 4, + FPU_OFFSET(0), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s0}, + nullptr, + nullptr, + nullptr, + 0}, + {"s1", + NULL, + 4, + FPU_OFFSET(1), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s1}, + nullptr, + nullptr, + nullptr, + 0}, + {"s2", + NULL, + 4, + FPU_OFFSET(2), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s2}, + nullptr, + nullptr, + nullptr, + 0}, + {"s3", + NULL, + 4, + FPU_OFFSET(3), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s3}, + nullptr, + nullptr, + nullptr, + 0}, + {"s4", + NULL, + 4, + FPU_OFFSET(4), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s4}, + nullptr, + nullptr, + nullptr, + 0}, + {"s5", + NULL, + 4, + FPU_OFFSET(5), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s5}, + nullptr, + nullptr, + nullptr, + 0}, + {"s6", + NULL, + 4, + FPU_OFFSET(6), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s6}, + nullptr, + nullptr, + nullptr, + 0}, + {"s7", + NULL, + 4, + FPU_OFFSET(7), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s7}, + nullptr, + nullptr, + nullptr, + 0}, + {"s8", + NULL, + 4, + FPU_OFFSET(8), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s8}, + nullptr, + nullptr, + nullptr, + 0}, + {"s9", + NULL, + 4, + FPU_OFFSET(9), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s9}, + nullptr, + nullptr, + nullptr, + 0}, + {"s10", + NULL, + 4, + FPU_OFFSET(10), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s10}, + nullptr, + nullptr, + nullptr, + 0}, + {"s11", + NULL, + 4, + FPU_OFFSET(11), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s11}, + nullptr, + nullptr, + nullptr, + 0}, + {"s12", + NULL, + 4, + FPU_OFFSET(12), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s12}, + nullptr, + nullptr, + nullptr, + 0}, + {"s13", + NULL, + 4, + FPU_OFFSET(13), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s13}, + nullptr, + nullptr, + nullptr, + 0}, + {"s14", + NULL, + 4, + FPU_OFFSET(14), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s14}, + nullptr, + nullptr, + nullptr, + 0}, + {"s15", + NULL, + 4, + FPU_OFFSET(15), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s15}, + nullptr, + nullptr, + nullptr, + 0}, + {"s16", + NULL, + 4, + FPU_OFFSET(16), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s16}, + nullptr, + nullptr, + nullptr, + 0}, + {"s17", + NULL, + 4, + FPU_OFFSET(17), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s17}, + nullptr, + nullptr, + nullptr, + 0}, + {"s18", + NULL, + 4, + FPU_OFFSET(18), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s18}, + nullptr, + nullptr, + nullptr, + 0}, + {"s19", + NULL, + 4, + FPU_OFFSET(19), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s19}, + nullptr, + nullptr, + nullptr, + 0}, + {"s20", + NULL, + 4, + FPU_OFFSET(20), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s20}, + nullptr, + nullptr, + nullptr, + 0}, + {"s21", + NULL, + 4, + FPU_OFFSET(21), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s21}, + nullptr, + nullptr, + nullptr, + 0}, + {"s22", + NULL, + 4, + FPU_OFFSET(22), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s22}, + nullptr, + nullptr, + nullptr, + 0}, + {"s23", + NULL, + 4, + FPU_OFFSET(23), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s23}, + nullptr, + nullptr, + nullptr, + 0}, + {"s24", + NULL, + 4, + FPU_OFFSET(24), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s24}, + nullptr, + nullptr, + nullptr, + 0}, + {"s25", + NULL, + 4, + FPU_OFFSET(25), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s25}, + nullptr, + nullptr, + nullptr, + 0}, + {"s26", + NULL, + 4, + FPU_OFFSET(26), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s26}, + nullptr, + nullptr, + nullptr, + 0}, + {"s27", + NULL, + 4, + FPU_OFFSET(27), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s27}, + nullptr, + nullptr, + nullptr, + 0}, + {"s28", + NULL, + 4, + FPU_OFFSET(28), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s28}, + nullptr, + nullptr, + nullptr, + 0}, + {"s29", + NULL, + 4, + FPU_OFFSET(29), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s29}, + nullptr, + nullptr, + nullptr, + 0}, + {"s30", + NULL, + 4, + FPU_OFFSET(30), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s30}, + nullptr, + nullptr, + nullptr, + 0}, + {"s31", + NULL, + 4, + FPU_OFFSET(31), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s31}, + nullptr, + nullptr, + nullptr, + 0}, + {"fpscr", + NULL, + 4, + FPU_OFFSET(32), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fpscr}, + nullptr, + nullptr, + nullptr, + 0}, + + {"exception", + NULL, + 4, + EXC_OFFSET(0), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_exception}, + nullptr, + nullptr, + nullptr, + 0}, + {"fsr", + NULL, + 4, + EXC_OFFSET(1), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_fsr}, + nullptr, + nullptr, + nullptr, + 0}, + {"far", + NULL, + 4, + EXC_OFFSET(2), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_far}, + nullptr, + nullptr, + nullptr, + 0}, + + {DEFINE_DBG(bvr, 0)}, + {DEFINE_DBG(bvr, 1)}, + {DEFINE_DBG(bvr, 2)}, + {DEFINE_DBG(bvr, 3)}, + {DEFINE_DBG(bvr, 4)}, + {DEFINE_DBG(bvr, 5)}, + {DEFINE_DBG(bvr, 6)}, + {DEFINE_DBG(bvr, 7)}, + {DEFINE_DBG(bvr, 8)}, + {DEFINE_DBG(bvr, 9)}, + {DEFINE_DBG(bvr, 10)}, + {DEFINE_DBG(bvr, 11)}, + {DEFINE_DBG(bvr, 12)}, + {DEFINE_DBG(bvr, 13)}, + {DEFINE_DBG(bvr, 14)}, + {DEFINE_DBG(bvr, 15)}, + + {DEFINE_DBG(bcr, 0)}, + {DEFINE_DBG(bcr, 1)}, + {DEFINE_DBG(bcr, 2)}, + {DEFINE_DBG(bcr, 3)}, + {DEFINE_DBG(bcr, 4)}, + {DEFINE_DBG(bcr, 5)}, + {DEFINE_DBG(bcr, 6)}, + {DEFINE_DBG(bcr, 7)}, + {DEFINE_DBG(bcr, 8)}, + {DEFINE_DBG(bcr, 9)}, + {DEFINE_DBG(bcr, 10)}, + {DEFINE_DBG(bcr, 11)}, + {DEFINE_DBG(bcr, 12)}, + {DEFINE_DBG(bcr, 13)}, + {DEFINE_DBG(bcr, 14)}, + {DEFINE_DBG(bcr, 15)}, + + {DEFINE_DBG(wvr, 0)}, + {DEFINE_DBG(wvr, 1)}, + {DEFINE_DBG(wvr, 2)}, + {DEFINE_DBG(wvr, 3)}, + {DEFINE_DBG(wvr, 4)}, + {DEFINE_DBG(wvr, 5)}, + {DEFINE_DBG(wvr, 6)}, + {DEFINE_DBG(wvr, 7)}, + {DEFINE_DBG(wvr, 8)}, + {DEFINE_DBG(wvr, 9)}, + {DEFINE_DBG(wvr, 10)}, + {DEFINE_DBG(wvr, 11)}, + {DEFINE_DBG(wvr, 12)}, + {DEFINE_DBG(wvr, 13)}, + {DEFINE_DBG(wvr, 14)}, + {DEFINE_DBG(wvr, 15)}, + + {DEFINE_DBG(wcr, 0)}, + {DEFINE_DBG(wcr, 1)}, + {DEFINE_DBG(wcr, 2)}, + {DEFINE_DBG(wcr, 3)}, + {DEFINE_DBG(wcr, 4)}, + {DEFINE_DBG(wcr, 5)}, + {DEFINE_DBG(wcr, 6)}, + {DEFINE_DBG(wcr, 7)}, + {DEFINE_DBG(wcr, 8)}, + {DEFINE_DBG(wcr, 9)}, + {DEFINE_DBG(wcr, 10)}, + {DEFINE_DBG(wcr, 11)}, + {DEFINE_DBG(wcr, 12)}, + {DEFINE_DBG(wcr, 13)}, + {DEFINE_DBG(wcr, 14)}, + {DEFINE_DBG(wcr, 15)}}; // General purpose registers -static uint32_t -g_gpr_regnums[] = -{ - gpr_r0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_sp, - gpr_lr, - gpr_pc, - gpr_cpsr -}; +static uint32_t g_gpr_regnums[] = { + gpr_r0, gpr_r1, gpr_r2, gpr_r3, gpr_r4, gpr_r5, gpr_r6, gpr_r7, gpr_r8, + gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_sp, gpr_lr, gpr_pc, gpr_cpsr}; // Floating point registers -static uint32_t -g_fpu_regnums[] = -{ - fpu_s0, - fpu_s1, - fpu_s2, - fpu_s3, - fpu_s4, - fpu_s5, - fpu_s6, - fpu_s7, - fpu_s8, - fpu_s9, - fpu_s10, - fpu_s11, - fpu_s12, - fpu_s13, - fpu_s14, - fpu_s15, - fpu_s16, - fpu_s17, - fpu_s18, - fpu_s19, - fpu_s20, - fpu_s21, - fpu_s22, - fpu_s23, - fpu_s24, - fpu_s25, - fpu_s26, - fpu_s27, - fpu_s28, - fpu_s29, - fpu_s30, - fpu_s31, - fpu_fpscr, +static uint32_t g_fpu_regnums[] = { + fpu_s0, fpu_s1, fpu_s2, fpu_s3, fpu_s4, fpu_s5, fpu_s6, + fpu_s7, fpu_s8, fpu_s9, fpu_s10, fpu_s11, fpu_s12, fpu_s13, + fpu_s14, fpu_s15, fpu_s16, fpu_s17, fpu_s18, fpu_s19, fpu_s20, + fpu_s21, fpu_s22, fpu_s23, fpu_s24, fpu_s25, fpu_s26, fpu_s27, + fpu_s28, fpu_s29, fpu_s30, fpu_s31, fpu_fpscr, }; // Exception registers -static uint32_t -g_exc_regnums[] = -{ - exc_exception, - exc_fsr, - exc_far, +static uint32_t g_exc_regnums[] = { + exc_exception, exc_fsr, exc_far, }; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext(thread, concrete_frame_idx), - gpr(), - fpu(), - exc() -{ - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } -} - -RegisterContextDarwin_arm::~RegisterContextDarwin_arm() -{ +RegisterContextDarwin_arm::RegisterContextDarwin_arm( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + } } +RegisterContextDarwin_arm::~RegisterContextDarwin_arm() {} -void -RegisterContextDarwin_arm::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); +void RegisterContextDarwin_arm::InvalidateAllRegisters() { + InvalidateAllRegisterStates(); } - -size_t -RegisterContextDarwin_arm::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; +size_t RegisterContextDarwin_arm::GetRegisterCount() { + assert(k_num_register_infos == k_num_registers); + return k_num_registers; } const RegisterInfo * -RegisterContextDarwin_arm::GetRegisterInfoAtIndex (size_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - return NULL; +RegisterContextDarwin_arm::GetRegisterInfoAtIndex(size_t reg) { + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextDarwin_arm::GetRegisterInfosCount () -{ - return k_num_register_infos; +size_t RegisterContextDarwin_arm::GetRegisterInfosCount() { + return k_num_register_infos; } -const RegisterInfo * -RegisterContextDarwin_arm::GetRegisterInfos () -{ - return g_register_infos; +const RegisterInfo *RegisterContextDarwin_arm::GetRegisterInfos() { + return g_register_infos; } - // Number of registers in each register set const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); @@ -449,782 +972,799 @@ const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -static const RegisterSet g_reg_sets[] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }, - { "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums } -}; +static const RegisterSet g_reg_sets[] = { + { + "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, + }, + {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, + {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); - -size_t -RegisterContextDarwin_arm::GetRegisterSetCount () -{ - return k_num_regsets; +size_t RegisterContextDarwin_arm::GetRegisterSetCount() { + return k_num_regsets; } -const RegisterSet * -RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; +const RegisterSet *RegisterContextDarwin_arm::GetRegisterSet(size_t reg_set) { + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; } - //---------------------------------------------------------------------- // Register information definitions for 32 bit i386. //---------------------------------------------------------------------- -int -RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg) -{ - if (reg < fpu_s0) - return GPRRegSet; - else if (reg < exc_exception) - return FPURegSet; - else if (reg < k_num_registers) - return EXCRegSet; - return -1; +int RegisterContextDarwin_arm::GetSetForNativeRegNum(int reg) { + if (reg < fpu_s0) + return GPRRegSet; + else if (reg < exc_exception) + return FPURegSet; + else if (reg < k_num_registers) + return EXCRegSet; + return -1; } -int -RegisterContextDarwin_arm::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); - } - return GetError(GPRRegSet, Read); +int RegisterContextDarwin_arm::ReadGPR(bool force) { + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(GPRRegSet, Read); } -int -RegisterContextDarwin_arm::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); - } - return GetError(FPURegSet, Read); +int RegisterContextDarwin_arm::ReadFPU(bool force) { + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(FPURegSet, Read); } -int -RegisterContextDarwin_arm::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); - } - return GetError(EXCRegSet, Read); +int RegisterContextDarwin_arm::ReadEXC(bool force) { + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(EXCRegSet, Read); } -int -RegisterContextDarwin_arm::ReadDBG (bool force) -{ - int set = DBGRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg)); - } - return GetError(DBGRegSet, Read); +int RegisterContextDarwin_arm::ReadDBG(bool force) { + int set = DBGRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg)); + } + return GetError(DBGRegSet, Read); } -int -RegisterContextDarwin_arm::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr)); - SetError (set, Read, -1); - return GetError(GPRRegSet, Write); -} - -int -RegisterContextDarwin_arm::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu)); - SetError (set, Read, -1); - return GetError(FPURegSet, Write); +int RegisterContextDarwin_arm::WriteGPR() { + int set = GPRRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr)); + SetError(set, Read, -1); + return GetError(GPRRegSet, Write); } -int -RegisterContextDarwin_arm::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc)); - SetError (set, Read, -1); - return GetError(EXCRegSet, Write); +int RegisterContextDarwin_arm::WriteFPU() { + int set = FPURegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu)); + SetError(set, Read, -1); + return GetError(FPURegSet, Write); } -int -RegisterContextDarwin_arm::WriteDBG () -{ - int set = DBGRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg)); - SetError (set, Read, -1); - return GetError(DBGRegSet, Write); +int RegisterContextDarwin_arm::WriteEXC() { + int set = EXCRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc)); + SetError(set, Read, -1); + return GetError(EXCRegSet, Write); } - -int -RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force) -{ - switch (set) - { - case GPRRegSet: return ReadGPR(force); - case GPRAltRegSet: return ReadGPR(force); - case FPURegSet: return ReadFPU(force); - case EXCRegSet: return ReadEXC(force); - case DBGRegSet: return ReadDBG(force); - default: break; - } +int RegisterContextDarwin_arm::WriteDBG() { + int set = DBGRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg)); + SetError(set, Read, -1); + return GetError(DBGRegSet, Write); } -int -RegisterContextDarwin_arm::WriteRegisterSet (uint32_t set) -{ - // Make sure we have a valid context to set. - if (RegisterSetIsCached(set)) - { - switch (set) - { - case GPRRegSet: return WriteGPR(); - case GPRAltRegSet: return WriteGPR(); - case FPURegSet: return WriteFPU(); - case EXCRegSet: return WriteEXC(); - case DBGRegSet: return WriteDBG(); - default: break; - } - } - return KERN_INVALID_ARGUMENT; +int RegisterContextDarwin_arm::ReadRegisterSet(uint32_t set, bool force) { + switch (set) { + case GPRRegSet: + return ReadGPR(force); + case GPRAltRegSet: + return ReadGPR(force); + case FPURegSet: + return ReadFPU(force); + case EXCRegSet: + return ReadEXC(force); + case DBGRegSet: + return ReadDBG(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -void -RegisterContextDarwin_arm::LogDBGRegisters (Log *log, const DBG& dbg) -{ - if (log) - { - for (uint32_t i=0; i<16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", - i, i, dbg.bvr[i], dbg.bcr[i], - i, i, dbg.wvr[i], dbg.wcr[i]); +int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set) { + // Make sure we have a valid context to set. + if (RegisterSetIsCached(set)) { + switch (set) { + case GPRRegSet: + return WriteGPR(); + case GPRAltRegSet: + return WriteGPR(); + case FPURegSet: + return WriteFPU(); + case EXCRegSet: + return WriteEXC(); + case DBGRegSet: + return WriteDBG(); + default: + break; } + } + return KERN_INVALID_ARGUMENT; } +void RegisterContextDarwin_arm::LogDBGRegisters(Log *log, const DBG &dbg) { + if (log) { + for (uint32_t i = 0; i < 16; i++) + log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " + "0x%8.8x, 0x%8.8x }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + } +} -bool -RegisterContextDarwin_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextDarwin_arm::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; +bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_arm::GetSetForNativeRegNum(reg); - switch (reg) - { - case gpr_r0: - case gpr_r1: - case gpr_r2: - case gpr_r3: - case gpr_r4: - case gpr_r5: - case gpr_r6: - case gpr_r7: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - value.SetUInt32 (gpr.r[reg - gpr_r0]); - break; - - case fpu_s0: - case fpu_s1: - case fpu_s2: - case fpu_s3: - case fpu_s4: - case fpu_s5: - case fpu_s6: - case fpu_s7: - case fpu_s8: - case fpu_s9: - case fpu_s10: - case fpu_s11: - case fpu_s12: - case fpu_s13: - case fpu_s14: - case fpu_s15: - case fpu_s16: - case fpu_s17: - case fpu_s18: - case fpu_s19: - case fpu_s20: - case fpu_s21: - case fpu_s22: - case fpu_s23: - case fpu_s24: - case fpu_s25: - case fpu_s26: - case fpu_s27: - case fpu_s28: - case fpu_s29: - case fpu_s30: - case fpu_s31: - value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat); - break; - - case fpu_fpscr: - value.SetUInt32 (fpu.fpscr); - break; - - case exc_exception: - value.SetUInt32 (exc.exception); - break; - case exc_fsr: - value.SetUInt32 (exc.fsr); - break; - case exc_far: - value.SetUInt32 (exc.far); - break; + if (set == -1) + return false; - default: - value.SetValueToInvalid(); - return false; + if (ReadRegisterSet(set, false) != KERN_SUCCESS) + return false; - } - return true; + switch (reg) { + case gpr_r0: + case gpr_r1: + case gpr_r2: + case gpr_r3: + case gpr_r4: + case gpr_r5: + case gpr_r6: + case gpr_r7: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + value.SetUInt32(gpr.r[reg - gpr_r0]); + break; + + case fpu_s0: + case fpu_s1: + case fpu_s2: + case fpu_s3: + case fpu_s4: + case fpu_s5: + case fpu_s6: + case fpu_s7: + case fpu_s8: + case fpu_s9: + case fpu_s10: + case fpu_s11: + case fpu_s12: + case fpu_s13: + case fpu_s14: + case fpu_s15: + case fpu_s16: + case fpu_s17: + case fpu_s18: + case fpu_s19: + case fpu_s20: + case fpu_s21: + case fpu_s22: + case fpu_s23: + case fpu_s24: + case fpu_s25: + case fpu_s26: + case fpu_s27: + case fpu_s28: + case fpu_s29: + case fpu_s30: + case fpu_s31: + value.SetUInt32(fpu.floats.s[reg], RegisterValue::eTypeFloat); + break; + + case fpu_fpscr: + value.SetUInt32(fpu.fpscr); + break; + + case exc_exception: + value.SetUInt32(exc.exception); + break; + case exc_fsr: + value.SetUInt32(exc.fsr); + break; + case exc_far: + value.SetUInt32(exc.far); + break; + + default: + value.SetValueToInvalid(); + return false; + } + return true; } +bool RegisterContextDarwin_arm::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = GetSetForNativeRegNum(reg); -bool -RegisterContextDarwin_arm::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_r0: - case gpr_r1: - case gpr_r2: - case gpr_r3: - case gpr_r4: - case gpr_r5: - case gpr_r6: - case gpr_r7: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - gpr.r[reg - gpr_r0] = value.GetAsUInt32(); - break; - - case fpu_s0: - case fpu_s1: - case fpu_s2: - case fpu_s3: - case fpu_s4: - case fpu_s5: - case fpu_s6: - case fpu_s7: - case fpu_s8: - case fpu_s9: - case fpu_s10: - case fpu_s11: - case fpu_s12: - case fpu_s13: - case fpu_s14: - case fpu_s15: - case fpu_s16: - case fpu_s17: - case fpu_s18: - case fpu_s19: - case fpu_s20: - case fpu_s21: - case fpu_s22: - case fpu_s23: - case fpu_s24: - case fpu_s25: - case fpu_s26: - case fpu_s27: - case fpu_s28: - case fpu_s29: - case fpu_s30: - case fpu_s31: - fpu.floats.s[reg] = value.GetAsUInt32(); - break; - - case fpu_fpscr: - fpu.fpscr = value.GetAsUInt32(); - break; - - case exc_exception: - exc.exception = value.GetAsUInt32(); - break; - case exc_fsr: - exc.fsr = value.GetAsUInt32(); - break; - case exc_far: - exc.far = value.GetAsUInt32(); - break; + if (set == -1) + return false; - default: - return false; + if (ReadRegisterSet(set, false) != KERN_SUCCESS) + return false; - } - return WriteRegisterSet(set) == KERN_SUCCESS; + switch (reg) { + case gpr_r0: + case gpr_r1: + case gpr_r2: + case gpr_r3: + case gpr_r4: + case gpr_r5: + case gpr_r6: + case gpr_r7: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + gpr.r[reg - gpr_r0] = value.GetAsUInt32(); + break; + + case fpu_s0: + case fpu_s1: + case fpu_s2: + case fpu_s3: + case fpu_s4: + case fpu_s5: + case fpu_s6: + case fpu_s7: + case fpu_s8: + case fpu_s9: + case fpu_s10: + case fpu_s11: + case fpu_s12: + case fpu_s13: + case fpu_s14: + case fpu_s15: + case fpu_s16: + case fpu_s17: + case fpu_s18: + case fpu_s19: + case fpu_s20: + case fpu_s21: + case fpu_s22: + case fpu_s23: + case fpu_s24: + case fpu_s25: + case fpu_s26: + case fpu_s27: + case fpu_s28: + case fpu_s29: + case fpu_s30: + case fpu_s31: + fpu.floats.s[reg] = value.GetAsUInt32(); + break; + + case fpu_fpscr: + fpu.fpscr = value.GetAsUInt32(); + break; + + case exc_exception: + exc.exception = value.GetAsUInt32(); + break; + case exc_fsr: + exc.fsr = value.GetAsUInt32(); + break; + case exc_far: + exc.far = value.GetAsUInt32(); + break; + + default: + return false; + } + return WriteRegisterSet(set) == KERN_SUCCESS; } -bool -RegisterContextDarwin_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == KERN_SUCCESS && - ReadFPU (false) == KERN_SUCCESS && - ReadEXC (false) == KERN_SUCCESS) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &gpr, sizeof(gpr)); - dst += sizeof(gpr); +bool RegisterContextDarwin_arm::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR(false) == KERN_SUCCESS && + ReadFPU(false) == KERN_SUCCESS && ReadEXC(false) == KERN_SUCCESS) { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy(dst, &gpr, sizeof(gpr)); + dst += sizeof(gpr); - ::memcpy (dst, &fpu, sizeof(fpu)); - dst += sizeof(gpr); + ::memcpy(dst, &fpu, sizeof(fpu)); + dst += sizeof(gpr); - ::memcpy (dst, &exc, sizeof(exc)); - return true; - } - return false; + ::memcpy(dst, &exc, sizeof(exc)); + return true; + } + return false; } -bool -RegisterContextDarwin_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&gpr, src, sizeof(gpr)); - src += sizeof(gpr); - - ::memcpy (&fpu, src, sizeof(fpu)); - src += sizeof(gpr); - - ::memcpy (&exc, src, sizeof(exc)); - uint32_t success_count = 0; - if (WriteGPR() == KERN_SUCCESS) - ++success_count; - if (WriteFPU() == KERN_SUCCESS) - ++success_count; - if (WriteEXC() == KERN_SUCCESS) - ++success_count; - return success_count == 3; - } - return false; +bool RegisterContextDarwin_arm::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy(&gpr, src, sizeof(gpr)); + src += sizeof(gpr); + + ::memcpy(&fpu, src, sizeof(fpu)); + src += sizeof(gpr); + + ::memcpy(&exc, src, sizeof(exc)); + uint32_t success_count = 0; + if (WriteGPR() == KERN_SUCCESS) + ++success_count; + if (WriteFPU() == KERN_SUCCESS) + ++success_count; + if (WriteEXC() == KERN_SUCCESS) + ++success_count; + return success_count == 3; + } + return false; } -uint32_t -RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg) -{ - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_pc; - case LLDB_REGNUM_GENERIC_SP: return gpr_sp; - case LLDB_REGNUM_GENERIC_FP: return gpr_r7; - case LLDB_REGNUM_GENERIC_RA: return gpr_lr; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr; - default: - break; - } - } - else if (kind == eRegisterKindDWARF) - { - switch (reg) - { - case dwarf_r0: return gpr_r0; - case dwarf_r1: return gpr_r1; - case dwarf_r2: return gpr_r2; - case dwarf_r3: return gpr_r3; - case dwarf_r4: return gpr_r4; - case dwarf_r5: return gpr_r5; - case dwarf_r6: return gpr_r6; - case dwarf_r7: return gpr_r7; - case dwarf_r8: return gpr_r8; - case dwarf_r9: return gpr_r9; - case dwarf_r10: return gpr_r10; - case dwarf_r11: return gpr_r11; - case dwarf_r12: return gpr_r12; - case dwarf_sp: return gpr_sp; - case dwarf_lr: return gpr_lr; - case dwarf_pc: return gpr_pc; - case dwarf_spsr: return gpr_cpsr; - - case dwarf_s0: return fpu_s0; - case dwarf_s1: return fpu_s1; - case dwarf_s2: return fpu_s2; - case dwarf_s3: return fpu_s3; - case dwarf_s4: return fpu_s4; - case dwarf_s5: return fpu_s5; - case dwarf_s6: return fpu_s6; - case dwarf_s7: return fpu_s7; - case dwarf_s8: return fpu_s8; - case dwarf_s9: return fpu_s9; - case dwarf_s10: return fpu_s10; - case dwarf_s11: return fpu_s11; - case dwarf_s12: return fpu_s12; - case dwarf_s13: return fpu_s13; - case dwarf_s14: return fpu_s14; - case dwarf_s15: return fpu_s15; - case dwarf_s16: return fpu_s16; - case dwarf_s17: return fpu_s17; - case dwarf_s18: return fpu_s18; - case dwarf_s19: return fpu_s19; - case dwarf_s20: return fpu_s20; - case dwarf_s21: return fpu_s21; - case dwarf_s22: return fpu_s22; - case dwarf_s23: return fpu_s23; - case dwarf_s24: return fpu_s24; - case dwarf_s25: return fpu_s25; - case dwarf_s26: return fpu_s26; - case dwarf_s27: return fpu_s27; - case dwarf_s28: return fpu_s28; - case dwarf_s29: return fpu_s29; - case dwarf_s30: return fpu_s30; - case dwarf_s31: return fpu_s31; - - default: - break; - } +uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t reg) { + if (kind == eRegisterKindGeneric) { + switch (reg) { + case LLDB_REGNUM_GENERIC_PC: + return gpr_pc; + case LLDB_REGNUM_GENERIC_SP: + return gpr_sp; + case LLDB_REGNUM_GENERIC_FP: + return gpr_r7; + case LLDB_REGNUM_GENERIC_RA: + return gpr_lr; + case LLDB_REGNUM_GENERIC_FLAGS: + return gpr_cpsr; + default: + break; } - else if (kind == eRegisterKindEHFrame) - { - switch (reg) - { - case ehframe_r0: return gpr_r0; - case ehframe_r1: return gpr_r1; - case ehframe_r2: return gpr_r2; - case ehframe_r3: return gpr_r3; - case ehframe_r4: return gpr_r4; - case ehframe_r5: return gpr_r5; - case ehframe_r6: return gpr_r6; - case ehframe_r7: return gpr_r7; - case ehframe_r8: return gpr_r8; - case ehframe_r9: return gpr_r9; - case ehframe_r10: return gpr_r10; - case ehframe_r11: return gpr_r11; - case ehframe_r12: return gpr_r12; - case ehframe_sp: return gpr_sp; - case ehframe_lr: return gpr_lr; - case ehframe_pc: return gpr_pc; - case ehframe_cpsr: return gpr_cpsr; - } + } else if (kind == eRegisterKindDWARF) { + switch (reg) { + case dwarf_r0: + return gpr_r0; + case dwarf_r1: + return gpr_r1; + case dwarf_r2: + return gpr_r2; + case dwarf_r3: + return gpr_r3; + case dwarf_r4: + return gpr_r4; + case dwarf_r5: + return gpr_r5; + case dwarf_r6: + return gpr_r6; + case dwarf_r7: + return gpr_r7; + case dwarf_r8: + return gpr_r8; + case dwarf_r9: + return gpr_r9; + case dwarf_r10: + return gpr_r10; + case dwarf_r11: + return gpr_r11; + case dwarf_r12: + return gpr_r12; + case dwarf_sp: + return gpr_sp; + case dwarf_lr: + return gpr_lr; + case dwarf_pc: + return gpr_pc; + case dwarf_spsr: + return gpr_cpsr; + + case dwarf_s0: + return fpu_s0; + case dwarf_s1: + return fpu_s1; + case dwarf_s2: + return fpu_s2; + case dwarf_s3: + return fpu_s3; + case dwarf_s4: + return fpu_s4; + case dwarf_s5: + return fpu_s5; + case dwarf_s6: + return fpu_s6; + case dwarf_s7: + return fpu_s7; + case dwarf_s8: + return fpu_s8; + case dwarf_s9: + return fpu_s9; + case dwarf_s10: + return fpu_s10; + case dwarf_s11: + return fpu_s11; + case dwarf_s12: + return fpu_s12; + case dwarf_s13: + return fpu_s13; + case dwarf_s14: + return fpu_s14; + case dwarf_s15: + return fpu_s15; + case dwarf_s16: + return fpu_s16; + case dwarf_s17: + return fpu_s17; + case dwarf_s18: + return fpu_s18; + case dwarf_s19: + return fpu_s19; + case dwarf_s20: + return fpu_s20; + case dwarf_s21: + return fpu_s21; + case dwarf_s22: + return fpu_s22; + case dwarf_s23: + return fpu_s23; + case dwarf_s24: + return fpu_s24; + case dwarf_s25: + return fpu_s25; + case dwarf_s26: + return fpu_s26; + case dwarf_s27: + return fpu_s27; + case dwarf_s28: + return fpu_s28; + case dwarf_s29: + return fpu_s29; + case dwarf_s30: + return fpu_s30; + case dwarf_s31: + return fpu_s31; + + default: + break; } - else if (kind == eRegisterKindLLDB) - { - return reg; + } else if (kind == eRegisterKindEHFrame) { + switch (reg) { + case ehframe_r0: + return gpr_r0; + case ehframe_r1: + return gpr_r1; + case ehframe_r2: + return gpr_r2; + case ehframe_r3: + return gpr_r3; + case ehframe_r4: + return gpr_r4; + case ehframe_r5: + return gpr_r5; + case ehframe_r6: + return gpr_r6; + case ehframe_r7: + return gpr_r7; + case ehframe_r8: + return gpr_r8; + case ehframe_r9: + return gpr_r9; + case ehframe_r10: + return gpr_r10; + case ehframe_r11: + return gpr_r11; + case ehframe_r12: + return gpr_r12; + case ehframe_sp: + return gpr_sp; + case ehframe_lr: + return gpr_lr; + case ehframe_pc: + return gpr_pc; + case ehframe_cpsr: + return gpr_cpsr; } - return LLDB_INVALID_REGNUM; + } else if (kind == eRegisterKindLLDB) { + return reg; + } + return LLDB_INVALID_REGNUM; } - -uint32_t -RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints () -{ -#if defined (__arm__) - // Set the init value to something that will let us know that we need to - // autodetect how many breakpoints are supported dynamically... - static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX; - if (g_num_supported_hw_breakpoints == UINT32_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_breakpoints = 0; - - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - g_num_supported_hw_breakpoints = Bits32 (register_DBGDIDR, 27, 24); - // Zero is reserved for the BRP count, so don't increment it if it is zero - if (g_num_supported_hw_breakpoints > 0) - g_num_supported_hw_breakpoints++; -// if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints); - - } - return g_num_supported_hw_breakpoints; +uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() { +#if defined(__arm__) + // Set the init value to something that will let us know that we need to + // autodetect how many breakpoints are supported dynamically... + static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX; + if (g_num_supported_hw_breakpoints == UINT32_MAX) { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_breakpoints = 0; + + uint32_t register_DBGDIDR; + + asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); + g_num_supported_hw_breakpoints = Bits32(register_DBGDIDR, 27, 24); + // Zero is reserved for the BRP count, so don't increment it if it is zero + if (g_num_supported_hw_breakpoints > 0) + g_num_supported_hw_breakpoints++; + // if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", + // register_DBGDIDR, g_num_supported_hw_breakpoints); + } + return g_num_supported_hw_breakpoints; #else - // TODO: figure out remote case here! - return 6; + // TODO: figure out remote case here! + return 6; #endif } -uint32_t -RegisterContextDarwin_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - // Make sure our address isn't bogus - if (addr & 1) - return LLDB_INVALID_INDEX32; +uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + // Make sure our address isn't bogus + if (addr & 1) + return LLDB_INVALID_INDEX32; - int kret = ReadDBG (false); + int kret = ReadDBG(false); - if (kret == KERN_SUCCESS) - { - const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); - uint32_t i; - for (i=0; i<num_hw_breakpoints; ++i) - { - if ((dbg.bcr[i] & BCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_breakpoints) - { - // Make sure bits 1:0 are clear in our address - dbg.bvr[i] = addr & ~((lldb::addr_t)3); - - if (size == 2 || addr & 2) - { - uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; - - // We have a thumb breakpoint - // We have an ARM breakpoint - dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", -// addr, -// size, -// i, -// i, -// dbg.bvr[i], -// dbg.bcr[i]); - } - else if (size == 4) - { - // We have an ARM breakpoint - dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", -// addr, -// size, -// i, -// i, -// dbg.bvr[i], -// dbg.bcr[i]); - } - - kret = WriteDBG(); -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } -// else -// { -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size); -// } + if (kret == KERN_SUCCESS) { + const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); + uint32_t i; + for (i = 0; i < num_hw_breakpoints; ++i) { + if ((dbg.bcr[i] & BCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) } - return LLDB_INVALID_INDEX32; + // See if we found an available hw breakpoint slot above + if (i < num_hw_breakpoints) { + // Make sure bits 1:0 are clear in our address + dbg.bvr[i] = addr & ~((lldb::addr_t)3); + + if (size == 2 || addr & 2) { + uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; + + // We have a thumb breakpoint + // We have an ARM breakpoint + dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch + byte_addr_select | // Set the correct byte address select + // so we only trigger on the correct + // opcode + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( + // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / + // 0x%8.8x (Thumb)", + // addr, + // size, + // i, + // i, + // dbg.bvr[i], + // dbg.bcr[i]); + } else if (size == 4) { + // We have an ARM breakpoint + dbg.bcr[i] = + BCR_M_IMVA_MATCH | // Stop on address mismatch + BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( + // addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / + // 0x%8.8x (ARM)", + // addr, + // size, + // i, + // i, + // dbg.bvr[i], + // dbg.bcr[i]); + } + + kret = WriteDBG(); + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() + // WriteDBG() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return i; + } + // else + // { + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = + // %8.8p, size = %u) => all hardware breakpoint resources are + // being used.", addr, size); + // } + } + + return LLDB_INVALID_INDEX32; } -bool -RegisterContextDarwin_arm::ClearHardwareBreakpoint (uint32_t hw_index) -{ - int kret = ReadDBG (false); - - const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - dbg.bcr[hw_index] = 0; -// if (log) log->Printf ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", -// hw_index, -// hw_index, -// dbg.bvr[hw_index], -// hw_index, -// dbg.bcr[hw_index]); - - kret = WriteDBG(); - - if (kret == KERN_SUCCESS) - return true; - } +bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index) { + int kret = ReadDBG(false); + + const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); + if (kret == KERN_SUCCESS) { + if (hw_index < num_hw_points) { + dbg.bcr[hw_index] = 0; + // if (log) log->Printf + // ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - + // BVR%u = 0x%8.8x BCR%u = 0x%8.8x", + // hw_index, + // hw_index, + // dbg.bvr[hw_index], + // hw_index, + // dbg.bcr[hw_index]); + + kret = WriteDBG(); + + if (kret == KERN_SUCCESS) + return true; } - return false; + } + return false; } -uint32_t -RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints () -{ -#if defined (__arm__) - // Set the init value to something that will let us know that we need to - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; - if (g_num_supported_hw_watchpoints == UINT32_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_watchpoints = 0; - - uint32_t register_DBGDIDR; - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - g_num_supported_hw_watchpoints = Bits32 (register_DBGDIDR, 31, 28) + 1; -// if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints); - } - return g_num_supported_hw_watchpoints; +uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() { +#if defined(__arm__) + // Set the init value to something that will let us know that we need to + // autodetect how many watchpoints are supported dynamically... + static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; + if (g_num_supported_hw_watchpoints == UINT32_MAX) { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_watchpoints = 0; + + uint32_t register_DBGDIDR; + asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); + g_num_supported_hw_watchpoints = Bits32(register_DBGDIDR, 31, 28) + 1; + // if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", + // register_DBGDIDR, g_num_supported_hw_watchpoints); + } + return g_num_supported_hw_watchpoints; #else - // TODO: figure out remote case here! - return 2; + // TODO: figure out remote case here! + return 2; #endif } +uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, + bool read, + bool write) { + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size + // = %u, read = %u, write = %u)", addr, size, read, write); -uint32_t -RegisterContextDarwin_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) -{ -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + // Can't watch zero bytes + if (size == 0) + return LLDB_INVALID_INDEX32; - // Can't watch zero bytes - if (size == 0) - return LLDB_INVALID_INDEX32; + // We must watch for either read or write + if (read == false && write == false) + return LLDB_INVALID_INDEX32; - // We must watch for either read or write - if (read == false && write == false) - return LLDB_INVALID_INDEX32; + // Can't watch more than 4 bytes per WVR/WCR pair + if (size > 4) + return LLDB_INVALID_INDEX32; - // Can't watch more than 4 bytes per WVR/WCR pair - if (size > 4) - return LLDB_INVALID_INDEX32; + // We can only watch up to four bytes that follow a 4 byte aligned address + // per watchpoint register pair. Since we have at most so we can only watch + // until the next 4 byte boundary and we need to make sure we can properly + // encode this. + uint32_t addr_word_offset = addr % 4; + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - + // addr_word_offset = 0x%8.8x", addr_word_offset); + + uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = + // 0x%8.8x", byte_mask); + if (byte_mask > 0xfu) + return LLDB_INVALID_INDEX32; - // We can only watch up to four bytes that follow a 4 byte aligned address - // per watchpoint register pair. Since we have at most so we can only watch - // until the next 4 byte boundary and we need to make sure we can properly - // encode this. - uint32_t addr_word_offset = addr % 4; -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); + // Read the debug state + int kret = ReadDBG(false); - uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); - if (byte_mask > 0xfu) - return LLDB_INVALID_INDEX32; + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - // Read the debug state - int kret = ReadDBG (false); + for (i = 0; i < num_hw_watchpoints; ++i) { + if ((dbg.wcr[i] & WCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) + } - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i=0; i<num_hw_watchpoints; ++i) - { - if ((dbg.wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) - { - // Make the byte_mask into a valid Byte Address Select mask - uint32_t byte_address_select = byte_mask << 5; - // Make sure bits 1:0 are clear in our address - dbg.wvr[i] = addr & ~((lldb::addr_t)3); - dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; - - kret = WriteDBG(); -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } - else - { -// if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw breakpoint slot above + if (i < num_hw_watchpoints) { + // Make the byte_mask into a valid Byte Address Select mask + uint32_t byte_address_select = byte_mask << 5; + // Make sure bits 1:0 are clear in our address + dbg.wvr[i] = addr & ~((lldb::addr_t)3); + dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA + // that we will watch + S_USER | // Stop only in user mode + (read ? WCR_LOAD : 0) | // Stop on read access? + (write ? WCR_STORE : 0) | // Stop on write access? + WCR_ENABLE; // Enable this watchpoint; + + kret = WriteDBG(); + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() + // WriteDBG() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return i; + } else { + // if (log) log->Printf + // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All + // hardware resources (%u) are in use.", num_hw_watchpoints); } - return LLDB_INVALID_INDEX32; + } + return LLDB_INVALID_INDEX32; } -bool -RegisterContextDarwin_arm::ClearHardwareWatchpoint (uint32_t hw_index) -{ - int kret = ReadDBG (false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - dbg.wcr[hw_index] = 0; -// if (log) log->Printf ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", -// hw_index, -// hw_index, -// dbg.wvr[hw_index], -// hw_index, -// dbg.wcr[hw_index]); - - kret = WriteDBG(); - - if (kret == KERN_SUCCESS) - return true; - } +bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index) { + int kret = ReadDBG(false); + + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (kret == KERN_SUCCESS) { + if (hw_index < num_hw_points) { + dbg.wcr[hw_index] = 0; + // if (log) log->Printf + // ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - + // WVR%u = 0x%8.8x WCR%u = 0x%8.8x", + // hw_index, + // hw_index, + // dbg.wvr[hw_index], + // hw_index, + // dbg.wcr[hw_index]); + + kret = WriteDBG(); + + if (kret == KERN_SUCCESS) + return true; } - return false; + } + return false; } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h index 4e831b5a8da..cdf3479dff6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h @@ -14,317 +14,256 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" // BCR address match type -#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) -#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) -#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) -#define BCR_M_RESERVED ((uint32_t)(3u << 21)) +#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) +#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) +#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) +#define BCR_M_RESERVED ((uint32_t)(3u << 21)) // Link a BVR/BCR or WVR/WCR pair to another -#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) +#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) // Byte Address Select -#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) -#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) -#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) -#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) -#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) -#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) -#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) +#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) +#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) +#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) +#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) +#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) +#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) +#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) // Break only in privileged or user mode -#define S_RSVD ((uint32_t)(0u << 1)) -#define S_PRIV ((uint32_t)(1u << 1)) -#define S_USER ((uint32_t)(2u << 1)) -#define S_PRIV_USER ((S_PRIV) | (S_USER)) +#define S_RSVD ((uint32_t)(0u << 1)) +#define S_PRIV ((uint32_t)(1u << 1)) +#define S_USER ((uint32_t)(2u << 1)) +#define S_PRIV_USER ((S_PRIV) | (S_USER)) -#define BCR_ENABLE ((uint32_t)(1u)) -#define WCR_ENABLE ((uint32_t)(1u)) +#define BCR_ENABLE ((uint32_t)(1u)) +#define WCR_ENABLE ((uint32_t)(1u)) // Watchpoint load/store -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) +#define WCR_LOAD ((uint32_t)(1u << 3)) +#define WCR_STORE ((uint32_t)(1u << 4)) -class RegisterContextDarwin_arm : public lldb_private::RegisterContext -{ +class RegisterContextDarwin_arm : public lldb_private::RegisterContext { public: - RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx); + RegisterContextDarwin_arm(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); - ~RegisterContextDarwin_arm() override; + ~RegisterContextDarwin_arm() override; - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue ®_value) override; - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue ®_value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value) override; - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - uint32_t - NumSupportedHardwareBreakpoints() override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - uint32_t - SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - bool - ClearHardwareBreakpoint(uint32_t hw_idx) override; + uint32_t NumSupportedHardwareBreakpoints() override; - uint32_t - NumSupportedHardwareWatchpoints() override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - bool - ClearHardwareWatchpoint(uint32_t hw_index) override; + uint32_t NumSupportedHardwareWatchpoints() override; - struct GPR - { - uint32_t r[16]; // R0-R15 - uint32_t cpsr; // CPSR - }; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write) override; - struct QReg - { - uint8_t bytes[16]; - }; + bool ClearHardwareWatchpoint(uint32_t hw_index) override; - struct FPU - { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; + struct GPR { + uint32_t r[16]; // R0-R15 + uint32_t cpsr; // CPSR + }; -// struct NeonReg -// { -// uint8_t bytes[16]; -// }; -// -// struct VFPv3 -// { -// union { -// uint32_t s[32]; -// uint64_t d[32]; -// NeonReg q[16]; -// } v3; -// uint32_t fpscr; -// }; - - struct EXC - { - uint32_t exception; - uint32_t fsr; /* Fault status */ - uint32_t far; /* Virtual Fault Address */ - }; - - struct DBG - { - uint32_t bvr[16]; - uint32_t bcr[16]; - uint32_t wvr[16]; - uint32_t wcr[16]; - }; - - static void - LogDBGRegisters (lldb_private::Log *log, const DBG& dbg); + struct QReg { + uint8_t bytes[16]; + }; + + struct FPU { + union { + uint32_t s[32]; + uint64_t d[32]; + QReg q[16]; // the 128-bit NEON registers + } floats; + uint32_t fpscr; + }; + + // struct NeonReg + // { + // uint8_t bytes[16]; + // }; + // + // struct VFPv3 + // { + // union { + // uint32_t s[32]; + // uint64_t d[32]; + // NeonReg q[16]; + // } v3; + // uint32_t fpscr; + // }; + + struct EXC { + uint32_t exception; + uint32_t fsr; /* Fault status */ + uint32_t far; /* Virtual Fault Address */ + }; + + struct DBG { + uint32_t bvr[16]; + uint32_t bcr[16]; + uint32_t wvr[16]; + uint32_t wcr[16]; + }; + + static void LogDBGRegisters(lldb_private::Log *log, const DBG &dbg); protected: - enum - { - GPRRegSet = 1, // ARM_THREAD_STATE - GPRAltRegSet = 9, // ARM_THREAD_STATE32 - FPURegSet = 2, // ARM_VFP_STATE - EXCRegSet = 3, // ARM_EXCEPTION_STATE - DBGRegSet = 4 // ARM_DEBUG_STATE - }; - - enum - { - GPRWordCount = sizeof(GPR)/sizeof(uint32_t), - FPUWordCount = sizeof(FPU)/sizeof(uint32_t), - EXCWordCount = sizeof(EXC)/sizeof(uint32_t), - DBGWordCount = sizeof(DBG)/sizeof(uint32_t) - }; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - GPR gpr; - FPU fpu; - EXC exc; - DBG dbg; - int gpr_errs[2]; // Read/Write errors - int fpu_errs[2]; // Read/Write errors - int exc_errs[2]; // Read/Write errors - int dbg_errs[2]; // Read/Write errors - - void - InvalidateAllRegisterStates() - { - SetError (GPRRegSet, Read, -1); - SetError (FPURegSet, Read, -1); - SetError (EXCRegSet, Read, -1); + enum { + GPRRegSet = 1, // ARM_THREAD_STATE + GPRAltRegSet = 9, // ARM_THREAD_STATE32 + FPURegSet = 2, // ARM_VFP_STATE + EXCRegSet = 3, // ARM_EXCEPTION_STATE + DBGRegSet = 4 // ARM_DEBUG_STATE + }; + + enum { + GPRWordCount = sizeof(GPR) / sizeof(uint32_t), + FPUWordCount = sizeof(FPU) / sizeof(uint32_t), + EXCWordCount = sizeof(EXC) / sizeof(uint32_t), + DBGWordCount = sizeof(DBG) / sizeof(uint32_t) + }; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + GPR gpr; + FPU fpu; + EXC exc; + DBG dbg; + int gpr_errs[2]; // Read/Write errors + int fpu_errs[2]; // Read/Write errors + int exc_errs[2]; // Read/Write errors + int dbg_errs[2]; // Read/Write errors + + void InvalidateAllRegisterStates() { + SetError(GPRRegSet, Read, -1); + SetError(FPURegSet, Read, -1); + SetError(EXCRegSet, Read, -1); + } + + int GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case GPRRegSet: + return gpr_errs[err_idx]; + case FPURegSet: + return fpu_errs[err_idx]; + case EXCRegSet: + return exc_errs[err_idx]; + case DBGRegSet: + return dbg_errs[err_idx]; + default: + break; + } } - - int - GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case GPRRegSet: return gpr_errs[err_idx]; - case FPURegSet: return fpu_errs[err_idx]; - case EXCRegSet: return exc_errs[err_idx]; - case DBGRegSet: return dbg_errs[err_idx]; - default: break; - } - } - return -1; + return -1; + } + + bool SetError(int flavor, uint32_t err_idx, int err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case GPRRegSet: + gpr_errs[err_idx] = err; + return true; + + case FPURegSet: + fpu_errs[err_idx] = err; + return true; + + case EXCRegSet: + exc_errs[err_idx] = err; + return true; + + case DBGRegSet: + exc_errs[err_idx] = err; + return true; + + default: + break; + } } + return false; + } - bool - SetError (int flavor, uint32_t err_idx, int err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case GPRRegSet: - gpr_errs[err_idx] = err; - return true; - - case FPURegSet: - fpu_errs[err_idx] = err; - return true; - - case EXCRegSet: - exc_errs[err_idx] = err; - return true; - - case DBGRegSet: - exc_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; - } + bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; } - bool - RegisterSetIsCached (int set) const - { - return GetError(set, Read) == 0; - } + int ReadGPR(bool force); - int - ReadGPR (bool force); + int ReadFPU(bool force); - int - ReadFPU (bool force); + int ReadEXC(bool force); - int - ReadEXC (bool force); + int ReadDBG(bool force); - int - ReadDBG (bool force); + int WriteGPR(); - int - WriteGPR (); + int WriteFPU(); - int - WriteFPU (); + int WriteEXC(); - int - WriteEXC (); + int WriteDBG(); - int - WriteDBG (); + // Subclasses override these to do the actual reading. + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { return -1; } - - // Subclasses override these to do the actual reading. - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) - { - return -1; - } - - virtual int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0; - - virtual int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0; + virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0; + + virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0; + + virtual int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) = 0; + + virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - virtual int - DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0; + virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - virtual int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - - virtual int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - - virtual int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0; + virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0; - virtual int - DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0; + virtual int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) = 0; - int - ReadRegisterSet (uint32_t set, bool force); + int ReadRegisterSet(uint32_t set, bool force); - int - WriteRegisterSet (uint32_t set); + int WriteRegisterSet(uint32_t set); - static uint32_t - GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num); + static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num); - static int - GetSetForNativeRegNum (int reg_num); + static int GetSetForNativeRegNum(int reg_num); - static size_t - GetRegisterInfosCount (); + static size_t GetRegisterInfosCount(); - static const lldb_private::RegisterInfo * - GetRegisterInfos (); + static const lldb_private::RegisterInfo *GetRegisterInfos(); }; #endif // liblldb_RegisterContextDarwin_arm_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 53cb9dea0fb..d839843a26e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++ -*-===// +//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -41,18 +42,36 @@ using namespace lldb; using namespace lldb_private; - -#define GPR_OFFSET(idx) ((idx) * 8) -#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg)) - -#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextDarwin_arm64::GPR)) -#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::FPU, reg)) - -#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU)) -#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC)) - -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC)) +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg)) + +#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR)) +#define FPU_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg)) + +#define EXC_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) + \ + sizeof(RegisterContextDarwin_arm64::GPR) + \ + sizeof(RegisterContextDarwin_arm64::FPU)) +#define DBG_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) + \ + sizeof(RegisterContextDarwin_arm64::GPR) + \ + sizeof(RegisterContextDarwin_arm64::FPU) + \ + sizeof(RegisterContextDarwin_arm64::EXC)) + +#define DEFINE_DBG(reg, i) \ + #reg, NULL, \ + sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]), \ + DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM }, \ + NULL, NULL, NULL, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextDarwin_arm64::GPR) + \ + sizeof(RegisterContextDarwin_arm64::FPU) + \ + sizeof(RegisterContextDarwin_arm64::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure. @@ -62,153 +81,66 @@ using namespace lldb_private; #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT // General purpose registers -static uint32_t -g_gpr_regnums[] = -{ - gpr_x0, - gpr_x1, - gpr_x2, - gpr_x3, - gpr_x4, - gpr_x5, - gpr_x6, - gpr_x7, - gpr_x8, - gpr_x9, - gpr_x10, - gpr_x11, - gpr_x12, - gpr_x13, - gpr_x14, - gpr_x15, - gpr_x16, - gpr_x17, - gpr_x18, - gpr_x19, - gpr_x20, - gpr_x21, - gpr_x22, - gpr_x23, - gpr_x24, - gpr_x25, - gpr_x26, - gpr_x27, - gpr_x28, - gpr_fp, - gpr_lr, - gpr_sp, - gpr_pc, - gpr_cpsr -}; +static uint32_t g_gpr_regnums[] = { + gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6, + gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13, + gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20, + gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27, + gpr_x28, gpr_fp, gpr_lr, gpr_sp, gpr_pc, gpr_cpsr}; // Floating point registers -static uint32_t -g_fpu_regnums[] = -{ - fpu_v0, - fpu_v1, - fpu_v2, - fpu_v3, - fpu_v4, - fpu_v5, - fpu_v6, - fpu_v7, - fpu_v8, - fpu_v9, - fpu_v10, - fpu_v11, - fpu_v12, - fpu_v13, - fpu_v14, - fpu_v15, - fpu_v16, - fpu_v17, - fpu_v18, - fpu_v19, - fpu_v20, - fpu_v21, - fpu_v22, - fpu_v23, - fpu_v24, - fpu_v25, - fpu_v26, - fpu_v27, - fpu_v28, - fpu_v29, - fpu_v30, - fpu_v31, - fpu_fpsr, - fpu_fpcr -}; +static uint32_t g_fpu_regnums[] = { + fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6, + fpu_v7, fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13, + fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20, + fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25, fpu_v26, fpu_v27, + fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr}; // Exception registers -static uint32_t -g_exc_regnums[] = -{ - exc_far, - exc_esr, - exc_exception -}; - -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64); - -RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext(thread, concrete_frame_idx), - gpr(), - fpu(), - exc() -{ - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } -} +static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception}; + +static size_t k_num_register_infos = + llvm::array_lengthof(g_register_infos_arm64); -RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() -{ +RegisterContextDarwin_arm64::RegisterContextDarwin_arm64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + } } +RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {} -void -RegisterContextDarwin_arm64::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); +void RegisterContextDarwin_arm64::InvalidateAllRegisters() { + InvalidateAllRegisterStates(); } - -size_t -RegisterContextDarwin_arm64::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; +size_t RegisterContextDarwin_arm64::GetRegisterCount() { + assert(k_num_register_infos == k_num_registers); + return k_num_registers; } const RegisterInfo * -RegisterContextDarwin_arm64::GetRegisterInfoAtIndex (size_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos_arm64[reg]; - return NULL; +RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) { + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos_arm64[reg]; + return NULL; } -size_t -RegisterContextDarwin_arm64::GetRegisterInfosCount () -{ - return k_num_register_infos; +size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() { + return k_num_register_infos; } -const RegisterInfo * -RegisterContextDarwin_arm64::GetRegisterInfos () -{ - return g_register_infos_arm64; +const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() { + return g_register_infos_arm64; } - // Number of registers in each register set const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); @@ -219,726 +151,773 @@ const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -static const RegisterSet g_reg_sets[] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }, - { "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums } -}; +static const RegisterSet g_reg_sets[] = { + { + "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, + }, + {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, + {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); - -size_t -RegisterContextDarwin_arm64::GetRegisterSetCount () -{ - return k_num_regsets; +size_t RegisterContextDarwin_arm64::GetRegisterSetCount() { + return k_num_regsets; } -const RegisterSet * -RegisterContextDarwin_arm64::GetRegisterSet (size_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; +const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) { + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; } - //---------------------------------------------------------------------- // Register information definitions for arm64 //---------------------------------------------------------------------- -int -RegisterContextDarwin_arm64::GetSetForNativeRegNum (int reg) -{ - if (reg < fpu_v0) - return GPRRegSet; - else if (reg < exc_far) - return FPURegSet; - else if (reg < k_num_registers) - return EXCRegSet; - return -1; +int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) { + if (reg < fpu_v0) + return GPRRegSet; + else if (reg < exc_far) + return FPURegSet; + else if (reg < k_num_registers) + return EXCRegSet; + return -1; } -int -RegisterContextDarwin_arm64::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); - } - return GetError(GPRRegSet, Read); +int RegisterContextDarwin_arm64::ReadGPR(bool force) { + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(GPRRegSet, Read); } -int -RegisterContextDarwin_arm64::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); - } - return GetError(FPURegSet, Read); +int RegisterContextDarwin_arm64::ReadFPU(bool force) { + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(FPURegSet, Read); } -int -RegisterContextDarwin_arm64::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); - } - return GetError(EXCRegSet, Read); -} - -int -RegisterContextDarwin_arm64::ReadDBG (bool force) -{ - int set = DBGRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg)); - } - return GetError(DBGRegSet, Read); +int RegisterContextDarwin_arm64::ReadEXC(bool force) { + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(EXCRegSet, Read); } -int -RegisterContextDarwin_arm64::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr)); - SetError (set, Read, -1); - return GetError(GPRRegSet, Write); +int RegisterContextDarwin_arm64::ReadDBG(bool force) { + int set = DBGRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg)); + } + return GetError(DBGRegSet, Read); } -int -RegisterContextDarwin_arm64::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu)); - SetError (set, Read, -1); - return GetError(FPURegSet, Write); +int RegisterContextDarwin_arm64::WriteGPR() { + int set = GPRRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr)); + SetError(set, Read, -1); + return GetError(GPRRegSet, Write); } -int -RegisterContextDarwin_arm64::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc)); - SetError (set, Read, -1); - return GetError(EXCRegSet, Write); +int RegisterContextDarwin_arm64::WriteFPU() { + int set = FPURegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu)); + SetError(set, Read, -1); + return GetError(FPURegSet, Write); } -int -RegisterContextDarwin_arm64::WriteDBG () -{ - int set = DBGRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg)); - SetError (set, Read, -1); - return GetError(DBGRegSet, Write); +int RegisterContextDarwin_arm64::WriteEXC() { + int set = EXCRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc)); + SetError(set, Read, -1); + return GetError(EXCRegSet, Write); } - -int -RegisterContextDarwin_arm64::ReadRegisterSet (uint32_t set, bool force) -{ - switch (set) - { - case GPRRegSet: return ReadGPR(force); - case FPURegSet: return ReadFPU(force); - case EXCRegSet: return ReadEXC(force); - case DBGRegSet: return ReadDBG(force); - default: break; - } +int RegisterContextDarwin_arm64::WriteDBG() { + int set = DBGRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); return KERN_INVALID_ARGUMENT; + } + SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg)); + SetError(set, Read, -1); + return GetError(DBGRegSet, Write); } -int -RegisterContextDarwin_arm64::WriteRegisterSet (uint32_t set) -{ - // Make sure we have a valid context to set. - if (RegisterSetIsCached(set)) - { - switch (set) - { - case GPRRegSet: return WriteGPR(); - case FPURegSet: return WriteFPU(); - case EXCRegSet: return WriteEXC(); - case DBGRegSet: return WriteDBG(); - default: break; - } - } - return KERN_INVALID_ARGUMENT; +int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) { + switch (set) { + case GPRRegSet: + return ReadGPR(force); + case FPURegSet: + return ReadFPU(force); + case EXCRegSet: + return ReadEXC(force); + case DBGRegSet: + return ReadDBG(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -void -RegisterContextDarwin_arm64::LogDBGRegisters (Log *log, const DBG& dbg) -{ - if (log) - { - for (uint32_t i=0; i<16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u = { 0x%8.8llx, 0x%8.8llx }", - i, i, dbg.bvr[i], dbg.bcr[i], - i, i, dbg.wvr[i], dbg.wcr[i]); +int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) { + // Make sure we have a valid context to set. + if (RegisterSetIsCached(set)) { + switch (set) { + case GPRRegSet: + return WriteGPR(); + case FPURegSet: + return WriteFPU(); + case EXCRegSet: + return WriteEXC(); + case DBGRegSet: + return WriteDBG(); + default: + break; } + } + return KERN_INVALID_ARGUMENT; } +void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) { + if (log) { + for (uint32_t i = 0; i < 16; i++) + log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u " + "= { 0x%8.8llx, 0x%8.8llx }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + } +} -bool -RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; +bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg); - switch (reg) - { - case gpr_x0: - case gpr_x1: - case gpr_x2: - case gpr_x3: - case gpr_x4: - case gpr_x5: - case gpr_x6: - case gpr_x7: - case gpr_x8: - case gpr_x9: - case gpr_x10: - case gpr_x11: - case gpr_x12: - case gpr_x13: - case gpr_x14: - case gpr_x15: - case gpr_x16: - case gpr_x17: - case gpr_x18: - case gpr_x19: - case gpr_x20: - case gpr_x21: - case gpr_x22: - case gpr_x23: - case gpr_x24: - case gpr_x25: - case gpr_x26: - case gpr_x27: - case gpr_x28: - case gpr_fp: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - value.SetUInt64 (gpr.x[reg - gpr_x0]); - break; - - case fpu_v0: - case fpu_v1: - case fpu_v2: - case fpu_v3: - case fpu_v4: - case fpu_v5: - case fpu_v6: - case fpu_v7: - case fpu_v8: - case fpu_v9: - case fpu_v10: - case fpu_v11: - case fpu_v12: - case fpu_v13: - case fpu_v14: - case fpu_v15: - case fpu_v16: - case fpu_v17: - case fpu_v18: - case fpu_v19: - case fpu_v20: - case fpu_v21: - case fpu_v22: - case fpu_v23: - case fpu_v24: - case fpu_v25: - case fpu_v26: - case fpu_v27: - case fpu_v28: - case fpu_v29: - case fpu_v30: - case fpu_v31: - value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, endian::InlHostByteOrder()); - break; - - case fpu_fpsr: - value.SetUInt32 (fpu.fpsr); - break; - - case fpu_fpcr: - value.SetUInt32 (fpu.fpcr); - break; - - case exc_exception: - value.SetUInt32 (exc.exception); - break; - case exc_esr: - value.SetUInt32 (exc.esr); - break; - case exc_far: - value.SetUInt64 (exc.far); - break; + if (set == -1) + return false; - default: - value.SetValueToInvalid(); - return false; + if (ReadRegisterSet(set, false) != KERN_SUCCESS) + return false; - } - return true; + switch (reg) { + case gpr_x0: + case gpr_x1: + case gpr_x2: + case gpr_x3: + case gpr_x4: + case gpr_x5: + case gpr_x6: + case gpr_x7: + case gpr_x8: + case gpr_x9: + case gpr_x10: + case gpr_x11: + case gpr_x12: + case gpr_x13: + case gpr_x14: + case gpr_x15: + case gpr_x16: + case gpr_x17: + case gpr_x18: + case gpr_x19: + case gpr_x20: + case gpr_x21: + case gpr_x22: + case gpr_x23: + case gpr_x24: + case gpr_x25: + case gpr_x26: + case gpr_x27: + case gpr_x28: + case gpr_fp: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + value.SetUInt64(gpr.x[reg - gpr_x0]); + break; + + case fpu_v0: + case fpu_v1: + case fpu_v2: + case fpu_v3: + case fpu_v4: + case fpu_v5: + case fpu_v6: + case fpu_v7: + case fpu_v8: + case fpu_v9: + case fpu_v10: + case fpu_v11: + case fpu_v12: + case fpu_v13: + case fpu_v14: + case fpu_v15: + case fpu_v16: + case fpu_v17: + case fpu_v18: + case fpu_v19: + case fpu_v20: + case fpu_v21: + case fpu_v22: + case fpu_v23: + case fpu_v24: + case fpu_v25: + case fpu_v26: + case fpu_v27: + case fpu_v28: + case fpu_v29: + case fpu_v30: + case fpu_v31: + value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, + endian::InlHostByteOrder()); + break; + + case fpu_fpsr: + value.SetUInt32(fpu.fpsr); + break; + + case fpu_fpcr: + value.SetUInt32(fpu.fpcr); + break; + + case exc_exception: + value.SetUInt32(exc.exception); + break; + case exc_esr: + value.SetUInt32(exc.esr); + break; + case exc_far: + value.SetUInt64(exc.far); + break; + + default: + value.SetValueToInvalid(); + return false; + } + return true; } +bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = GetSetForNativeRegNum(reg); -bool -RegisterContextDarwin_arm64::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_x0: - case gpr_x1: - case gpr_x2: - case gpr_x3: - case gpr_x4: - case gpr_x5: - case gpr_x6: - case gpr_x7: - case gpr_x8: - case gpr_x9: - case gpr_x10: - case gpr_x11: - case gpr_x12: - case gpr_x13: - case gpr_x14: - case gpr_x15: - case gpr_x16: - case gpr_x17: - case gpr_x18: - case gpr_x19: - case gpr_x20: - case gpr_x21: - case gpr_x22: - case gpr_x23: - case gpr_x24: - case gpr_x25: - case gpr_x26: - case gpr_x27: - case gpr_x28: - case gpr_fp: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - gpr.x[reg - gpr_x0] = value.GetAsUInt64(); - break; - - case fpu_v0: - case fpu_v1: - case fpu_v2: - case fpu_v3: - case fpu_v4: - case fpu_v5: - case fpu_v6: - case fpu_v7: - case fpu_v8: - case fpu_v9: - case fpu_v10: - case fpu_v11: - case fpu_v12: - case fpu_v13: - case fpu_v14: - case fpu_v15: - case fpu_v16: - case fpu_v17: - case fpu_v18: - case fpu_v19: - case fpu_v20: - case fpu_v21: - case fpu_v22: - case fpu_v23: - case fpu_v24: - case fpu_v25: - case fpu_v26: - case fpu_v27: - case fpu_v28: - case fpu_v29: - case fpu_v30: - case fpu_v31: - ::memcpy (fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize()); - break; - - case fpu_fpsr: - fpu.fpsr = value.GetAsUInt32(); - break; - - case fpu_fpcr: - fpu.fpcr = value.GetAsUInt32(); - break; - - case exc_exception: - exc.exception = value.GetAsUInt32(); - break; - case exc_esr: - exc.esr = value.GetAsUInt32(); - break; - case exc_far: - exc.far = value.GetAsUInt64(); - break; + if (set == -1) + return false; - default: - return false; + if (ReadRegisterSet(set, false) != KERN_SUCCESS) + return false; - } - return WriteRegisterSet(set) == KERN_SUCCESS; + switch (reg) { + case gpr_x0: + case gpr_x1: + case gpr_x2: + case gpr_x3: + case gpr_x4: + case gpr_x5: + case gpr_x6: + case gpr_x7: + case gpr_x8: + case gpr_x9: + case gpr_x10: + case gpr_x11: + case gpr_x12: + case gpr_x13: + case gpr_x14: + case gpr_x15: + case gpr_x16: + case gpr_x17: + case gpr_x18: + case gpr_x19: + case gpr_x20: + case gpr_x21: + case gpr_x22: + case gpr_x23: + case gpr_x24: + case gpr_x25: + case gpr_x26: + case gpr_x27: + case gpr_x28: + case gpr_fp: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + gpr.x[reg - gpr_x0] = value.GetAsUInt64(); + break; + + case fpu_v0: + case fpu_v1: + case fpu_v2: + case fpu_v3: + case fpu_v4: + case fpu_v5: + case fpu_v6: + case fpu_v7: + case fpu_v8: + case fpu_v9: + case fpu_v10: + case fpu_v11: + case fpu_v12: + case fpu_v13: + case fpu_v14: + case fpu_v15: + case fpu_v16: + case fpu_v17: + case fpu_v18: + case fpu_v19: + case fpu_v20: + case fpu_v21: + case fpu_v22: + case fpu_v23: + case fpu_v24: + case fpu_v25: + case fpu_v26: + case fpu_v27: + case fpu_v28: + case fpu_v29: + case fpu_v30: + case fpu_v31: + ::memcpy(fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize()); + break; + + case fpu_fpsr: + fpu.fpsr = value.GetAsUInt32(); + break; + + case fpu_fpcr: + fpu.fpcr = value.GetAsUInt32(); + break; + + case exc_exception: + exc.exception = value.GetAsUInt32(); + break; + case exc_esr: + exc.esr = value.GetAsUInt32(); + break; + case exc_far: + exc.far = value.GetAsUInt64(); + break; + + default: + return false; + } + return WriteRegisterSet(set) == KERN_SUCCESS; } -bool -RegisterContextDarwin_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == KERN_SUCCESS && - ReadFPU (false) == KERN_SUCCESS && - ReadEXC (false) == KERN_SUCCESS) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &gpr, sizeof(gpr)); - dst += sizeof(gpr); +bool RegisterContextDarwin_arm64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR(false) == KERN_SUCCESS && + ReadFPU(false) == KERN_SUCCESS && ReadEXC(false) == KERN_SUCCESS) { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy(dst, &gpr, sizeof(gpr)); + dst += sizeof(gpr); - ::memcpy (dst, &fpu, sizeof(fpu)); - dst += sizeof(gpr); + ::memcpy(dst, &fpu, sizeof(fpu)); + dst += sizeof(gpr); - ::memcpy (dst, &exc, sizeof(exc)); - return true; - } - return false; + ::memcpy(dst, &exc, sizeof(exc)); + return true; + } + return false; } -bool -RegisterContextDarwin_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&gpr, src, sizeof(gpr)); - src += sizeof(gpr); - - ::memcpy (&fpu, src, sizeof(fpu)); - src += sizeof(gpr); - - ::memcpy (&exc, src, sizeof(exc)); - uint32_t success_count = 0; - if (WriteGPR() == KERN_SUCCESS) - ++success_count; - if (WriteFPU() == KERN_SUCCESS) - ++success_count; - if (WriteEXC() == KERN_SUCCESS) - ++success_count; - return success_count == 3; - } - return false; +bool RegisterContextDarwin_arm64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy(&gpr, src, sizeof(gpr)); + src += sizeof(gpr); + + ::memcpy(&fpu, src, sizeof(fpu)); + src += sizeof(gpr); + + ::memcpy(&exc, src, sizeof(exc)); + uint32_t success_count = 0; + if (WriteGPR() == KERN_SUCCESS) + ++success_count; + if (WriteFPU() == KERN_SUCCESS) + ++success_count; + if (WriteEXC() == KERN_SUCCESS) + ++success_count; + return success_count == 3; + } + return false; } -uint32_t -RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind kind, uint32_t reg) -{ - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_pc; - case LLDB_REGNUM_GENERIC_SP: return gpr_sp; - case LLDB_REGNUM_GENERIC_FP: return gpr_fp; - case LLDB_REGNUM_GENERIC_RA: return gpr_lr; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr; - default: - break; - } - } - else if (kind == eRegisterKindDWARF) - { - switch (reg) - { - case arm64_dwarf::x0: return gpr_x0; - case arm64_dwarf::x1: return gpr_x1; - case arm64_dwarf::x2: return gpr_x2; - case arm64_dwarf::x3: return gpr_x3; - case arm64_dwarf::x4: return gpr_x4; - case arm64_dwarf::x5: return gpr_x5; - case arm64_dwarf::x6: return gpr_x6; - case arm64_dwarf::x7: return gpr_x7; - case arm64_dwarf::x8: return gpr_x8; - case arm64_dwarf::x9: return gpr_x9; - case arm64_dwarf::x10: return gpr_x10; - case arm64_dwarf::x11: return gpr_x11; - case arm64_dwarf::x12: return gpr_x12; - case arm64_dwarf::x13: return gpr_x13; - case arm64_dwarf::x14: return gpr_x14; - case arm64_dwarf::x15: return gpr_x15; - case arm64_dwarf::x16: return gpr_x16; - case arm64_dwarf::x17: return gpr_x17; - case arm64_dwarf::x18: return gpr_x18; - case arm64_dwarf::x19: return gpr_x19; - case arm64_dwarf::x20: return gpr_x20; - case arm64_dwarf::x21: return gpr_x21; - case arm64_dwarf::x22: return gpr_x22; - case arm64_dwarf::x23: return gpr_x23; - case arm64_dwarf::x24: return gpr_x24; - case arm64_dwarf::x25: return gpr_x25; - case arm64_dwarf::x26: return gpr_x26; - case arm64_dwarf::x27: return gpr_x27; - case arm64_dwarf::x28: return gpr_x28; - - case arm64_dwarf::fp: return gpr_fp; - case arm64_dwarf::sp: return gpr_sp; - case arm64_dwarf::lr: return gpr_lr; - case arm64_dwarf::pc: return gpr_pc; - case arm64_dwarf::cpsr: return gpr_cpsr; - - case arm64_dwarf::v0: return fpu_v0; - case arm64_dwarf::v1: return fpu_v1; - case arm64_dwarf::v2: return fpu_v2; - case arm64_dwarf::v3: return fpu_v3; - case arm64_dwarf::v4: return fpu_v4; - case arm64_dwarf::v5: return fpu_v5; - case arm64_dwarf::v6: return fpu_v6; - case arm64_dwarf::v7: return fpu_v7; - case arm64_dwarf::v8: return fpu_v8; - case arm64_dwarf::v9: return fpu_v9; - case arm64_dwarf::v10: return fpu_v10; - case arm64_dwarf::v11: return fpu_v11; - case arm64_dwarf::v12: return fpu_v12; - case arm64_dwarf::v13: return fpu_v13; - case arm64_dwarf::v14: return fpu_v14; - case arm64_dwarf::v15: return fpu_v15; - case arm64_dwarf::v16: return fpu_v16; - case arm64_dwarf::v17: return fpu_v17; - case arm64_dwarf::v18: return fpu_v18; - case arm64_dwarf::v19: return fpu_v19; - case arm64_dwarf::v20: return fpu_v20; - case arm64_dwarf::v21: return fpu_v21; - case arm64_dwarf::v22: return fpu_v22; - case arm64_dwarf::v23: return fpu_v23; - case arm64_dwarf::v24: return fpu_v24; - case arm64_dwarf::v25: return fpu_v25; - case arm64_dwarf::v26: return fpu_v26; - case arm64_dwarf::v27: return fpu_v27; - case arm64_dwarf::v28: return fpu_v28; - case arm64_dwarf::v29: return fpu_v29; - case arm64_dwarf::v30: return fpu_v30; - case arm64_dwarf::v31: return fpu_v31; - - default: - break; - } +uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber( + RegisterKind kind, uint32_t reg) { + if (kind == eRegisterKindGeneric) { + switch (reg) { + case LLDB_REGNUM_GENERIC_PC: + return gpr_pc; + case LLDB_REGNUM_GENERIC_SP: + return gpr_sp; + case LLDB_REGNUM_GENERIC_FP: + return gpr_fp; + case LLDB_REGNUM_GENERIC_RA: + return gpr_lr; + case LLDB_REGNUM_GENERIC_FLAGS: + return gpr_cpsr; + default: + break; } - else if (kind == eRegisterKindEHFrame) - { - switch (reg) - { - case arm64_ehframe::x0: return gpr_x0; - case arm64_ehframe::x1: return gpr_x1; - case arm64_ehframe::x2: return gpr_x2; - case arm64_ehframe::x3: return gpr_x3; - case arm64_ehframe::x4: return gpr_x4; - case arm64_ehframe::x5: return gpr_x5; - case arm64_ehframe::x6: return gpr_x6; - case arm64_ehframe::x7: return gpr_x7; - case arm64_ehframe::x8: return gpr_x8; - case arm64_ehframe::x9: return gpr_x9; - case arm64_ehframe::x10: return gpr_x10; - case arm64_ehframe::x11: return gpr_x11; - case arm64_ehframe::x12: return gpr_x12; - case arm64_ehframe::x13: return gpr_x13; - case arm64_ehframe::x14: return gpr_x14; - case arm64_ehframe::x15: return gpr_x15; - case arm64_ehframe::x16: return gpr_x16; - case arm64_ehframe::x17: return gpr_x17; - case arm64_ehframe::x18: return gpr_x18; - case arm64_ehframe::x19: return gpr_x19; - case arm64_ehframe::x20: return gpr_x20; - case arm64_ehframe::x21: return gpr_x21; - case arm64_ehframe::x22: return gpr_x22; - case arm64_ehframe::x23: return gpr_x23; - case arm64_ehframe::x24: return gpr_x24; - case arm64_ehframe::x25: return gpr_x25; - case arm64_ehframe::x26: return gpr_x26; - case arm64_ehframe::x27: return gpr_x27; - case arm64_ehframe::x28: return gpr_x28; - case arm64_ehframe::fp: return gpr_fp; - case arm64_ehframe::sp: return gpr_sp; - case arm64_ehframe::lr: return gpr_lr; - case arm64_ehframe::pc: return gpr_pc; - case arm64_ehframe::cpsr: return gpr_cpsr; - } + } else if (kind == eRegisterKindDWARF) { + switch (reg) { + case arm64_dwarf::x0: + return gpr_x0; + case arm64_dwarf::x1: + return gpr_x1; + case arm64_dwarf::x2: + return gpr_x2; + case arm64_dwarf::x3: + return gpr_x3; + case arm64_dwarf::x4: + return gpr_x4; + case arm64_dwarf::x5: + return gpr_x5; + case arm64_dwarf::x6: + return gpr_x6; + case arm64_dwarf::x7: + return gpr_x7; + case arm64_dwarf::x8: + return gpr_x8; + case arm64_dwarf::x9: + return gpr_x9; + case arm64_dwarf::x10: + return gpr_x10; + case arm64_dwarf::x11: + return gpr_x11; + case arm64_dwarf::x12: + return gpr_x12; + case arm64_dwarf::x13: + return gpr_x13; + case arm64_dwarf::x14: + return gpr_x14; + case arm64_dwarf::x15: + return gpr_x15; + case arm64_dwarf::x16: + return gpr_x16; + case arm64_dwarf::x17: + return gpr_x17; + case arm64_dwarf::x18: + return gpr_x18; + case arm64_dwarf::x19: + return gpr_x19; + case arm64_dwarf::x20: + return gpr_x20; + case arm64_dwarf::x21: + return gpr_x21; + case arm64_dwarf::x22: + return gpr_x22; + case arm64_dwarf::x23: + return gpr_x23; + case arm64_dwarf::x24: + return gpr_x24; + case arm64_dwarf::x25: + return gpr_x25; + case arm64_dwarf::x26: + return gpr_x26; + case arm64_dwarf::x27: + return gpr_x27; + case arm64_dwarf::x28: + return gpr_x28; + + case arm64_dwarf::fp: + return gpr_fp; + case arm64_dwarf::sp: + return gpr_sp; + case arm64_dwarf::lr: + return gpr_lr; + case arm64_dwarf::pc: + return gpr_pc; + case arm64_dwarf::cpsr: + return gpr_cpsr; + + case arm64_dwarf::v0: + return fpu_v0; + case arm64_dwarf::v1: + return fpu_v1; + case arm64_dwarf::v2: + return fpu_v2; + case arm64_dwarf::v3: + return fpu_v3; + case arm64_dwarf::v4: + return fpu_v4; + case arm64_dwarf::v5: + return fpu_v5; + case arm64_dwarf::v6: + return fpu_v6; + case arm64_dwarf::v7: + return fpu_v7; + case arm64_dwarf::v8: + return fpu_v8; + case arm64_dwarf::v9: + return fpu_v9; + case arm64_dwarf::v10: + return fpu_v10; + case arm64_dwarf::v11: + return fpu_v11; + case arm64_dwarf::v12: + return fpu_v12; + case arm64_dwarf::v13: + return fpu_v13; + case arm64_dwarf::v14: + return fpu_v14; + case arm64_dwarf::v15: + return fpu_v15; + case arm64_dwarf::v16: + return fpu_v16; + case arm64_dwarf::v17: + return fpu_v17; + case arm64_dwarf::v18: + return fpu_v18; + case arm64_dwarf::v19: + return fpu_v19; + case arm64_dwarf::v20: + return fpu_v20; + case arm64_dwarf::v21: + return fpu_v21; + case arm64_dwarf::v22: + return fpu_v22; + case arm64_dwarf::v23: + return fpu_v23; + case arm64_dwarf::v24: + return fpu_v24; + case arm64_dwarf::v25: + return fpu_v25; + case arm64_dwarf::v26: + return fpu_v26; + case arm64_dwarf::v27: + return fpu_v27; + case arm64_dwarf::v28: + return fpu_v28; + case arm64_dwarf::v29: + return fpu_v29; + case arm64_dwarf::v30: + return fpu_v30; + case arm64_dwarf::v31: + return fpu_v31; + + default: + break; } - else if (kind == eRegisterKindLLDB) - { - return reg; + } else if (kind == eRegisterKindEHFrame) { + switch (reg) { + case arm64_ehframe::x0: + return gpr_x0; + case arm64_ehframe::x1: + return gpr_x1; + case arm64_ehframe::x2: + return gpr_x2; + case arm64_ehframe::x3: + return gpr_x3; + case arm64_ehframe::x4: + return gpr_x4; + case arm64_ehframe::x5: + return gpr_x5; + case arm64_ehframe::x6: + return gpr_x6; + case arm64_ehframe::x7: + return gpr_x7; + case arm64_ehframe::x8: + return gpr_x8; + case arm64_ehframe::x9: + return gpr_x9; + case arm64_ehframe::x10: + return gpr_x10; + case arm64_ehframe::x11: + return gpr_x11; + case arm64_ehframe::x12: + return gpr_x12; + case arm64_ehframe::x13: + return gpr_x13; + case arm64_ehframe::x14: + return gpr_x14; + case arm64_ehframe::x15: + return gpr_x15; + case arm64_ehframe::x16: + return gpr_x16; + case arm64_ehframe::x17: + return gpr_x17; + case arm64_ehframe::x18: + return gpr_x18; + case arm64_ehframe::x19: + return gpr_x19; + case arm64_ehframe::x20: + return gpr_x20; + case arm64_ehframe::x21: + return gpr_x21; + case arm64_ehframe::x22: + return gpr_x22; + case arm64_ehframe::x23: + return gpr_x23; + case arm64_ehframe::x24: + return gpr_x24; + case arm64_ehframe::x25: + return gpr_x25; + case arm64_ehframe::x26: + return gpr_x26; + case arm64_ehframe::x27: + return gpr_x27; + case arm64_ehframe::x28: + return gpr_x28; + case arm64_ehframe::fp: + return gpr_fp; + case arm64_ehframe::sp: + return gpr_sp; + case arm64_ehframe::lr: + return gpr_lr; + case arm64_ehframe::pc: + return gpr_pc; + case arm64_ehframe::cpsr: + return gpr_cpsr; } - return LLDB_INVALID_REGNUM; + } else if (kind == eRegisterKindLLDB) { + return reg; + } + return LLDB_INVALID_REGNUM; } - -uint32_t -RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints () -{ -#if defined (__arm64__) || defined (__aarch64__) - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; - if (g_num_supported_hw_watchpoints == UINT32_MAX) - { - size_t len; - uint32_t n = 0; - len = sizeof (n); - if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) - { - g_num_supported_hw_watchpoints = n; - } +uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() { +#if defined(__arm64__) || defined(__aarch64__) + // autodetect how many watchpoints are supported dynamically... + static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; + if (g_num_supported_hw_watchpoints == UINT32_MAX) { + size_t len; + uint32_t n = 0; + len = sizeof(n); + if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) { + g_num_supported_hw_watchpoints = n; } - return g_num_supported_hw_watchpoints; + } + return g_num_supported_hw_watchpoints; #else - // TODO: figure out remote case here! - return 2; + // TODO: figure out remote case here! + return 2; #endif } +uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, + bool read, + bool write) { + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p, + // size = %u, read = %u, write = %u)", addr, size, read, write); -uint32_t -RegisterContextDarwin_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) -{ -// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + // Can't watch zero bytes + if (size == 0) + return LLDB_INVALID_INDEX32; - // Can't watch zero bytes - if (size == 0) - return LLDB_INVALID_INDEX32; + // We must watch for either read or write + if (read == false && write == false) + return LLDB_INVALID_INDEX32; - // We must watch for either read or write - if (read == false && write == false) - return LLDB_INVALID_INDEX32; + // Can't watch more than 4 bytes per WVR/WCR pair + if (size > 4) + return LLDB_INVALID_INDEX32; - // Can't watch more than 4 bytes per WVR/WCR pair - if (size > 4) - return LLDB_INVALID_INDEX32; + // We can only watch up to four bytes that follow a 4 byte aligned address + // per watchpoint register pair. Since we have at most so we can only watch + // until the next 4 byte boundary and we need to make sure we can properly + // encode this. + uint32_t addr_word_offset = addr % 4; + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - + // addr_word_offset = 0x%8.8x", addr_word_offset); + + uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask = + // 0x%8.8x", byte_mask); + if (byte_mask > 0xfu) + return LLDB_INVALID_INDEX32; - // We can only watch up to four bytes that follow a 4 byte aligned address - // per watchpoint register pair. Since we have at most so we can only watch - // until the next 4 byte boundary and we need to make sure we can properly - // encode this. - uint32_t addr_word_offset = addr % 4; -// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); + // Read the debug state + int kret = ReadDBG(false); - uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; -// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); - if (byte_mask > 0xfu) - return LLDB_INVALID_INDEX32; + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - // Read the debug state - int kret = ReadDBG (false); + for (i = 0; i < num_hw_watchpoints; ++i) { + if ((dbg.wcr[i] & WCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) + } - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i=0; i<num_hw_watchpoints; ++i) - { - if ((dbg.wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) - { - // Make the byte_mask into a valid Byte Address Select mask - uint32_t byte_address_select = byte_mask << 5; - // Make sure bits 1:0 are clear in our address - dbg.wvr[i] = addr & ~((lldb::addr_t)3); - dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; - - kret = WriteDBG(); -// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } - else - { -// if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw breakpoint slot above + if (i < num_hw_watchpoints) { + // Make the byte_mask into a valid Byte Address Select mask + uint32_t byte_address_select = byte_mask << 5; + // Make sure bits 1:0 are clear in our address + dbg.wvr[i] = addr & ~((lldb::addr_t)3); + dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA + // that we will watch + S_USER | // Stop only in user mode + (read ? WCR_LOAD : 0) | // Stop on read access? + (write ? WCR_STORE : 0) | // Stop on write access? + WCR_ENABLE; // Enable this watchpoint; + + kret = WriteDBG(); + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() + // WriteDBG() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return i; + } else { + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(): + // All hardware resources (%u) are in use.", + // num_hw_watchpoints); } - return LLDB_INVALID_INDEX32; + } + return LLDB_INVALID_INDEX32; } -bool -RegisterContextDarwin_arm64::ClearHardwareWatchpoint (uint32_t hw_index) -{ - int kret = ReadDBG (false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - dbg.wcr[hw_index] = 0; -// if (log) log->Printf ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", -// hw_index, -// hw_index, -// dbg.wvr[hw_index], -// hw_index, -// dbg.wcr[hw_index]); - - kret = WriteDBG(); - - if (kret == KERN_SUCCESS) - return true; - } +bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) { + int kret = ReadDBG(false); + + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (kret == KERN_SUCCESS) { + if (hw_index < num_hw_points) { + dbg.wcr[hw_index] = 0; + // if (log) log->Printf + // ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u ) + // - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", + // hw_index, + // hw_index, + // dbg.wvr[hw_index], + // hw_index, + // dbg.wcr[hw_index]); + + kret = WriteDBG(); + + if (kret == KERN_SUCCESS) + return true; } - return false; + } + return false; } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index b228c42ade5..2d1fe0555b5 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -1,4 +1,5 @@ -//===-- RegisterContextDarwin_arm64.h -----------------------------*- C++ -*-===// +//===-- RegisterContextDarwin_arm64.h -----------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,279 +15,222 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" // Break only in privileged or user mode -#define S_RSVD ((uint32_t)(0u << 1)) -#define S_PRIV ((uint32_t)(1u << 1)) -#define S_USER ((uint32_t)(2u << 1)) -#define S_PRIV_USER ((S_PRIV) | (S_USER)) +#define S_RSVD ((uint32_t)(0u << 1)) +#define S_PRIV ((uint32_t)(1u << 1)) +#define S_USER ((uint32_t)(2u << 1)) +#define S_PRIV_USER ((S_PRIV) | (S_USER)) -#define WCR_ENABLE ((uint32_t)(1u)) +#define WCR_ENABLE ((uint32_t)(1u)) // Watchpoint load/store -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) +#define WCR_LOAD ((uint32_t)(1u << 3)) +#define WCR_STORE ((uint32_t)(1u << 4)) -class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext -{ +class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext { public: - RegisterContextDarwin_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx); - - ~RegisterContextDarwin_arm64() override; - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue ®_value) override; - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue ®_value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - uint32_t - NumSupportedHardwareWatchpoints() override; - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; - - bool - ClearHardwareWatchpoint(uint32_t hw_index) override; - - // mirrors <mach/arm/thread_status.h> arm_thread_state64_t - struct GPR - { - uint64_t x[29]; // x0-x28 - uint64_t fp; // x29 - uint64_t lr; // x30 - uint64_t sp; // x31 - uint64_t pc; // pc - uint32_t cpsr; // cpsr - }; - - struct VReg - { - uint8_t bytes[16]; - }; - - // mirrors <mach/arm/thread_status.h> arm_neon_state64_t - struct FPU - { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; - - // mirrors <mach/arm/thread_status.h> arm_exception_state64_t - struct EXC - { - uint64_t far; // Virtual Fault Address - uint32_t esr; // Exception syndrome - uint32_t exception; // number of arm exception token - }; - - // mirrors <mach/arm/thread_status.h> arm_debug_state64_t - struct DBG - { - uint64_t bvr[16]; - uint64_t bcr[16]; - uint64_t wvr[16]; - uint64_t wcr[16]; - uint64_t mdscr_el1; - }; - - static void - LogDBGRegisters (lldb_private::Log *log, const DBG& dbg); + RegisterContextDarwin_arm64(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + ~RegisterContextDarwin_arm64() override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + uint32_t NumSupportedHardwareWatchpoints() override; + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write) override; + + bool ClearHardwareWatchpoint(uint32_t hw_index) override; + + // mirrors <mach/arm/thread_status.h> arm_thread_state64_t + struct GPR { + uint64_t x[29]; // x0-x28 + uint64_t fp; // x29 + uint64_t lr; // x30 + uint64_t sp; // x31 + uint64_t pc; // pc + uint32_t cpsr; // cpsr + }; + + struct VReg { + uint8_t bytes[16]; + }; + + // mirrors <mach/arm/thread_status.h> arm_neon_state64_t + struct FPU { + VReg v[32]; + uint32_t fpsr; + uint32_t fpcr; + }; + + // mirrors <mach/arm/thread_status.h> arm_exception_state64_t + struct EXC { + uint64_t far; // Virtual Fault Address + uint32_t esr; // Exception syndrome + uint32_t exception; // number of arm exception token + }; + + // mirrors <mach/arm/thread_status.h> arm_debug_state64_t + struct DBG { + uint64_t bvr[16]; + uint64_t bcr[16]; + uint64_t wvr[16]; + uint64_t wcr[16]; + uint64_t mdscr_el1; + }; + + static void LogDBGRegisters(lldb_private::Log *log, const DBG &dbg); protected: - enum - { - GPRRegSet = 6, // ARM_THREAD_STATE64 - FPURegSet = 17, // ARM_NEON_STATE64 - EXCRegSet = 7, // ARM_EXCEPTION_STATE64 - DBGRegSet = 15 // ARM_DEBUG_STATE64 - }; - - enum - { - GPRWordCount = sizeof(GPR)/sizeof(uint32_t), // ARM_THREAD_STATE64_COUNT - FPUWordCount = sizeof(FPU)/sizeof(uint32_t), // ARM_NEON_STATE64_COUNT - EXCWordCount = sizeof(EXC)/sizeof(uint32_t), // ARM_EXCEPTION_STATE64_COUNT - DBGWordCount = sizeof(DBG)/sizeof(uint32_t) // ARM_DEBUG_STATE64_COUNT - }; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - GPR gpr; - FPU fpu; - EXC exc; - DBG dbg; - int gpr_errs[2]; // Read/Write errors - int fpu_errs[2]; // Read/Write errors - int exc_errs[2]; // Read/Write errors - int dbg_errs[2]; // Read/Write errors - - void - InvalidateAllRegisterStates() - { - SetError (GPRRegSet, Read, -1); - SetError (FPURegSet, Read, -1); - SetError (EXCRegSet, Read, -1); + enum { + GPRRegSet = 6, // ARM_THREAD_STATE64 + FPURegSet = 17, // ARM_NEON_STATE64 + EXCRegSet = 7, // ARM_EXCEPTION_STATE64 + DBGRegSet = 15 // ARM_DEBUG_STATE64 + }; + + enum { + GPRWordCount = sizeof(GPR) / sizeof(uint32_t), // ARM_THREAD_STATE64_COUNT + FPUWordCount = sizeof(FPU) / sizeof(uint32_t), // ARM_NEON_STATE64_COUNT + EXCWordCount = + sizeof(EXC) / sizeof(uint32_t), // ARM_EXCEPTION_STATE64_COUNT + DBGWordCount = sizeof(DBG) / sizeof(uint32_t) // ARM_DEBUG_STATE64_COUNT + }; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + GPR gpr; + FPU fpu; + EXC exc; + DBG dbg; + int gpr_errs[2]; // Read/Write errors + int fpu_errs[2]; // Read/Write errors + int exc_errs[2]; // Read/Write errors + int dbg_errs[2]; // Read/Write errors + + void InvalidateAllRegisterStates() { + SetError(GPRRegSet, Read, -1); + SetError(FPURegSet, Read, -1); + SetError(EXCRegSet, Read, -1); + } + + int GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case GPRRegSet: + return gpr_errs[err_idx]; + case FPURegSet: + return fpu_errs[err_idx]; + case EXCRegSet: + return exc_errs[err_idx]; + case DBGRegSet: + return dbg_errs[err_idx]; + default: + break; + } } - - int - GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case GPRRegSet: return gpr_errs[err_idx]; - case FPURegSet: return fpu_errs[err_idx]; - case EXCRegSet: return exc_errs[err_idx]; - case DBGRegSet: return dbg_errs[err_idx]; - default: break; - } - } - return -1; + return -1; + } + + bool SetError(int flavor, uint32_t err_idx, int err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case GPRRegSet: + gpr_errs[err_idx] = err; + return true; + + case FPURegSet: + fpu_errs[err_idx] = err; + return true; + + case EXCRegSet: + exc_errs[err_idx] = err; + return true; + + case DBGRegSet: + exc_errs[err_idx] = err; + return true; + + default: + break; + } } + return false; + } - bool - SetError (int flavor, uint32_t err_idx, int err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case GPRRegSet: - gpr_errs[err_idx] = err; - return true; - - case FPURegSet: - fpu_errs[err_idx] = err; - return true; - - case EXCRegSet: - exc_errs[err_idx] = err; - return true; - - case DBGRegSet: - exc_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; - } + bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; } - bool - RegisterSetIsCached (int set) const - { - return GetError(set, Read) == 0; - } + int ReadGPR(bool force); - int - ReadGPR (bool force); + int ReadFPU(bool force); - int - ReadFPU (bool force); + int ReadEXC(bool force); - int - ReadEXC (bool force); + int ReadDBG(bool force); - int - ReadDBG (bool force); + int WriteGPR(); - int - WriteGPR (); + int WriteFPU(); - int - WriteFPU (); + int WriteEXC(); - int - WriteEXC (); + int WriteDBG(); - int - WriteDBG (); + // Subclasses override these to do the actual reading. + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { return -1; } - - // Subclasses override these to do the actual reading. - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) - { - return -1; - } - - virtual int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0; - - virtual int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0; + virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0; + + virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0; + + virtual int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) = 0; + + virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - virtual int - DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0; + virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - virtual int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - - virtual int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - - virtual int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0; + virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0; - virtual int - DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0; + virtual int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) = 0; - int - ReadRegisterSet (uint32_t set, bool force); + int ReadRegisterSet(uint32_t set, bool force); - int - WriteRegisterSet (uint32_t set); + int WriteRegisterSet(uint32_t set); - static uint32_t - GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num); + static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num); - static int - GetSetForNativeRegNum (int reg_num); + static int GetSetForNativeRegNum(int reg_num); - static size_t - GetRegisterInfosCount (); + static size_t GetRegisterInfosCount(); - static const lldb_private::RegisterInfo * - GetRegisterInfos (); + static const lldb_private::RegisterInfo *GetRegisterInfos(); }; #endif // liblldb_RegisterContextDarwin_arm64_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 94170144d1c..f42fb00b375 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -7,9 +7,8 @@ // //===----------------------------------------------------------------------===// - // C Includes -#include <stddef.h> // offsetof +#include <stddef.h> // offsetof // C++ Includes // Other libraries and framework includes @@ -34,302 +33,430 @@ using namespace lldb; using namespace lldb_private; -enum -{ - gpr_eax = 0, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, - - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - - exc_trapno, - exc_err, - exc_faultvaddr, - - k_num_registers, - - // Aliases - fpu_fctrl = fpu_fcw, - fpu_fstat = fpu_fsw, - fpu_ftag = fpu_ftw, - fpu_fiseg = fpu_cs, - fpu_fioff = fpu_ip, - fpu_foseg = fpu_ds, - fpu_fooff = fpu_dp +enum { + gpr_eax = 0, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_ss, + gpr_eflags, + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, + + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + + exc_trapno, + exc_err, + exc_faultvaddr, + + k_num_registers, + + // Aliases + fpu_fctrl = fpu_fcw, + fpu_fstat = fpu_fsw, + fpu_ftag = fpu_ftw, + fpu_fiseg = fpu_cs, + fpu_fioff = fpu_ip, + fpu_foseg = fpu_ds, + fpu_fooff = fpu_dp }; -enum -{ - ehframe_eax = 0, - ehframe_ecx, - ehframe_edx, - ehframe_ebx, - ehframe_ebp, - ehframe_esp, - ehframe_esi, - ehframe_edi, - ehframe_eip, - ehframe_eflags +enum { + ehframe_eax = 0, + ehframe_ecx, + ehframe_edx, + ehframe_ebx, + ehframe_ebp, + ehframe_esp, + ehframe_esi, + ehframe_edi, + ehframe_eip, + ehframe_eflags }; -enum -{ - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7 +enum { + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + dwarf_stmm0 = 11, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7 }; - -#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::GPR, reg)) -#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR)) -#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::EXC, reg) + sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU)) +#define GPR_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::GPR, reg)) +#define FPU_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::FPU, reg) + \ + sizeof(RegisterContextDarwin_i386::GPR)) +#define EXC_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_i386::EXC, reg) + \ + sizeof(RegisterContextDarwin_i386::GPR) + \ + sizeof(RegisterContextDarwin_i386::FPU)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, nullptr, nullptr, nullptr, 0 - -#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex -#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC)) - -static RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff eh_frame DWARF GENERIC PROCESS PLUGIN LLDB -// =============================== ======================= =================== ========================= ================== ================= - { DEFINE_GPR(eax , NULL) , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_eax }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(ebx , NULL) , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ebx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(ecx , NULL) , { ehframe_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ecx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(edx , NULL) , { ehframe_edx , dwarf_edx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(edi , NULL) , { ehframe_edi , dwarf_edi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edi }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(esi , NULL) , { ehframe_esi , dwarf_esi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_esi }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(ebp , "fp") , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_ebp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(esp , "sp") , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_esp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ss }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(eflags , "flags") , { ehframe_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, gpr_eflags }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(eip , "pc") , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_eip }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ds }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_es }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, nullptr, nullptr, nullptr, 0}, - - { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_VECT(stmm,0) }, - { DEFINE_FPU_VECT(stmm,1) }, - { DEFINE_FPU_VECT(stmm,2) }, - { DEFINE_FPU_VECT(stmm,3) }, - { DEFINE_FPU_VECT(stmm,4) }, - { DEFINE_FPU_VECT(stmm,5) }, - { DEFINE_FPU_VECT(stmm,6) }, - { DEFINE_FPU_VECT(stmm,7) }, - { DEFINE_FPU_VECT(xmm,0) }, - { DEFINE_FPU_VECT(xmm,1) }, - { DEFINE_FPU_VECT(xmm,2) }, - { DEFINE_FPU_VECT(xmm,3) }, - { DEFINE_FPU_VECT(xmm,4) }, - { DEFINE_FPU_VECT(xmm,5) }, - { DEFINE_FPU_VECT(xmm,6) }, - { DEFINE_FPU_VECT(xmm,7) }, - - { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }, nullptr, nullptr, nullptr, 0}, - { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }, nullptr, nullptr, nullptr, 0}, - { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, nullptr, nullptr, nullptr, 0} -}; +#define DEFINE_GPR(reg, alt) \ + #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_UINT(reg) \ + #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg), \ + FPU_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_VECT(reg, i) \ + #reg #i, NULL, \ + sizeof(((RegisterContextDarwin_i386::FPU *) NULL)->reg[i].bytes), \ + FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {LLDB_INVALID_REGNUM, dwarf_##reg##i, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + fpu_##reg##i }, \ + nullptr, nullptr, nullptr, 0 + +#define DEFINE_EXC(reg) \ + #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *) NULL)->reg), \ + EXC_OFFSET(reg), eEncodingUint, eFormatHex +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextDarwin_i386::GPR) + \ + sizeof(RegisterContextDarwin_i386::FPU) + \ + sizeof(RegisterContextDarwin_i386::EXC)) + +static RegisterInfo g_register_infos[] = { + // Macro auto defines most stuff eh_frame DWARF + // GENERIC PROCESS PLUGIN LLDB + // =============================== ======================= + // =================== ========================= ================== + // ================= + {DEFINE_GPR(eax, NULL), + {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_eax}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(ebx, NULL), + {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_ebx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(ecx, NULL), + {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_ecx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(edx, NULL), + {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_edx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(edi, NULL), + {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_edi}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(esi, NULL), + {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_esi}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(ebp, "fp"), + {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, + gpr_ebp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(esp, "sp"), + {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, + gpr_esp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(ss, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_ss}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(eflags, "flags"), + {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, gpr_eflags}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(eip, "pc"), + {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + gpr_eip}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(cs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_cs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(ds, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_ds}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(es, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_es}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(fs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_fs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(gs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_gs}, + nullptr, + nullptr, + nullptr, + 0}, + + {DEFINE_FPU_UINT(fcw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fcw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(fsw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fsw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ftw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ftw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(fop), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fop}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ip), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ip}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(cs), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_cs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(dp), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_dp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ds), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ds}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(mxcsr), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_mxcsr}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(mxcsrmask), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_mxcsrmask}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_VECT(stmm, 0)}, + {DEFINE_FPU_VECT(stmm, 1)}, + {DEFINE_FPU_VECT(stmm, 2)}, + {DEFINE_FPU_VECT(stmm, 3)}, + {DEFINE_FPU_VECT(stmm, 4)}, + {DEFINE_FPU_VECT(stmm, 5)}, + {DEFINE_FPU_VECT(stmm, 6)}, + {DEFINE_FPU_VECT(stmm, 7)}, + {DEFINE_FPU_VECT(xmm, 0)}, + {DEFINE_FPU_VECT(xmm, 1)}, + {DEFINE_FPU_VECT(xmm, 2)}, + {DEFINE_FPU_VECT(xmm, 3)}, + {DEFINE_FPU_VECT(xmm, 4)}, + {DEFINE_FPU_VECT(xmm, 5)}, + {DEFINE_FPU_VECT(xmm, 6)}, + {DEFINE_FPU_VECT(xmm, 7)}, + + {DEFINE_EXC(trapno), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_trapno}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_EXC(err), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_err}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_EXC(faultvaddr), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_faultvaddr}, + nullptr, + nullptr, + nullptr, + 0}}; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext(thread, concrete_frame_idx), - gpr(), - fpu(), - exc() -{ - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } -} - -RegisterContextDarwin_i386::~RegisterContextDarwin_i386() -{ +RegisterContextDarwin_i386::RegisterContextDarwin_i386( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + } } +RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {} -void -RegisterContextDarwin_i386::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); +void RegisterContextDarwin_i386::InvalidateAllRegisters() { + InvalidateAllRegisterStates(); } - -size_t -RegisterContextDarwin_i386::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; +size_t RegisterContextDarwin_i386::GetRegisterCount() { + assert(k_num_register_infos == k_num_registers); + return k_num_registers; } const RegisterInfo * -RegisterContextDarwin_i386::GetRegisterInfoAtIndex (size_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - return NULL; +RegisterContextDarwin_i386::GetRegisterInfoAtIndex(size_t reg) { + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextDarwin_i386::GetRegisterInfosCount () -{ - return k_num_register_infos; +size_t RegisterContextDarwin_i386::GetRegisterInfosCount() { + return k_num_register_infos; } -const RegisterInfo * -RegisterContextDarwin_i386::GetRegisterInfos () -{ - return g_register_infos; +const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() { + return g_register_infos; } - // General purpose registers -static uint32_t -g_gpr_regnums[] = -{ - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs -}; +static uint32_t g_gpr_regnums[] = { + gpr_eax, gpr_ebx, gpr_ecx, gpr_edx, gpr_edi, gpr_esi, gpr_ebp, gpr_esp, + gpr_ss, gpr_eflags, gpr_eip, gpr_cs, gpr_ds, gpr_es, gpr_fs, gpr_gs}; // Floating point registers -static uint32_t -g_fpu_regnums[] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7 -}; +static uint32_t g_fpu_regnums[] = { + fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs, + fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1, + fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7, + fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5, + fpu_xmm6, fpu_xmm7}; // Exception registers -static uint32_t -g_exc_regnums[] = -{ - exc_trapno, - exc_err, - exc_faultvaddr -}; +static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr}; // Number of registers in each register set const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); @@ -341,539 +468,514 @@ const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -static const RegisterSet g_reg_sets[] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }, - { "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums } -}; +static const RegisterSet g_reg_sets[] = { + { + "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, + }, + {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, + {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); - -size_t -RegisterContextDarwin_i386::GetRegisterSetCount () -{ - return k_num_regsets; +size_t RegisterContextDarwin_i386::GetRegisterSetCount() { + return k_num_regsets; } -const RegisterSet * -RegisterContextDarwin_i386::GetRegisterSet (size_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; +const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) { + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; } - //---------------------------------------------------------------------- // Register information definitions for 32 bit i386. //---------------------------------------------------------------------- -int -RegisterContextDarwin_i386::GetSetForNativeRegNum (int reg_num) -{ - if (reg_num < fpu_fcw) - return GPRRegSet; - else if (reg_num < exc_trapno) - return FPURegSet; - else if (reg_num < k_num_registers) - return EXCRegSet; - return -1; +int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) { + if (reg_num < fpu_fcw) + return GPRRegSet; + else if (reg_num < exc_trapno) + return FPURegSet; + else if (reg_num < k_num_registers) + return EXCRegSet; + return -1; } - -void -RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) -{ - if (log) - { - if (title) - log->Printf ("%s", title); - for (uint32_t i=0; i<k_num_gpr_registers; i++) - { - uint32_t reg = gpr_eax + i; - log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&gpr.eax)[reg]); - } +void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) { + if (log) { + if (title) + log->Printf("%s", title); + for (uint32_t i = 0; i < k_num_gpr_registers; i++) { + uint32_t reg = gpr_eax + i; + log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, + (&gpr.eax)[reg]); } + } } - - -int -RegisterContextDarwin_i386::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); - } - return GetError(set, Read); +int RegisterContextDarwin_i386::ReadGPR(bool force) { + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(set, Read); } -int -RegisterContextDarwin_i386::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); - } - return GetError(set, Read); +int RegisterContextDarwin_i386::ReadFPU(bool force) { + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(set, Read); } -int -RegisterContextDarwin_i386::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); - } - return GetError(set, Read); +int RegisterContextDarwin_i386::ReadEXC(bool force) { + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(set, Read); } -int -RegisterContextDarwin_i386::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr)); - SetError (set, Read, -1); - return GetError(set, Write); +int RegisterContextDarwin_i386::WriteGPR() { + int set = GPRRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return -1; + } + SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr)); + SetError(set, Read, -1); + return GetError(set, Write); } -int -RegisterContextDarwin_i386::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu)); - SetError (set, Read, -1); - return GetError(set, Write); +int RegisterContextDarwin_i386::WriteFPU() { + int set = FPURegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return -1; + } + SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu)); + SetError(set, Read, -1); + return GetError(set, Write); } -int -RegisterContextDarwin_i386::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc)); - SetError (set, Read, -1); - return GetError(set, Write); +int RegisterContextDarwin_i386::WriteEXC() { + int set = EXCRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return -1; + } + SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc)); + SetError(set, Read, -1); + return GetError(set, Write); } -int -RegisterContextDarwin_i386::ReadRegisterSet (uint32_t set, bool force) -{ - switch (set) - { - case GPRRegSet: return ReadGPR(force); - case FPURegSet: return ReadFPU(force); - case EXCRegSet: return ReadEXC(force); - default: break; - } - return -1; +int RegisterContextDarwin_i386::ReadRegisterSet(uint32_t set, bool force) { + switch (set) { + case GPRRegSet: + return ReadGPR(force); + case FPURegSet: + return ReadFPU(force); + case EXCRegSet: + return ReadEXC(force); + default: + break; + } + return -1; } -int -RegisterContextDarwin_i386::WriteRegisterSet (uint32_t set) -{ - // Make sure we have a valid context to set. - if (RegisterSetIsCached(set)) - { - switch (set) - { - case GPRRegSet: return WriteGPR(); - case FPURegSet: return WriteFPU(); - case EXCRegSet: return WriteEXC(); - default: break; - } +int RegisterContextDarwin_i386::WriteRegisterSet(uint32_t set) { + // Make sure we have a valid context to set. + if (RegisterSetIsCached(set)) { + switch (set) { + case GPRRegSet: + return WriteGPR(); + case FPURegSet: + return WriteFPU(); + case EXCRegSet: + return WriteEXC(); + default: + break; } - return -1; + } + return -1; } -bool -RegisterContextDarwin_i386::ReadRegister (const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextDarwin_i386::GetSetForNativeRegNum (reg); +bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_i386::GetSetForNativeRegNum(reg); - if (set == -1) - return false; + if (set == -1) + return false; - if (ReadRegisterSet(set, false) != 0) - return false; + if (ReadRegisterSet(set, false) != 0) + return false; - switch (reg) - { - case gpr_eax: - case gpr_ebx: - case gpr_ecx: - case gpr_edx: - case gpr_edi: - case gpr_esi: - case gpr_ebp: - case gpr_esp: - case gpr_ss: - case gpr_eflags: - case gpr_eip: - case gpr_cs: - case gpr_ds: - case gpr_es: - case gpr_fs: - case gpr_gs: - value = (&gpr.eax)[reg - gpr_eax]; - break; - - case fpu_fcw: - value = fpu.fcw; - break; - - case fpu_fsw: - value = fpu.fsw; - break; - - case fpu_ftw: - value = fpu.ftw; - break; - - case fpu_fop: - value = fpu.fop; - break; - - case fpu_ip: - value = fpu.ip; - break; - - case fpu_cs: - value = fpu.cs; - break; - - case fpu_dp: - value = fpu.dp; - break; - - case fpu_ds: - value = fpu.ds; - break; - - case fpu_mxcsr: - value = fpu.mxcsr; - break; - - case fpu_mxcsrmask: - value = fpu.mxcsrmask; - break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - // These values don't fit into scalar types, - // RegisterContext::ReadRegisterBytes() must be used for these - // registers - //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, 10); - return false; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes() - // must be used for these registers - //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, 16); - return false; - - case exc_trapno: - value = exc.trapno; - break; - - case exc_err: - value = exc.err; - break; - - case exc_faultvaddr: - value = exc.faultvaddr; - break; + switch (reg) { + case gpr_eax: + case gpr_ebx: + case gpr_ecx: + case gpr_edx: + case gpr_edi: + case gpr_esi: + case gpr_ebp: + case gpr_esp: + case gpr_ss: + case gpr_eflags: + case gpr_eip: + case gpr_cs: + case gpr_ds: + case gpr_es: + case gpr_fs: + case gpr_gs: + value = (&gpr.eax)[reg - gpr_eax]; + break; + + case fpu_fcw: + value = fpu.fcw; + break; + + case fpu_fsw: + value = fpu.fsw; + break; + + case fpu_ftw: + value = fpu.ftw; + break; + + case fpu_fop: + value = fpu.fop; + break; + + case fpu_ip: + value = fpu.ip; + break; + + case fpu_cs: + value = fpu.cs; + break; + + case fpu_dp: + value = fpu.dp; + break; + + case fpu_ds: + value = fpu.ds; + break; + + case fpu_mxcsr: + value = fpu.mxcsr; + break; + + case fpu_mxcsrmask: + value = fpu.mxcsrmask; + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + // These values don't fit into scalar types, + // RegisterContext::ReadRegisterBytes() must be used for these + // registers + //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, + //10); + return false; - default: - return false; - } - return true; -} + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + // These values don't fit into scalar types, + // RegisterContext::ReadRegisterBytes() + // must be used for these registers + //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, + //16); + return false; + case exc_trapno: + value = exc.trapno; + break; -bool -RegisterContextDarwin_i386::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = GetSetForNativeRegNum (reg); + case exc_err: + value = exc.err; + break; - if (set == -1) - return false; + case exc_faultvaddr: + value = exc.faultvaddr; + break; - if (ReadRegisterSet(set, false) != 0) - return false; + default: + return false; + } + return true; +} - switch (reg) - { - case gpr_eax: - case gpr_ebx: - case gpr_ecx: - case gpr_edx: - case gpr_edi: - case gpr_esi: - case gpr_ebp: - case gpr_esp: - case gpr_ss: - case gpr_eflags: - case gpr_eip: - case gpr_cs: - case gpr_ds: - case gpr_es: - case gpr_fs: - case gpr_gs: - (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32(); - break; - - case fpu_fcw: - fpu.fcw = value.GetAsUInt16(); - break; - - case fpu_fsw: - fpu.fsw = value.GetAsUInt16(); - break; - - case fpu_ftw: - fpu.ftw = value.GetAsUInt8(); - break; - - case fpu_fop: - fpu.fop = value.GetAsUInt16(); - break; - - case fpu_ip: - fpu.ip = value.GetAsUInt32(); - break; - - case fpu_cs: - fpu.cs = value.GetAsUInt16(); - break; - - case fpu_dp: - fpu.dp = value.GetAsUInt32(); - break; - - case fpu_ds: - fpu.ds = value.GetAsUInt16(); - break; - - case fpu_mxcsr: - fpu.mxcsr = value.GetAsUInt32(); - break; - - case fpu_mxcsrmask: - fpu.mxcsrmask = value.GetAsUInt32(); - break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes() - // must be used for these registers - ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); - return false; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes() - // must be used for these registers - ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize()); - return false; - - case exc_trapno: - exc.trapno = value.GetAsUInt32(); - break; - - case exc_err: - exc.err = value.GetAsUInt32(); - break; - - case exc_faultvaddr: - exc.faultvaddr = value.GetAsUInt32(); - break; +bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = GetSetForNativeRegNum(reg); - default: - return false; - } - return WriteRegisterSet(set) == 0; -} + if (set == -1) + return false; -bool -RegisterContextDarwin_i386::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == 0 && - ReadFPU (false) == 0 && - ReadEXC (false) == 0) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &gpr, sizeof(gpr)); - dst += sizeof(gpr); + if (ReadRegisterSet(set, false) != 0) + return false; - ::memcpy (dst, &fpu, sizeof(fpu)); - dst += sizeof(gpr); + switch (reg) { + case gpr_eax: + case gpr_ebx: + case gpr_ecx: + case gpr_edx: + case gpr_edi: + case gpr_esi: + case gpr_ebp: + case gpr_esp: + case gpr_ss: + case gpr_eflags: + case gpr_eip: + case gpr_cs: + case gpr_ds: + case gpr_es: + case gpr_fs: + case gpr_gs: + (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32(); + break; + + case fpu_fcw: + fpu.fcw = value.GetAsUInt16(); + break; + + case fpu_fsw: + fpu.fsw = value.GetAsUInt16(); + break; + + case fpu_ftw: + fpu.ftw = value.GetAsUInt8(); + break; + + case fpu_fop: + fpu.fop = value.GetAsUInt16(); + break; + + case fpu_ip: + fpu.ip = value.GetAsUInt32(); + break; + + case fpu_cs: + fpu.cs = value.GetAsUInt16(); + break; + + case fpu_dp: + fpu.dp = value.GetAsUInt32(); + break; + + case fpu_ds: + fpu.ds = value.GetAsUInt16(); + break; + + case fpu_mxcsr: + fpu.mxcsr = value.GetAsUInt32(); + break; + + case fpu_mxcsrmask: + fpu.mxcsrmask = value.GetAsUInt32(); + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + // These values don't fit into scalar types, + // RegisterContext::ReadRegisterBytes() + // must be used for these registers + ::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), + value.GetByteSize()); + return false; - ::memcpy (dst, &exc, sizeof(exc)); - return true; - } + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + // These values don't fit into scalar types, + // RegisterContext::ReadRegisterBytes() + // must be used for these registers + ::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), + value.GetByteSize()); return false; -} -bool -RegisterContextDarwin_i386::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&gpr, src, sizeof(gpr)); - src += sizeof(gpr); - - ::memcpy (&fpu, src, sizeof(fpu)); - src += sizeof(gpr); - - ::memcpy (&exc, src, sizeof(exc)); - uint32_t success_count = 0; - if (WriteGPR() == 0) - ++success_count; - if (WriteFPU() == 0) - ++success_count; - if (WriteEXC() == 0) - ++success_count; - return success_count == 3; - } + case exc_trapno: + exc.trapno = value.GetAsUInt32(); + break; + + case exc_err: + exc.err = value.GetAsUInt32(); + break; + + case exc_faultvaddr: + exc.faultvaddr = value.GetAsUInt32(); + break; + + default: return false; + } + return WriteRegisterSet(set) == 0; } +bool RegisterContextDarwin_i386::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR(false) == 0 && ReadFPU(false) == 0 && + ReadEXC(false) == 0) { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy(dst, &gpr, sizeof(gpr)); + dst += sizeof(gpr); -uint32_t -RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg) -{ - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - break; - } - } - else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) - { - switch (reg) - { - case dwarf_eax: return gpr_eax; - case dwarf_ecx: return gpr_ecx; - case dwarf_edx: return gpr_edx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esp: return gpr_esp; - case dwarf_ebp: return gpr_ebp; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_eip: return gpr_eip; - case dwarf_eflags: return gpr_eflags; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - default: - break; - } - } - else if (kind == eRegisterKindLLDB) - { - return reg; - } - return LLDB_INVALID_REGNUM; -} + ::memcpy(dst, &fpu, sizeof(fpu)); + dst += sizeof(gpr); + ::memcpy(dst, &exc, sizeof(exc)); + return true; + } + return false; +} -bool -RegisterContextDarwin_i386::HardwareSingleStep (bool enable) -{ - if (ReadGPR(false) != 0) - return false; +bool RegisterContextDarwin_i386::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy(&gpr, src, sizeof(gpr)); + src += sizeof(gpr); + + ::memcpy(&fpu, src, sizeof(fpu)); + src += sizeof(gpr); + + ::memcpy(&exc, src, sizeof(exc)); + uint32_t success_count = 0; + if (WriteGPR() == 0) + ++success_count; + if (WriteFPU() == 0) + ++success_count; + if (WriteEXC() == 0) + ++success_count; + return success_count == 3; + } + return false; +} - const uint32_t trace_bit = 0x100u; - if (enable) - { - // If the trace bit is already set, there is nothing to do - if (gpr.eflags & trace_bit) - return true; - else - gpr.eflags |= trace_bit; +uint32_t RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t reg) { + if (kind == eRegisterKindGeneric) { + switch (reg) { + case LLDB_REGNUM_GENERIC_PC: + return gpr_eip; + case LLDB_REGNUM_GENERIC_SP: + return gpr_esp; + case LLDB_REGNUM_GENERIC_FP: + return gpr_ebp; + case LLDB_REGNUM_GENERIC_FLAGS: + return gpr_eflags; + case LLDB_REGNUM_GENERIC_RA: + default: + break; } - else - { - // If the trace bit is already cleared, there is nothing to do - if (gpr.eflags & trace_bit) - gpr.eflags &= ~trace_bit; - else - return true; + } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) { + switch (reg) { + case dwarf_eax: + return gpr_eax; + case dwarf_ecx: + return gpr_ecx; + case dwarf_edx: + return gpr_edx; + case dwarf_ebx: + return gpr_ebx; + case dwarf_esp: + return gpr_esp; + case dwarf_ebp: + return gpr_ebp; + case dwarf_esi: + return gpr_esi; + case dwarf_edi: + return gpr_edi; + case dwarf_eip: + return gpr_eip; + case dwarf_eflags: + return gpr_eflags; + case dwarf_stmm0: + return fpu_stmm0; + case dwarf_stmm1: + return fpu_stmm1; + case dwarf_stmm2: + return fpu_stmm2; + case dwarf_stmm3: + return fpu_stmm3; + case dwarf_stmm4: + return fpu_stmm4; + case dwarf_stmm5: + return fpu_stmm5; + case dwarf_stmm6: + return fpu_stmm6; + case dwarf_stmm7: + return fpu_stmm7; + case dwarf_xmm0: + return fpu_xmm0; + case dwarf_xmm1: + return fpu_xmm1; + case dwarf_xmm2: + return fpu_xmm2; + case dwarf_xmm3: + return fpu_xmm3; + case dwarf_xmm4: + return fpu_xmm4; + case dwarf_xmm5: + return fpu_xmm5; + case dwarf_xmm6: + return fpu_xmm6; + case dwarf_xmm7: + return fpu_xmm7; + default: + break; } - - return WriteGPR() == 0; + } else if (kind == eRegisterKindLLDB) { + return reg; + } + return LLDB_INVALID_REGNUM; } +bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) { + if (ReadGPR(false) != 0) + return false; + const uint32_t trace_bit = 0x100u; + if (enable) { + // If the trace bit is already set, there is nothing to do + if (gpr.eflags & trace_bit) + return true; + else + gpr.eflags |= trace_bit; + } else { + // If the trace bit is already cleared, there is nothing to do + if (gpr.eflags & trace_bit) + gpr.eflags &= ~trace_bit; + else + return true; + } + return WriteGPR() == 0; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h index 9568b0332b4..aea8a290091 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h @@ -14,255 +14,200 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" -class RegisterContextDarwin_i386 : public lldb_private::RegisterContext -{ +class RegisterContextDarwin_i386 : public lldb_private::RegisterContext { public: - RegisterContextDarwin_i386(lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContextDarwin_i386() override; - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - bool - HardwareSingleStep(bool enable) override; - - struct GPR - { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; - uint32_t ss; - uint32_t eflags; - uint32_t eip; - uint32_t cs; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - }; - - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint32_t pad[2]; - uint16_t fcw; - uint16_t fsw; - uint8_t ftw; - uint8_t pad1; - uint16_t fop; - uint32_t ip; - uint16_t cs; - uint16_t pad2; - uint32_t dp; - uint16_t ds; - uint16_t pad3; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[8]; - uint8_t pad4[14*16]; - int pad5; - }; - - struct EXC - { - uint32_t trapno; - uint32_t err; - uint32_t faultvaddr; - }; + RegisterContextDarwin_i386(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + ~RegisterContextDarwin_i386() override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + bool HardwareSingleStep(bool enable) override; + + struct GPR { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ss; + uint32_t eflags; + uint32_t eip; + uint32_t cs; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + }; + + struct MMSReg { + uint8_t bytes[10]; + uint8_t pad[6]; + }; + + struct XMMReg { + uint8_t bytes[16]; + }; + + struct FPU { + uint32_t pad[2]; + uint16_t fcw; + uint16_t fsw; + uint8_t ftw; + uint8_t pad1; + uint16_t fop; + uint32_t ip; + uint16_t cs; + uint16_t pad2; + uint32_t dp; + uint16_t ds; + uint16_t pad3; + uint32_t mxcsr; + uint32_t mxcsrmask; + MMSReg stmm[8]; + XMMReg xmm[8]; + uint8_t pad4[14 * 16]; + int pad5; + }; + + struct EXC { + uint32_t trapno; + uint32_t err; + uint32_t faultvaddr; + }; protected: - enum - { - GPRRegSet = 1, - FPURegSet = 2, - EXCRegSet = 3 - }; - - enum - { - GPRWordCount = sizeof(GPR)/sizeof(uint32_t), - FPUWordCount = sizeof(FPU)/sizeof(uint32_t), - EXCWordCount = sizeof(EXC)/sizeof(uint32_t) - }; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - GPR gpr; - FPU fpu; - EXC exc; - int gpr_errs[2]; // Read/Write errors - int fpu_errs[2]; // Read/Write errors - int exc_errs[2]; // Read/Write errors - - void - InvalidateAllRegisterStates() - { - SetError (GPRRegSet, Read, -1); - SetError (FPURegSet, Read, -1); - SetError (EXCRegSet, Read, -1); + enum { GPRRegSet = 1, FPURegSet = 2, EXCRegSet = 3 }; + + enum { + GPRWordCount = sizeof(GPR) / sizeof(uint32_t), + FPUWordCount = sizeof(FPU) / sizeof(uint32_t), + EXCWordCount = sizeof(EXC) / sizeof(uint32_t) + }; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + GPR gpr; + FPU fpu; + EXC exc; + int gpr_errs[2]; // Read/Write errors + int fpu_errs[2]; // Read/Write errors + int exc_errs[2]; // Read/Write errors + + void InvalidateAllRegisterStates() { + SetError(GPRRegSet, Read, -1); + SetError(FPURegSet, Read, -1); + SetError(EXCRegSet, Read, -1); + } + + int GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case GPRRegSet: + return gpr_errs[err_idx]; + case FPURegSet: + return fpu_errs[err_idx]; + case EXCRegSet: + return exc_errs[err_idx]; + default: + break; + } } - - int - GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case GPRRegSet: return gpr_errs[err_idx]; - case FPURegSet: return fpu_errs[err_idx]; - case EXCRegSet: return exc_errs[err_idx]; - default: break; - } - } - return -1; + return -1; + } + + bool SetError(int flavor, uint32_t err_idx, int err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case GPRRegSet: + gpr_errs[err_idx] = err; + return true; + + case FPURegSet: + fpu_errs[err_idx] = err; + return true; + + case EXCRegSet: + exc_errs[err_idx] = err; + return true; + + default: + break; + } } + return false; + } - bool - SetError (int flavor, uint32_t err_idx, int err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case GPRRegSet: - gpr_errs[err_idx] = err; - return true; - - case FPURegSet: - fpu_errs[err_idx] = err; - return true; - - case EXCRegSet: - exc_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; - } + bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; } - bool - RegisterSetIsCached (int set) const - { - return GetError(set, Read) == 0; - } + void LogGPR(lldb_private::Log *log, const char *title); + + int ReadGPR(bool force); + + int ReadFPU(bool force); - void - LogGPR (lldb_private::Log *log, const char *title); + int ReadEXC(bool force); - int - ReadGPR (bool force); + int WriteGPR(); - int - ReadFPU (bool force); + int WriteFPU(); - int - ReadEXC (bool force); + int WriteEXC(); - int - WriteGPR (); + // Subclasses override these to do the actual reading. + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) = 0; - int - WriteFPU (); + virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0; - int - WriteEXC (); + virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0; - // Subclasses override these to do the actual reading. - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0; - - virtual int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0; + virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - virtual int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0; + virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - virtual int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - - virtual int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - - virtual int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0; + virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0; - int - ReadRegisterSet (uint32_t set, bool force); + int ReadRegisterSet(uint32_t set, bool force); - int - WriteRegisterSet (uint32_t set); + int WriteRegisterSet(uint32_t set); - static uint32_t - GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num); + static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num); - static int - GetSetForNativeRegNum (int reg_num); + static int GetSetForNativeRegNum(int reg_num); - static size_t - GetRegisterInfosCount (); + static size_t GetRegisterInfosCount(); - static const lldb_private::RegisterInfo * - GetRegisterInfos (); + static const lldb_private::RegisterInfo *GetRegisterInfos(); }; #endif // liblldb_RegisterContextDarwin_i386_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index b9ad8681789..7c0bafa68f9 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -7,11 +7,10 @@ // //===----------------------------------------------------------------------===// - // C Includes #include <inttypes.h> // PRIx64 #include <stdarg.h> -#include <stddef.h> // offsetof +#include <stddef.h> // offsetof // C++ Includes // Other libraries and framework includes @@ -36,340 +35,489 @@ using namespace lldb; using namespace lldb_private; -enum -{ - gpr_rax = 0, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - - exc_trapno, - exc_err, - exc_faultvaddr, - - k_num_registers, - - // Aliases - fpu_fctrl = fpu_fcw, - fpu_fstat = fpu_fsw, - fpu_ftag = fpu_ftw, - fpu_fiseg = fpu_cs, - fpu_fioff = fpu_ip, - fpu_foseg = fpu_ds, - fpu_fooff = fpu_dp +enum { + gpr_rax = 0, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15, + + exc_trapno, + exc_err, + exc_faultvaddr, + + k_num_registers, + + // Aliases + fpu_fctrl = fpu_fcw, + fpu_fstat = fpu_fsw, + fpu_ftag = fpu_ftw, + fpu_fiseg = fpu_cs, + fpu_fioff = fpu_ip, + fpu_foseg = fpu_ds, + fpu_fooff = fpu_dp }; -enum ehframe_dwarf_regnums -{ - ehframe_dwarf_gpr_rax = 0, - ehframe_dwarf_gpr_rdx, - ehframe_dwarf_gpr_rcx, - ehframe_dwarf_gpr_rbx, - ehframe_dwarf_gpr_rsi, - ehframe_dwarf_gpr_rdi, - ehframe_dwarf_gpr_rbp, - ehframe_dwarf_gpr_rsp, - ehframe_dwarf_gpr_r8, - ehframe_dwarf_gpr_r9, - ehframe_dwarf_gpr_r10, - ehframe_dwarf_gpr_r11, - ehframe_dwarf_gpr_r12, - ehframe_dwarf_gpr_r13, - ehframe_dwarf_gpr_r14, - ehframe_dwarf_gpr_r15, - ehframe_dwarf_gpr_rip, - ehframe_dwarf_fpu_xmm0, - ehframe_dwarf_fpu_xmm1, - ehframe_dwarf_fpu_xmm2, - ehframe_dwarf_fpu_xmm3, - ehframe_dwarf_fpu_xmm4, - ehframe_dwarf_fpu_xmm5, - ehframe_dwarf_fpu_xmm6, - ehframe_dwarf_fpu_xmm7, - ehframe_dwarf_fpu_xmm8, - ehframe_dwarf_fpu_xmm9, - ehframe_dwarf_fpu_xmm10, - ehframe_dwarf_fpu_xmm11, - ehframe_dwarf_fpu_xmm12, - ehframe_dwarf_fpu_xmm13, - ehframe_dwarf_fpu_xmm14, - ehframe_dwarf_fpu_xmm15, - ehframe_dwarf_fpu_stmm0, - ehframe_dwarf_fpu_stmm1, - ehframe_dwarf_fpu_stmm2, - ehframe_dwarf_fpu_stmm3, - ehframe_dwarf_fpu_stmm4, - ehframe_dwarf_fpu_stmm5, - ehframe_dwarf_fpu_stmm6, - ehframe_dwarf_fpu_stmm7 +enum ehframe_dwarf_regnums { + ehframe_dwarf_gpr_rax = 0, + ehframe_dwarf_gpr_rdx, + ehframe_dwarf_gpr_rcx, + ehframe_dwarf_gpr_rbx, + ehframe_dwarf_gpr_rsi, + ehframe_dwarf_gpr_rdi, + ehframe_dwarf_gpr_rbp, + ehframe_dwarf_gpr_rsp, + ehframe_dwarf_gpr_r8, + ehframe_dwarf_gpr_r9, + ehframe_dwarf_gpr_r10, + ehframe_dwarf_gpr_r11, + ehframe_dwarf_gpr_r12, + ehframe_dwarf_gpr_r13, + ehframe_dwarf_gpr_r14, + ehframe_dwarf_gpr_r15, + ehframe_dwarf_gpr_rip, + ehframe_dwarf_fpu_xmm0, + ehframe_dwarf_fpu_xmm1, + ehframe_dwarf_fpu_xmm2, + ehframe_dwarf_fpu_xmm3, + ehframe_dwarf_fpu_xmm4, + ehframe_dwarf_fpu_xmm5, + ehframe_dwarf_fpu_xmm6, + ehframe_dwarf_fpu_xmm7, + ehframe_dwarf_fpu_xmm8, + ehframe_dwarf_fpu_xmm9, + ehframe_dwarf_fpu_xmm10, + ehframe_dwarf_fpu_xmm11, + ehframe_dwarf_fpu_xmm12, + ehframe_dwarf_fpu_xmm13, + ehframe_dwarf_fpu_xmm14, + ehframe_dwarf_fpu_xmm15, + ehframe_dwarf_fpu_stmm0, + ehframe_dwarf_fpu_stmm1, + ehframe_dwarf_fpu_stmm2, + ehframe_dwarf_fpu_stmm3, + ehframe_dwarf_fpu_stmm4, + ehframe_dwarf_fpu_stmm5, + ehframe_dwarf_fpu_stmm6, + ehframe_dwarf_fpu_stmm7 }; -#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::GPR, reg)) -#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR)) -#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU)) +#define GPR_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::GPR, reg)) +#define FPU_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::FPU, reg) + \ + sizeof(RegisterContextDarwin_x86_64::GPR)) +#define EXC_OFFSET(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::EXC, reg) + \ + sizeof(RegisterContextDarwin_x86_64::GPR) + \ + sizeof(RegisterContextDarwin_x86_64::FPU)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { ehframe_dwarf_fpu_##reg##i, ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, nullptr, nullptr, nullptr, 0 -#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex - -#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC)) +#define DEFINE_GPR(reg, alt) \ + #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *) NULL)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_UINT(reg) \ + #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *) NULL)->reg), \ + FPU_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_VECT(reg, i) \ + #reg #i, NULL, \ + sizeof(((RegisterContextDarwin_x86_64::FPU *) NULL)->reg[i].bytes), \ + FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {ehframe_dwarf_fpu_##reg##i, \ + ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpu_##reg##i }, \ + nullptr, nullptr, nullptr, 0 +#define DEFINE_EXC(reg) \ + #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *) NULL)->reg), \ + EXC_OFFSET(reg), eEncodingUint, eFormatHex + +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextDarwin_x86_64::GPR) + \ + sizeof(RegisterContextDarwin_x86_64::FPU) + \ + sizeof(RegisterContextDarwin_x86_64::EXC)) // General purpose registers for 64 bit -static RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB -// =============================== ====================== =================== ========================== ==================== =================== - { DEFINE_GPR (rax , NULL) , { ehframe_dwarf_gpr_rax , ehframe_dwarf_gpr_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rax }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rbx , NULL) , { ehframe_dwarf_gpr_rbx , ehframe_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rbx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rcx , NULL) , { ehframe_dwarf_gpr_rcx , ehframe_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rcx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rdx , NULL) , { ehframe_dwarf_gpr_rdx , ehframe_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdx }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rdi , NULL) , { ehframe_dwarf_gpr_rdi , ehframe_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdi }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rsi , NULL) , { ehframe_dwarf_gpr_rsi , ehframe_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rsi }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rbp , "fp") , { ehframe_dwarf_gpr_rbp , ehframe_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_rbp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rsp , "sp") , { ehframe_dwarf_gpr_rsp , ehframe_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_rsp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r8 , NULL) , { ehframe_dwarf_gpr_r8 , ehframe_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r8 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r9 , NULL) , { ehframe_dwarf_gpr_r9 , ehframe_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r9 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r10 , NULL) , { ehframe_dwarf_gpr_r10 , ehframe_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r10 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r11 , NULL) , { ehframe_dwarf_gpr_r11 , ehframe_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r11 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r12 , NULL) , { ehframe_dwarf_gpr_r12 , ehframe_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r12 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r13 , NULL) , { ehframe_dwarf_gpr_r13 , ehframe_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r13 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r14 , NULL) , { ehframe_dwarf_gpr_r14 , ehframe_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r14 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (r15 , NULL) , { ehframe_dwarf_gpr_r15 , ehframe_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r15 }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rip , "pc") , { ehframe_dwarf_gpr_rip , ehframe_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_rip }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_rflags }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, nullptr, nullptr, nullptr, 0}, - - { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask }, nullptr, nullptr, nullptr, 0}, - { DEFINE_FPU_VECT(stmm,0) }, - { DEFINE_FPU_VECT(stmm,1) }, - { DEFINE_FPU_VECT(stmm,2) }, - { DEFINE_FPU_VECT(stmm,3) }, - { DEFINE_FPU_VECT(stmm,4) }, - { DEFINE_FPU_VECT(stmm,5) }, - { DEFINE_FPU_VECT(stmm,6) }, - { DEFINE_FPU_VECT(stmm,7) }, - { DEFINE_FPU_VECT(xmm,0) }, - { DEFINE_FPU_VECT(xmm,1) }, - { DEFINE_FPU_VECT(xmm,2) }, - { DEFINE_FPU_VECT(xmm,3) }, - { DEFINE_FPU_VECT(xmm,4) }, - { DEFINE_FPU_VECT(xmm,5) }, - { DEFINE_FPU_VECT(xmm,6) }, - { DEFINE_FPU_VECT(xmm,7) }, - { DEFINE_FPU_VECT(xmm,8) }, - { DEFINE_FPU_VECT(xmm,9) }, - { DEFINE_FPU_VECT(xmm,10) }, - { DEFINE_FPU_VECT(xmm,11) }, - { DEFINE_FPU_VECT(xmm,12) }, - { DEFINE_FPU_VECT(xmm,13) }, - { DEFINE_FPU_VECT(xmm,14) }, - { DEFINE_FPU_VECT(xmm,15) }, - - { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno },nullptr, nullptr, nullptr, 0}, - { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err },nullptr, nullptr, nullptr, 0}, - { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr },nullptr, nullptr, nullptr, 0} -}; +static RegisterInfo g_register_infos[] = { + // Macro auto defines most stuff EH_FRAME DWARF + // GENERIC PROCESS PLUGIN LLDB + // =============================== ====================== + // =================== ========================== ==================== + // =================== + {DEFINE_GPR(rax, NULL), + {ehframe_dwarf_gpr_rax, ehframe_dwarf_gpr_rax, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rax}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rbx, NULL), + {ehframe_dwarf_gpr_rbx, ehframe_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rbx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rcx, NULL), + {ehframe_dwarf_gpr_rcx, ehframe_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rcx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rdx, NULL), + {ehframe_dwarf_gpr_rdx, ehframe_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rdx}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rdi, NULL), + {ehframe_dwarf_gpr_rdi, ehframe_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rdi}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rsi, NULL), + {ehframe_dwarf_gpr_rsi, ehframe_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_rsi}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rbp, "fp"), + {ehframe_dwarf_gpr_rbp, ehframe_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, gpr_rbp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rsp, "sp"), + {ehframe_dwarf_gpr_rsp, ehframe_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, gpr_rsp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r8, NULL), + {ehframe_dwarf_gpr_r8, ehframe_dwarf_gpr_r8, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r8}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r9, NULL), + {ehframe_dwarf_gpr_r9, ehframe_dwarf_gpr_r9, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r9}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r10, NULL), + {ehframe_dwarf_gpr_r10, ehframe_dwarf_gpr_r10, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r10}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r11, NULL), + {ehframe_dwarf_gpr_r11, ehframe_dwarf_gpr_r11, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r11}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r12, NULL), + {ehframe_dwarf_gpr_r12, ehframe_dwarf_gpr_r12, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r12}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r13, NULL), + {ehframe_dwarf_gpr_r13, ehframe_dwarf_gpr_r13, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r13}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r14, NULL), + {ehframe_dwarf_gpr_r14, ehframe_dwarf_gpr_r14, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r14}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(r15, NULL), + {ehframe_dwarf_gpr_r15, ehframe_dwarf_gpr_r15, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_r15}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rip, "pc"), + {ehframe_dwarf_gpr_rip, ehframe_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, gpr_rip}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(rflags, "flags"), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, gpr_rflags}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(cs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_cs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(fs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_fs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_GPR(gs, NULL), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_gs}, + nullptr, + nullptr, + nullptr, + 0}, + + {DEFINE_FPU_UINT(fcw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fcw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(fsw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fsw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ftw), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ftw}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(fop), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fop}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ip), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ip}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(cs), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_cs}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(dp), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_dp}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(ds), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_ds}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(mxcsr), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_mxcsr}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_UINT(mxcsrmask), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_mxcsrmask}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_FPU_VECT(stmm, 0)}, + {DEFINE_FPU_VECT(stmm, 1)}, + {DEFINE_FPU_VECT(stmm, 2)}, + {DEFINE_FPU_VECT(stmm, 3)}, + {DEFINE_FPU_VECT(stmm, 4)}, + {DEFINE_FPU_VECT(stmm, 5)}, + {DEFINE_FPU_VECT(stmm, 6)}, + {DEFINE_FPU_VECT(stmm, 7)}, + {DEFINE_FPU_VECT(xmm, 0)}, + {DEFINE_FPU_VECT(xmm, 1)}, + {DEFINE_FPU_VECT(xmm, 2)}, + {DEFINE_FPU_VECT(xmm, 3)}, + {DEFINE_FPU_VECT(xmm, 4)}, + {DEFINE_FPU_VECT(xmm, 5)}, + {DEFINE_FPU_VECT(xmm, 6)}, + {DEFINE_FPU_VECT(xmm, 7)}, + {DEFINE_FPU_VECT(xmm, 8)}, + {DEFINE_FPU_VECT(xmm, 9)}, + {DEFINE_FPU_VECT(xmm, 10)}, + {DEFINE_FPU_VECT(xmm, 11)}, + {DEFINE_FPU_VECT(xmm, 12)}, + {DEFINE_FPU_VECT(xmm, 13)}, + {DEFINE_FPU_VECT(xmm, 14)}, + {DEFINE_FPU_VECT(xmm, 15)}, + + {DEFINE_EXC(trapno), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_trapno}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_EXC(err), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_err}, + nullptr, + nullptr, + nullptr, + 0}, + {DEFINE_EXC(faultvaddr), + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_faultvaddr}, + nullptr, + nullptr, + nullptr, + 0}}; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext (thread, concrete_frame_idx), - gpr(), - fpu(), - exc() -{ - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } -} - -RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() -{ +RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + } } +RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() {} -void -RegisterContextDarwin_x86_64::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); +void RegisterContextDarwin_x86_64::InvalidateAllRegisters() { + InvalidateAllRegisterStates(); } - -size_t -RegisterContextDarwin_x86_64::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; +size_t RegisterContextDarwin_x86_64::GetRegisterCount() { + assert(k_num_register_infos == k_num_registers); + return k_num_registers; } - const RegisterInfo * -RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (size_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - return NULL; +RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex(size_t reg) { + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos[reg]; + return NULL; } - -size_t -RegisterContextDarwin_x86_64::GetRegisterInfosCount () -{ - return k_num_register_infos; +size_t RegisterContextDarwin_x86_64::GetRegisterInfosCount() { + return k_num_register_infos; } const lldb_private::RegisterInfo * -RegisterContextDarwin_x86_64::GetRegisterInfos () -{ - return g_register_infos; +RegisterContextDarwin_x86_64::GetRegisterInfos() { + return g_register_infos; } +static uint32_t g_gpr_regnums[] = { + gpr_rax, gpr_rbx, gpr_rcx, gpr_rdx, gpr_rdi, gpr_rsi, gpr_rbp, + gpr_rsp, gpr_r8, gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_r13, + gpr_r14, gpr_r15, gpr_rip, gpr_rflags, gpr_cs, gpr_fs, gpr_gs}; +static uint32_t g_fpu_regnums[] = { + fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs, + fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1, + fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7, + fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5, + fpu_xmm6, fpu_xmm7, fpu_xmm8, fpu_xmm9, fpu_xmm10, fpu_xmm11, + fpu_xmm12, fpu_xmm13, fpu_xmm14, fpu_xmm15}; -static uint32_t g_gpr_regnums[] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs -}; - -static uint32_t g_fpu_regnums[] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -static uint32_t -g_exc_regnums[] = -{ - exc_trapno, - exc_err, - exc_faultvaddr -}; +static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr}; // Number of registers in each register set const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); @@ -381,562 +529,556 @@ const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -static const RegisterSet g_reg_sets[] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }, - { "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums } -}; +static const RegisterSet g_reg_sets[] = { + { + "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, + }, + {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, + {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); - -size_t -RegisterContextDarwin_x86_64::GetRegisterSetCount () -{ - return k_num_regsets; +size_t RegisterContextDarwin_x86_64::GetRegisterSetCount() { + return k_num_regsets; } const RegisterSet * -RegisterContextDarwin_x86_64::GetRegisterSet (size_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; -} - -int -RegisterContextDarwin_x86_64::GetSetForNativeRegNum (int reg_num) -{ - if (reg_num < fpu_fcw) - return GPRRegSet; - else if (reg_num < exc_trapno) - return FPURegSet; - else if (reg_num < k_num_registers) - return EXCRegSet; - return -1; +RegisterContextDarwin_x86_64::GetRegisterSet(size_t reg_set) { + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; } -void -RegisterContextDarwin_x86_64::LogGPR(Log *log, const char *format, ...) -{ - if (log) - { - if (format) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } - for (uint32_t i=0; i<k_num_gpr_registers; i++) - { - uint32_t reg = gpr_rax + i; - log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, (&gpr.rax)[reg]); - } - } +int RegisterContextDarwin_x86_64::GetSetForNativeRegNum(int reg_num) { + if (reg_num < fpu_fcw) + return GPRRegSet; + else if (reg_num < exc_trapno) + return FPURegSet; + else if (reg_num < k_num_registers) + return EXCRegSet; + return -1; } -int -RegisterContextDarwin_x86_64::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); +void RegisterContextDarwin_x86_64::LogGPR(Log *log, const char *format, ...) { + if (log) { + if (format) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); } - return GetError(GPRRegSet, Read); -} - -int -RegisterContextDarwin_x86_64::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + for (uint32_t i = 0; i < k_num_gpr_registers; i++) { + uint32_t reg = gpr_rax + i; + log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, + (&gpr.rax)[reg]); } - return GetError(FPURegSet, Read); + } } -int -RegisterContextDarwin_x86_64::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); - } - return GetError(EXCRegSet, Read); +int RegisterContextDarwin_x86_64::ReadGPR(bool force) { + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(GPRRegSet, Read); } -int -RegisterContextDarwin_x86_64::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr)); - SetError (set, Read, -1); - return GetError (set, Write); +int RegisterContextDarwin_x86_64::ReadFPU(bool force) { + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(FPURegSet, Read); } -int -RegisterContextDarwin_x86_64::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu)); - SetError (set, Read, -1); - return GetError (set, Write); +int RegisterContextDarwin_x86_64::ReadEXC(bool force) { + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(EXCRegSet, Read); } -int -RegisterContextDarwin_x86_64::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return -1; - } - SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc)); - SetError (set, Read, -1); - return GetError (set, Write); +int RegisterContextDarwin_x86_64::WriteGPR() { + int set = GPRRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); + return -1; + } + SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr)); + SetError(set, Read, -1); + return GetError(set, Write); } -int -RegisterContextDarwin_x86_64::ReadRegisterSet(uint32_t set, bool force) -{ - switch (set) - { - case GPRRegSet: return ReadGPR (force); - case FPURegSet: return ReadFPU (force); - case EXCRegSet: return ReadEXC (force); - default: break; - } +int RegisterContextDarwin_x86_64::WriteFPU() { + int set = FPURegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); return -1; + } + SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu)); + SetError(set, Read, -1); + return GetError(set, Write); } -int -RegisterContextDarwin_x86_64::WriteRegisterSet(uint32_t set) -{ - // Make sure we have a valid context to set. - switch (set) - { - case GPRRegSet: return WriteGPR (); - case FPURegSet: return WriteFPU (); - case EXCRegSet: return WriteEXC (); - default: break; - } +int RegisterContextDarwin_x86_64::WriteEXC() { + int set = EXCRegSet; + if (!RegisterSetIsCached(set)) { + SetError(set, Write, -1); return -1; + } + SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc)); + SetError(set, Read, -1); + return GetError(set, Write); } +int RegisterContextDarwin_x86_64::ReadRegisterSet(uint32_t set, bool force) { + switch (set) { + case GPRRegSet: + return ReadGPR(force); + case FPURegSet: + return ReadFPU(force); + case EXCRegSet: + return ReadEXC(force); + default: + break; + } + return -1; +} -bool -RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg); - if (set == -1) - return false; +int RegisterContextDarwin_x86_64::WriteRegisterSet(uint32_t set) { + // Make sure we have a valid context to set. + switch (set) { + case GPRRegSet: + return WriteGPR(); + case FPURegSet: + return WriteFPU(); + case EXCRegSet: + return WriteEXC(); + default: + break; + } + return -1; +} - if (ReadRegisterSet(set, false) != 0) - return false; +bool RegisterContextDarwin_x86_64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum(reg); + if (set == -1) + return false; - switch (reg) - { - case gpr_rax: - case gpr_rbx: - case gpr_rcx: - case gpr_rdx: - case gpr_rdi: - case gpr_rsi: - case gpr_rbp: - case gpr_rsp: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_r13: - case gpr_r14: - case gpr_r15: - case gpr_rip: - case gpr_rflags: - case gpr_cs: - case gpr_fs: - case gpr_gs: - value = (&gpr.rax)[reg - gpr_rax]; - break; - - case fpu_fcw: - value = fpu.fcw; - break; - - case fpu_fsw: - value = fpu.fsw; - break; - - case fpu_ftw: - value = fpu.ftw; - break; - - case fpu_fop: - value = fpu.fop; - break; - - case fpu_ip: - value = fpu.ip; - break; - - case fpu_cs: - value = fpu.cs; - break; - - case fpu_dp: - value = fpu.dp; - break; - - case fpu_ds: - value = fpu.ds; - break; - - case fpu_mxcsr: - value = fpu.mxcsr; - break; - - case fpu_mxcsrmask: - value = fpu.mxcsrmask; - break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder()); - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder()); - break; - - case exc_trapno: - value = exc.trapno; - break; - - case exc_err: - value = exc.err; - break; - - case exc_faultvaddr: - value = exc.faultvaddr; - break; + if (ReadRegisterSet(set, false) != 0) + return false; - default: - return false; - } - return true; + switch (reg) { + case gpr_rax: + case gpr_rbx: + case gpr_rcx: + case gpr_rdx: + case gpr_rdi: + case gpr_rsi: + case gpr_rbp: + case gpr_rsp: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_r13: + case gpr_r14: + case gpr_r15: + case gpr_rip: + case gpr_rflags: + case gpr_cs: + case gpr_fs: + case gpr_gs: + value = (&gpr.rax)[reg - gpr_rax]; + break; + + case fpu_fcw: + value = fpu.fcw; + break; + + case fpu_fsw: + value = fpu.fsw; + break; + + case fpu_ftw: + value = fpu.ftw; + break; + + case fpu_fop: + value = fpu.fop; + break; + + case fpu_ip: + value = fpu.ip; + break; + + case fpu_cs: + value = fpu.cs; + break; + + case fpu_dp: + value = fpu.dp; + break; + + case fpu_ds: + value = fpu.ds; + break; + + case fpu_mxcsr: + value = fpu.mxcsr; + break; + + case fpu_mxcsrmask: + value = fpu.mxcsrmask; + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, + endian::InlHostByteOrder()); + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, + endian::InlHostByteOrder()); + break; + + case exc_trapno: + value = exc.trapno; + break; + + case exc_err: + value = exc.err; + break; + + case exc_faultvaddr: + value = exc.faultvaddr; + break; + + default: + return false; + } + return true; } +bool RegisterContextDarwin_x86_64::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum(reg); -bool -RegisterContextDarwin_x86_64::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; + if (set == -1) + return false; - if (ReadRegisterSet(set, false) != 0) - return false; + if (ReadRegisterSet(set, false) != 0) + return false; - switch (reg) - { - case gpr_rax: - case gpr_rbx: - case gpr_rcx: - case gpr_rdx: - case gpr_rdi: - case gpr_rsi: - case gpr_rbp: - case gpr_rsp: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_r13: - case gpr_r14: - case gpr_r15: - case gpr_rip: - case gpr_rflags: - case gpr_cs: - case gpr_fs: - case gpr_gs: - (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64(); - break; - - case fpu_fcw: - fpu.fcw = value.GetAsUInt16(); - break; - - case fpu_fsw: - fpu.fsw = value.GetAsUInt16(); - break; - - case fpu_ftw: - fpu.ftw = value.GetAsUInt8(); - break; - - case fpu_fop: - fpu.fop = value.GetAsUInt16(); - break; - - case fpu_ip: - fpu.ip = value.GetAsUInt32(); - break; - - case fpu_cs: - fpu.cs = value.GetAsUInt16(); - break; - - case fpu_dp: - fpu.dp = value.GetAsUInt32(); - break; - - case fpu_ds: - fpu.ds = value.GetAsUInt16(); - break; - - case fpu_mxcsr: - fpu.mxcsr = value.GetAsUInt32(); - break; - - case fpu_mxcsrmask: - fpu.mxcsrmask = value.GetAsUInt32(); - break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize()); - return false; - - case exc_trapno: - exc.trapno = value.GetAsUInt32(); - break; - - case exc_err: - exc.err = value.GetAsUInt32(); - break; - - case exc_faultvaddr: - exc.faultvaddr = value.GetAsUInt64(); - break; + switch (reg) { + case gpr_rax: + case gpr_rbx: + case gpr_rcx: + case gpr_rdx: + case gpr_rdi: + case gpr_rsi: + case gpr_rbp: + case gpr_rsp: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_r13: + case gpr_r14: + case gpr_r15: + case gpr_rip: + case gpr_rflags: + case gpr_cs: + case gpr_fs: + case gpr_gs: + (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64(); + break; + + case fpu_fcw: + fpu.fcw = value.GetAsUInt16(); + break; + + case fpu_fsw: + fpu.fsw = value.GetAsUInt16(); + break; + + case fpu_ftw: + fpu.ftw = value.GetAsUInt8(); + break; + + case fpu_fop: + fpu.fop = value.GetAsUInt16(); + break; + + case fpu_ip: + fpu.ip = value.GetAsUInt32(); + break; + + case fpu_cs: + fpu.cs = value.GetAsUInt16(); + break; + + case fpu_dp: + fpu.dp = value.GetAsUInt32(); + break; + + case fpu_ds: + fpu.ds = value.GetAsUInt16(); + break; + + case fpu_mxcsr: + fpu.mxcsr = value.GetAsUInt32(); + break; + + case fpu_mxcsrmask: + fpu.mxcsrmask = value.GetAsUInt32(); + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + ::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), + value.GetByteSize()); + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + ::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), + value.GetByteSize()); + return false; - default: - return false; - } - return WriteRegisterSet(set) == 0; -} + case exc_trapno: + exc.trapno = value.GetAsUInt32(); + break; -bool -RegisterContextDarwin_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == 0 && - ReadFPU (false) == 0 && - ReadEXC (false) == 0) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &gpr, sizeof(gpr)); - dst += sizeof(gpr); + case exc_err: + exc.err = value.GetAsUInt32(); + break; - ::memcpy (dst, &fpu, sizeof(fpu)); - dst += sizeof(gpr); + case exc_faultvaddr: + exc.faultvaddr = value.GetAsUInt64(); + break; - ::memcpy (dst, &exc, sizeof(exc)); - return true; - } + default: return false; + } + return WriteRegisterSet(set) == 0; } -bool -RegisterContextDarwin_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&gpr, src, sizeof(gpr)); - src += sizeof(gpr); - - ::memcpy (&fpu, src, sizeof(fpu)); - src += sizeof(gpr); - - ::memcpy (&exc, src, sizeof(exc)); - uint32_t success_count = 0; - if (WriteGPR() == 0) - ++success_count; - if (WriteFPU() == 0) - ++success_count; - if (WriteEXC() == 0) - ++success_count; - return success_count == 3; - } - return false; +bool RegisterContextDarwin_x86_64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR(false) == 0 && ReadFPU(false) == 0 && + ReadEXC(false) == 0) { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy(dst, &gpr, sizeof(gpr)); + dst += sizeof(gpr); + + ::memcpy(dst, &fpu, sizeof(fpu)); + dst += sizeof(gpr); + + ::memcpy(dst, &exc, sizeof(exc)); + return true; + } + return false; } +bool RegisterContextDarwin_x86_64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy(&gpr, src, sizeof(gpr)); + src += sizeof(gpr); + + ::memcpy(&fpu, src, sizeof(fpu)); + src += sizeof(gpr); + + ::memcpy(&exc, src, sizeof(exc)); + uint32_t success_count = 0; + if (WriteGPR() == 0) + ++success_count; + if (WriteFPU() == 0) + ++success_count; + if (WriteEXC() == 0) + ++success_count; + return success_count == 3; + } + return false; +} -uint32_t -RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t reg) -{ - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - break; - } - } - else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) - { - switch (reg) - { - case ehframe_dwarf_gpr_rax: return gpr_rax; - case ehframe_dwarf_gpr_rdx: return gpr_rdx; - case ehframe_dwarf_gpr_rcx: return gpr_rcx; - case ehframe_dwarf_gpr_rbx: return gpr_rbx; - case ehframe_dwarf_gpr_rsi: return gpr_rsi; - case ehframe_dwarf_gpr_rdi: return gpr_rdi; - case ehframe_dwarf_gpr_rbp: return gpr_rbp; - case ehframe_dwarf_gpr_rsp: return gpr_rsp; - case ehframe_dwarf_gpr_r8: return gpr_r8; - case ehframe_dwarf_gpr_r9: return gpr_r9; - case ehframe_dwarf_gpr_r10: return gpr_r10; - case ehframe_dwarf_gpr_r11: return gpr_r11; - case ehframe_dwarf_gpr_r12: return gpr_r12; - case ehframe_dwarf_gpr_r13: return gpr_r13; - case ehframe_dwarf_gpr_r14: return gpr_r14; - case ehframe_dwarf_gpr_r15: return gpr_r15; - case ehframe_dwarf_gpr_rip: return gpr_rip; - case ehframe_dwarf_fpu_xmm0: return fpu_xmm0; - case ehframe_dwarf_fpu_xmm1: return fpu_xmm1; - case ehframe_dwarf_fpu_xmm2: return fpu_xmm2; - case ehframe_dwarf_fpu_xmm3: return fpu_xmm3; - case ehframe_dwarf_fpu_xmm4: return fpu_xmm4; - case ehframe_dwarf_fpu_xmm5: return fpu_xmm5; - case ehframe_dwarf_fpu_xmm6: return fpu_xmm6; - case ehframe_dwarf_fpu_xmm7: return fpu_xmm7; - case ehframe_dwarf_fpu_xmm8: return fpu_xmm8; - case ehframe_dwarf_fpu_xmm9: return fpu_xmm9; - case ehframe_dwarf_fpu_xmm10: return fpu_xmm10; - case ehframe_dwarf_fpu_xmm11: return fpu_xmm11; - case ehframe_dwarf_fpu_xmm12: return fpu_xmm12; - case ehframe_dwarf_fpu_xmm13: return fpu_xmm13; - case ehframe_dwarf_fpu_xmm14: return fpu_xmm14; - case ehframe_dwarf_fpu_xmm15: return fpu_xmm15; - case ehframe_dwarf_fpu_stmm0: return fpu_stmm0; - case ehframe_dwarf_fpu_stmm1: return fpu_stmm1; - case ehframe_dwarf_fpu_stmm2: return fpu_stmm2; - case ehframe_dwarf_fpu_stmm3: return fpu_stmm3; - case ehframe_dwarf_fpu_stmm4: return fpu_stmm4; - case ehframe_dwarf_fpu_stmm5: return fpu_stmm5; - case ehframe_dwarf_fpu_stmm6: return fpu_stmm6; - case ehframe_dwarf_fpu_stmm7: return fpu_stmm7; - default: - break; - } +uint32_t RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t reg) { + if (kind == eRegisterKindGeneric) { + switch (reg) { + case LLDB_REGNUM_GENERIC_PC: + return gpr_rip; + case LLDB_REGNUM_GENERIC_SP: + return gpr_rsp; + case LLDB_REGNUM_GENERIC_FP: + return gpr_rbp; + case LLDB_REGNUM_GENERIC_FLAGS: + return gpr_rflags; + case LLDB_REGNUM_GENERIC_RA: + default: + break; } - else if (kind == eRegisterKindLLDB) - { - return reg; + } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) { + switch (reg) { + case ehframe_dwarf_gpr_rax: + return gpr_rax; + case ehframe_dwarf_gpr_rdx: + return gpr_rdx; + case ehframe_dwarf_gpr_rcx: + return gpr_rcx; + case ehframe_dwarf_gpr_rbx: + return gpr_rbx; + case ehframe_dwarf_gpr_rsi: + return gpr_rsi; + case ehframe_dwarf_gpr_rdi: + return gpr_rdi; + case ehframe_dwarf_gpr_rbp: + return gpr_rbp; + case ehframe_dwarf_gpr_rsp: + return gpr_rsp; + case ehframe_dwarf_gpr_r8: + return gpr_r8; + case ehframe_dwarf_gpr_r9: + return gpr_r9; + case ehframe_dwarf_gpr_r10: + return gpr_r10; + case ehframe_dwarf_gpr_r11: + return gpr_r11; + case ehframe_dwarf_gpr_r12: + return gpr_r12; + case ehframe_dwarf_gpr_r13: + return gpr_r13; + case ehframe_dwarf_gpr_r14: + return gpr_r14; + case ehframe_dwarf_gpr_r15: + return gpr_r15; + case ehframe_dwarf_gpr_rip: + return gpr_rip; + case ehframe_dwarf_fpu_xmm0: + return fpu_xmm0; + case ehframe_dwarf_fpu_xmm1: + return fpu_xmm1; + case ehframe_dwarf_fpu_xmm2: + return fpu_xmm2; + case ehframe_dwarf_fpu_xmm3: + return fpu_xmm3; + case ehframe_dwarf_fpu_xmm4: + return fpu_xmm4; + case ehframe_dwarf_fpu_xmm5: + return fpu_xmm5; + case ehframe_dwarf_fpu_xmm6: + return fpu_xmm6; + case ehframe_dwarf_fpu_xmm7: + return fpu_xmm7; + case ehframe_dwarf_fpu_xmm8: + return fpu_xmm8; + case ehframe_dwarf_fpu_xmm9: + return fpu_xmm9; + case ehframe_dwarf_fpu_xmm10: + return fpu_xmm10; + case ehframe_dwarf_fpu_xmm11: + return fpu_xmm11; + case ehframe_dwarf_fpu_xmm12: + return fpu_xmm12; + case ehframe_dwarf_fpu_xmm13: + return fpu_xmm13; + case ehframe_dwarf_fpu_xmm14: + return fpu_xmm14; + case ehframe_dwarf_fpu_xmm15: + return fpu_xmm15; + case ehframe_dwarf_fpu_stmm0: + return fpu_stmm0; + case ehframe_dwarf_fpu_stmm1: + return fpu_stmm1; + case ehframe_dwarf_fpu_stmm2: + return fpu_stmm2; + case ehframe_dwarf_fpu_stmm3: + return fpu_stmm3; + case ehframe_dwarf_fpu_stmm4: + return fpu_stmm4; + case ehframe_dwarf_fpu_stmm5: + return fpu_stmm5; + case ehframe_dwarf_fpu_stmm6: + return fpu_stmm6; + case ehframe_dwarf_fpu_stmm7: + return fpu_stmm7; + default: + break; } - return LLDB_INVALID_REGNUM; + } else if (kind == eRegisterKindLLDB) { + return reg; + } + return LLDB_INVALID_REGNUM; } -bool -RegisterContextDarwin_x86_64::HardwareSingleStep (bool enable) -{ - if (ReadGPR(true) != 0) - return false; +bool RegisterContextDarwin_x86_64::HardwareSingleStep(bool enable) { + if (ReadGPR(true) != 0) + return false; - const uint64_t trace_bit = 0x100ull; - if (enable) - { + const uint64_t trace_bit = 0x100ull; + if (enable) { - if (gpr.rflags & trace_bit) - return true; // trace bit is already set, there is nothing to do - else - gpr.rflags |= trace_bit; - } + if (gpr.rflags & trace_bit) + return true; // trace bit is already set, there is nothing to do else - { - if (gpr.rflags & trace_bit) - gpr.rflags &= ~trace_bit; - else - return true; // trace bit is clear, there is nothing to do - } + gpr.rflags |= trace_bit; + } else { + if (gpr.rflags & trace_bit) + gpr.rflags &= ~trace_bit; + else + return true; // trace bit is clear, there is nothing to do + } - return WriteGPR() == 0; + return WriteGPR() == 0; } - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h index ed627e194a2..fdd5e8036de 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h @@ -14,261 +14,205 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" -class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext -{ +class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext { public: - RegisterContextDarwin_x86_64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContextDarwin_x86_64() override; - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - bool - HardwareSingleStep(bool enable) override; - - struct GPR - { - uint64_t rax; - uint64_t rbx; - uint64_t rcx; - uint64_t rdx; - uint64_t rdi; - uint64_t rsi; - uint64_t rbp; - uint64_t rsp; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t rip; - uint64_t rflags; - uint64_t cs; - uint64_t fs; - uint64_t gs; - }; - - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint32_t pad[2]; - uint16_t fcw; // "fctrl" - uint16_t fsw; // "fstat" - uint8_t ftw; // "ftag" - uint8_t pad1; - uint16_t fop; // "fop" - uint32_t ip; // "fioff" - uint16_t cs; // "fiseg" - uint16_t pad2; - uint32_t dp; // "fooff" - uint16_t ds; // "foseg" - uint16_t pad3; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[16]; - uint8_t pad4[6*16]; - int pad5; - }; - - struct EXC - { - uint32_t trapno; - uint32_t err; - uint64_t faultvaddr; - }; + RegisterContextDarwin_x86_64(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + ~RegisterContextDarwin_x86_64() override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + bool HardwareSingleStep(bool enable) override; + + struct GPR { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint64_t cs; + uint64_t fs; + uint64_t gs; + }; + + struct MMSReg { + uint8_t bytes[10]; + uint8_t pad[6]; + }; + + struct XMMReg { + uint8_t bytes[16]; + }; + + struct FPU { + uint32_t pad[2]; + uint16_t fcw; // "fctrl" + uint16_t fsw; // "fstat" + uint8_t ftw; // "ftag" + uint8_t pad1; + uint16_t fop; // "fop" + uint32_t ip; // "fioff" + uint16_t cs; // "fiseg" + uint16_t pad2; + uint32_t dp; // "fooff" + uint16_t ds; // "foseg" + uint16_t pad3; + uint32_t mxcsr; + uint32_t mxcsrmask; + MMSReg stmm[8]; + XMMReg xmm[16]; + uint8_t pad4[6 * 16]; + int pad5; + }; + + struct EXC { + uint32_t trapno; + uint32_t err; + uint64_t faultvaddr; + }; protected: - - enum - { - GPRRegSet = 4, - FPURegSet = 5, - EXCRegSet = 6 - }; - - enum - { - GPRWordCount = sizeof(GPR)/sizeof(uint32_t), - FPUWordCount = sizeof(FPU)/sizeof(uint32_t), - EXCWordCount = sizeof(EXC)/sizeof(uint32_t) - }; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - GPR gpr; - FPU fpu; - EXC exc; - int gpr_errs[2]; // Read/Write errors - int fpu_errs[2]; // Read/Write errors - int exc_errs[2]; // Read/Write errors - - void - InvalidateAllRegisterStates() - { - SetError (GPRRegSet, Read, -1); - SetError (FPURegSet, Read, -1); - SetError (EXCRegSet, Read, -1); + enum { GPRRegSet = 4, FPURegSet = 5, EXCRegSet = 6 }; + + enum { + GPRWordCount = sizeof(GPR) / sizeof(uint32_t), + FPUWordCount = sizeof(FPU) / sizeof(uint32_t), + EXCWordCount = sizeof(EXC) / sizeof(uint32_t) + }; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + GPR gpr; + FPU fpu; + EXC exc; + int gpr_errs[2]; // Read/Write errors + int fpu_errs[2]; // Read/Write errors + int exc_errs[2]; // Read/Write errors + + void InvalidateAllRegisterStates() { + SetError(GPRRegSet, Read, -1); + SetError(FPURegSet, Read, -1); + SetError(EXCRegSet, Read, -1); + } + + int GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case GPRRegSet: + return gpr_errs[err_idx]; + case FPURegSet: + return fpu_errs[err_idx]; + case EXCRegSet: + return exc_errs[err_idx]; + default: + break; + } } - - int - GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case GPRRegSet: return gpr_errs[err_idx]; - case FPURegSet: return fpu_errs[err_idx]; - case EXCRegSet: return exc_errs[err_idx]; - default: break; - } - } - return -1; + return -1; + } + + bool SetError(int flavor, uint32_t err_idx, int err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case GPRRegSet: + gpr_errs[err_idx] = err; + return true; + + case FPURegSet: + fpu_errs[err_idx] = err; + return true; + + case EXCRegSet: + exc_errs[err_idx] = err; + return true; + + default: + break; + } } + return false; + } - bool - SetError (int flavor, uint32_t err_idx, int err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case GPRRegSet: - gpr_errs[err_idx] = err; - return true; - - case FPURegSet: - fpu_errs[err_idx] = err; - return true; - - case EXCRegSet: - exc_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; - } + bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; } - bool - RegisterSetIsCached (int set) const - { - return GetError(set, Read) == 0; - } + void LogGPR(lldb_private::Log *log, const char *format, ...); + + int ReadGPR(bool force); + + int ReadFPU(bool force); + + int ReadEXC(bool force); + + int WriteGPR(); + + int WriteFPU(); + + int WriteEXC(); + + // Subclasses override these to do the actual reading. + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) = 0; + + virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0; + + virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0; + + virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0; + + virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0; + + virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0; + + int ReadRegisterSet(uint32_t set, bool force); + + int WriteRegisterSet(uint32_t set); + + static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num); + + static int GetSetForNativeRegNum(int reg_num); + + static size_t GetRegisterInfosCount(); - void - LogGPR (lldb_private::Log *log, const char *format, ...); - - int - ReadGPR (bool force); - - int - ReadFPU (bool force); - - int - ReadEXC (bool force); - - int - WriteGPR (); - - int - WriteFPU (); - - int - WriteEXC (); - - // Subclasses override these to do the actual reading. - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0; - - virtual int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0; - - virtual int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0; - - virtual int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0; - - virtual int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0; - - virtual int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0; - - int - ReadRegisterSet (uint32_t set, bool force); - - int - WriteRegisterSet (uint32_t set); - - static uint32_t - GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num); - - static int - GetSetForNativeRegNum (int reg_num); - - static size_t - GetRegisterInfosCount (); - - static const lldb_private::RegisterInfo * - GetRegisterInfos (); + static const lldb_private::RegisterInfo *GetRegisterInfos(); }; #endif // liblldb_RegisterContextDarwin_x86_64_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp index 0859e4e9419..93bb09b810a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextDummy.cpp ---------------------------------*- C++ -*-===// +//===-- RegisterContextDummy.cpp ---------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +8,6 @@ // //===----------------------------------------------------------------------===// - -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/DataBufferHeap.h" @@ -20,118 +19,103 @@ #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/DynamicLoader.h" +#include "lldb/lldb-private.h" #include "RegisterContextDummy.h" using namespace lldb; using namespace lldb_private; -RegisterContextDummy::RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size) : -RegisterContext (thread, concrete_frame_idx) -{ - m_reg_set0.name = "General Purpose Registers"; - m_reg_set0.short_name = "GPR"; - m_reg_set0.num_registers = 1; - m_reg_set0.registers = new uint32_t(0); - - m_pc_reg_info.name = "pc"; - m_pc_reg_info.alt_name = "pc"; - m_pc_reg_info.byte_offset = 0; - m_pc_reg_info.byte_size = address_byte_size; - m_pc_reg_info.encoding = eEncodingUint; - m_pc_reg_info.format = eFormatPointer; - m_pc_reg_info.invalidate_regs = NULL; - m_pc_reg_info.value_regs = NULL; - m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM; +RegisterContextDummy::RegisterContextDummy(Thread &thread, + uint32_t concrete_frame_idx, + uint32_t address_byte_size) + : RegisterContext(thread, concrete_frame_idx) { + m_reg_set0.name = "General Purpose Registers"; + m_reg_set0.short_name = "GPR"; + m_reg_set0.num_registers = 1; + m_reg_set0.registers = new uint32_t(0); + + m_pc_reg_info.name = "pc"; + m_pc_reg_info.alt_name = "pc"; + m_pc_reg_info.byte_offset = 0; + m_pc_reg_info.byte_size = address_byte_size; + m_pc_reg_info.encoding = eEncodingUint; + m_pc_reg_info.format = eFormatPointer; + m_pc_reg_info.invalidate_regs = NULL; + m_pc_reg_info.value_regs = NULL; + m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM; } -RegisterContextDummy::~RegisterContextDummy () -{ - delete m_reg_set0.registers; - delete m_pc_reg_info.invalidate_regs; - delete m_pc_reg_info.value_regs; +RegisterContextDummy::~RegisterContextDummy() { + delete m_reg_set0.registers; + delete m_pc_reg_info.invalidate_regs; + delete m_pc_reg_info.value_regs; } -void -RegisterContextDummy::InvalidateAllRegisters () {} +void RegisterContextDummy::InvalidateAllRegisters() {} -size_t -RegisterContextDummy::GetRegisterCount () -{ - return 1; -} +size_t RegisterContextDummy::GetRegisterCount() { return 1; } const lldb_private::RegisterInfo * -RegisterContextDummy::GetRegisterInfoAtIndex (size_t reg) -{ - if (reg) - return NULL; - return &m_pc_reg_info; +RegisterContextDummy::GetRegisterInfoAtIndex(size_t reg) { + if (reg) + return NULL; + return &m_pc_reg_info; } -size_t -RegisterContextDummy::GetRegisterSetCount () -{ - return 1; -} +size_t RegisterContextDummy::GetRegisterSetCount() { return 1; } const lldb_private::RegisterSet * -RegisterContextDummy::GetRegisterSet (size_t reg_set) -{ - if (reg_set) - return NULL; - return &m_reg_set0; +RegisterContextDummy::GetRegisterSet(size_t reg_set) { + if (reg_set) + return NULL; + return &m_reg_set0; } -bool -RegisterContextDummy::ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) -{ - if (!reg_info) - return false; - uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric]; - if (reg_number == LLDB_REGNUM_GENERIC_PC) - { - value.SetUInt(LLDB_INVALID_ADDRESS, reg_info->byte_size); - return true; - } +bool RegisterContextDummy::ReadRegister( + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) { + if (!reg_info) return false; + uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric]; + if (reg_number == LLDB_REGNUM_GENERIC_PC) { + value.SetUInt(LLDB_INVALID_ADDRESS, reg_info->byte_size); + return true; + } + return false; } -bool -RegisterContextDummy::WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) -{ - return false; +bool RegisterContextDummy::WriteRegister( + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) { + return false; } -bool -RegisterContextDummy::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextDummy::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextDummy::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextDummy::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -uint32_t -RegisterContextDummy::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC) - return 0; - return LLDB_INVALID_REGNUM; +uint32_t RegisterContextDummy::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC) + return 0; + return LLDB_INVALID_REGNUM; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h index 9f6a8dc347b..ea70288f3d6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h @@ -1,4 +1,5 @@ -//===-- RegisterContextDummy.h ----------------------------------------*- C++ -*-===// +//===-- RegisterContextDummy.h ----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,62 +17,53 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" namespace lldb_private { - -class RegisterContextDummy : public lldb_private::RegisterContext -{ + +class RegisterContextDummy : public lldb_private::RegisterContext { public: - typedef std::shared_ptr<RegisterContextDummy> SharedPtr; - - RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size); - - ~RegisterContextDummy() override; + typedef std::shared_ptr<RegisterContextDummy> SharedPtr; - void - InvalidateAllRegisters() override; + RegisterContextDummy(Thread &thread, uint32_t concrete_frame_idx, + uint32_t address_byte_size); - size_t - GetRegisterCount() override; + ~RegisterContextDummy() override; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + void InvalidateAllRegisters() override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t reg_set) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + size_t GetRegisterSetCount() override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - private: - //------------------------------------------------------------------ - // For RegisterContextLLDB only - //------------------------------------------------------------------ - - lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only) - lldb_private::RegisterInfo m_pc_reg_info; - - DISALLOW_COPY_AND_ASSIGN (RegisterContextDummy); + //------------------------------------------------------------------ + // For RegisterContextLLDB only + //------------------------------------------------------------------ + + lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only) + lldb_private::RegisterInfo m_pc_reg_info; + + DISALLOW_COPY_AND_ASSIGN(RegisterContextDummy); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp index 588793d5a64..fecfae0b7e6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp @@ -7,12 +7,12 @@ // //===---------------------------------------------------------------------===// +#include <cassert> #include <stddef.h> #include <vector> -#include <cassert> -#include "llvm/Support/Compiler.h" #include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" #include "RegisterContextFreeBSD_arm.h" @@ -21,14 +21,31 @@ using namespace lldb_private; // Based on RegisterContextLinux_arm.cpp and // http://svnweb.freebsd.org/base/head/sys/arm/include/reg.h -#define GPR_OFFSET(idx) ((idx) * 4) -#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR)) -#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::FPU, fpscr) + sizeof (RegisterContextFreeBSD_arm::GPR)) -#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU)) -#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::DBG, reg) + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU) + sizeof (RegisterContextFreeBSD_arm::EXC))) +#define GPR_OFFSET(idx) ((idx)*4) +#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextFreeBSD_arm::GPR)) +#define FPSCR_OFFSET \ + (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm::FPU, fpscr) + \ + sizeof(RegisterContextFreeBSD_arm::GPR)) +#define EXC_OFFSET(idx) \ + ((idx)*4 + sizeof(RegisterContextFreeBSD_arm::GPR) + \ + sizeof(RegisterContextFreeBSD_arm::FPU)) +#define DBG_OFFSET(reg) \ + ((LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm::DBG, reg) + \ + sizeof(RegisterContextFreeBSD_arm::GPR) + \ + sizeof(RegisterContextFreeBSD_arm::FPU) + \ + sizeof(RegisterContextFreeBSD_arm::EXC))) -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextFreeBSD_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU) + sizeof (RegisterContextFreeBSD_arm::EXC)) +#define DEFINE_DBG(reg, i) \ + #reg, NULL, sizeof(((RegisterContextFreeBSD_arm::DBG *) NULL)->reg[i]), \ + DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + dbg_##reg##i }, \ + NULL, NULL, NULL, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextFreeBSD_arm::GPR) + \ + sizeof(RegisterContextFreeBSD_arm::FPU) + \ + sizeof(RegisterContextFreeBSD_arm::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm to declare our g_register_infos_arm structure. @@ -38,52 +55,43 @@ using namespace lldb_private; #undef DECLARE_REGISTER_INFOS_ARM_STRUCT static const lldb_private::RegisterInfo * -GetRegisterInfoPtr (const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - return g_register_infos_arm; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + return g_register_infos_arm; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - return static_cast<uint32_t>(sizeof(g_register_infos_arm) / sizeof(g_register_infos_arm[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + return static_cast<uint32_t>(sizeof(g_register_infos_arm) / + sizeof(g_register_infos_arm[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextFreeBSD_arm::RegisterContextFreeBSD_arm(const lldb_private::ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) -{ -} +RegisterContextFreeBSD_arm::RegisterContextFreeBSD_arm( + const lldb_private::ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} -size_t -RegisterContextFreeBSD_arm::GetGPRSize() const -{ - return sizeof(struct RegisterContextFreeBSD_arm::GPR); +size_t RegisterContextFreeBSD_arm::GetGPRSize() const { + return sizeof(struct RegisterContextFreeBSD_arm::GPR); } const lldb_private::RegisterInfo * -RegisterContextFreeBSD_arm::GetRegisterInfo() const -{ - return m_register_info_p; +RegisterContextFreeBSD_arm::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextFreeBSD_arm::GetRegisterCount() const -{ - return m_register_info_count; +uint32_t RegisterContextFreeBSD_arm::GetRegisterCount() const { + return m_register_info_count; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h index f2d9364b3ce..422ecb7686d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h @@ -10,65 +10,53 @@ #ifndef liblldb_RegisterContextFreeBSD_arm_h_ #define liblldb_RegisterContextFreeBSD_arm_h_ -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" -class RegisterContextFreeBSD_arm - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_arm : public lldb_private::RegisterInfoInterface { public: - - struct GPR - { - uint32_t r[16]; // R0-R15 - uint32_t cpsr; // CPSR - }; - - - struct QReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; - struct EXC - { - uint32_t exception; - uint32_t fsr; /* Fault status */ - uint32_t far; /* Virtual Fault Address */ - }; - - struct DBG - { - uint32_t bvr[16]; - uint32_t bcr[16]; - uint32_t wvr[16]; - uint32_t wcr[16]; - }; - - RegisterContextFreeBSD_arm(const lldb_private::ArchSpec &target_arch); - - size_t - GetGPRSize() const override; - - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; - - uint32_t - GetRegisterCount () const override; + struct GPR { + uint32_t r[16]; // R0-R15 + uint32_t cpsr; // CPSR + }; + + struct QReg { + uint8_t bytes[16]; + }; + + struct FPU { + union { + uint32_t s[32]; + uint64_t d[32]; + QReg q[16]; // the 128-bit NEON registers + } floats; + uint32_t fpscr; + }; + struct EXC { + uint32_t exception; + uint32_t fsr; /* Fault status */ + uint32_t far; /* Virtual Fault Address */ + }; + + struct DBG { + uint32_t bvr[16]; + uint32_t bcr[16]; + uint32_t wvr[16]; + uint32_t wcr[16]; + }; + + RegisterContextFreeBSD_arm(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; }; -#endif // liblldb_RegisterContextFreeBSD_arm_h_ +#endif // liblldb_RegisterContextFreeBSD_arm_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp index 6e7e9e67f52..123f7d93d93 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp @@ -7,24 +7,43 @@ // //===---------------------------------------------------------------------===// -#include <vector> -#include "RegisterContextPOSIX_arm64.h" #include "RegisterContextFreeBSD_arm64.h" +#include "RegisterContextPOSIX_arm64.h" +#include <vector> using namespace lldb; // Based on RegisterContextDarwin_arm64.cpp -#define GPR_OFFSET(idx) ((idx) * 8) -#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm64::GPR, reg)) +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm64::GPR, reg)) -#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextFreeBSD_arm64::GPR)) -#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm64::FPU, reg)) +#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextFreeBSD_arm64::GPR)) +#define FPU_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm64::FPU, reg)) -#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm64::EXC, reg) + sizeof (RegisterContextFreeBSD_arm64::GPR) + sizeof (RegisterContextFreeBSD_arm64::FPU)) -#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm64::DBG, reg) + sizeof (RegisterContextFreeBSD_arm64::GPR) + sizeof (RegisterContextFreeBSD_arm64::FPU) + sizeof (RegisterContextFreeBSD_arm64::EXC)) +#define EXC_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm64::EXC, reg) + \ + sizeof(RegisterContextFreeBSD_arm64::GPR) + \ + sizeof(RegisterContextFreeBSD_arm64::FPU)) +#define DBG_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm64::DBG, reg) + \ + sizeof(RegisterContextFreeBSD_arm64::GPR) + \ + sizeof(RegisterContextFreeBSD_arm64::FPU) + \ + sizeof(RegisterContextFreeBSD_arm64::EXC)) -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextFreeBSD_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextFreeBSD_arm64::GPR) + sizeof (RegisterContextFreeBSD_arm64::FPU) + sizeof (RegisterContextFreeBSD_arm64::EXC)) +#define DEFINE_DBG(reg, i) \ + #reg, NULL, \ + sizeof(((RegisterContextFreeBSD_arm64::DBG *) NULL)->reg[i]), \ + DBG_OFFSET_NAME(reg[i]), lldb::eEncodingUint, lldb::eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + dbg_##reg##i }, \ + NULL, NULL, NULL, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextFreeBSD_arm64::GPR) + \ + sizeof(RegisterContextFreeBSD_arm64::FPU) + \ + sizeof(RegisterContextFreeBSD_arm64::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure. @@ -34,53 +53,43 @@ using namespace lldb; #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT static const lldb_private::RegisterInfo * -GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - return g_register_infos_arm64; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + return g_register_infos_arm64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - return static_cast<uint32_t>(sizeof(g_register_infos_arm64) / sizeof(g_register_infos_arm64[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + return static_cast<uint32_t>(sizeof(g_register_infos_arm64) / + sizeof(g_register_infos_arm64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextFreeBSD_arm64::RegisterContextFreeBSD_arm64(const lldb_private::ArchSpec &target_arch) : - RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) -{ -} +RegisterContextFreeBSD_arm64::RegisterContextFreeBSD_arm64( + const lldb_private::ArchSpec &target_arch) + : RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} -size_t -RegisterContextFreeBSD_arm64::GetGPRSize() const -{ - return sizeof(struct RegisterContextFreeBSD_arm64::GPR); +size_t RegisterContextFreeBSD_arm64::GetGPRSize() const { + return sizeof(struct RegisterContextFreeBSD_arm64::GPR); } const lldb_private::RegisterInfo * -RegisterContextFreeBSD_arm64::GetRegisterInfo() const -{ - return m_register_info_p; +RegisterContextFreeBSD_arm64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextFreeBSD_arm64::GetRegisterCount() const -{ - return m_register_info_count; +uint32_t RegisterContextFreeBSD_arm64::GetRegisterCount() const { + return m_register_info_count; } - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h index cfdae4d2b55..bf778071507 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h @@ -12,67 +12,58 @@ #include "RegisterInfoInterface.h" -class RegisterContextFreeBSD_arm64: - public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_arm64 + : public lldb_private::RegisterInfoInterface { public: - // based on RegisterContextDarwin_arm64.h - struct GPR - { - uint64_t x[29]; // x0-x28 - uint64_t fp; // x29 - uint64_t lr; // x30 - uint64_t sp; // x31 - uint64_t pc; // pc - uint32_t cpsr; // cpsr - }; + // based on RegisterContextDarwin_arm64.h + struct GPR { + uint64_t x[29]; // x0-x28 + uint64_t fp; // x29 + uint64_t lr; // x30 + uint64_t sp; // x31 + uint64_t pc; // pc + uint32_t cpsr; // cpsr + }; - // based on RegisterContextDarwin_arm64.h - struct VReg - { - uint8_t bytes[16]; - }; + // based on RegisterContextDarwin_arm64.h + struct VReg { + uint8_t bytes[16]; + }; - // based on RegisterContextDarwin_arm64.h - struct FPU - { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; + // based on RegisterContextDarwin_arm64.h + struct FPU { + VReg v[32]; + uint32_t fpsr; + uint32_t fpcr; + }; - // based on RegisterContextDarwin_arm64.h - struct EXC - { - uint64_t far; // Virtual Fault Address - uint32_t esr; // Exception syndrome - uint32_t exception; // number of arm exception token - }; + // based on RegisterContextDarwin_arm64.h + struct EXC { + uint64_t far; // Virtual Fault Address + uint32_t esr; // Exception syndrome + uint32_t exception; // number of arm exception token + }; - // based on RegisterContextDarwin_arm64.h - struct DBG - { - uint64_t bvr[16]; - uint64_t bcr[16]; - uint64_t wvr[16]; - uint64_t wcr[16]; - uint64_t mdscr_el1; - }; + // based on RegisterContextDarwin_arm64.h + struct DBG { + uint64_t bvr[16]; + uint64_t bcr[16]; + uint64_t wvr[16]; + uint64_t wcr[16]; + uint64_t mdscr_el1; + }; - RegisterContextFreeBSD_arm64(const lldb_private::ArchSpec &target_arch); + RegisterContextFreeBSD_arm64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp index 0171da66a19..4ccfa2a16fe 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp @@ -7,55 +7,52 @@ // //===---------------------------------------------------------------------===// -#include "RegisterContextPOSIX_x86.h" #include "RegisterContextFreeBSD_i386.h" +#include "RegisterContextPOSIX_x86.h" using namespace lldb_private; using namespace lldb; // http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h -struct GPR -{ - uint32_t fs; - uint32_t es; - uint32_t ds; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t isp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t trapno; - uint32_t err; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; - uint32_t gs; +struct GPR { + uint32_t fs; + uint32_t es; + uint32_t ds; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t isp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t trapno; + uint32_t err; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; + uint32_t gs; }; struct dbreg { - uint32_t dr[8]; /* debug registers */ - /* Index 0-3: debug address registers */ - /* Index 4-5: reserved */ - /* Index 6: debug status */ - /* Index 7: debug control */ + uint32_t dr[8]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ }; using FPR_i386 = FXSAVE; -struct UserArea -{ - GPR gpr; - FPR_i386 i387; +struct UserArea { + GPR gpr; + FPR_i386 i387; }; #define DR_SIZE sizeof(uint32_t) -#define DR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) +#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) //--------------------------------------------------------------------------- // Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. @@ -64,32 +61,23 @@ struct UserArea #include "RegisterInfos_i386.h" #undef DECLARE_REGISTER_INFOS_I386_STRUCT -RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_arch) : - RegisterInfoInterface(target_arch) -{ -} +RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} -size_t -RegisterContextFreeBSD_i386::GetGPRSize() const -{ - return sizeof(GPR); -} +size_t RegisterContextFreeBSD_i386::GetGPRSize() const { return sizeof(GPR); } -const RegisterInfo * -RegisterContextFreeBSD_i386::GetRegisterInfo() const -{ - switch (m_target_arch.GetMachine()) - { - case llvm::Triple::x86: - return g_register_infos_i386; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +const RegisterInfo *RegisterContextFreeBSD_i386::GetRegisterInfo() const { + switch (m_target_arch.GetMachine()) { + case llvm::Triple::x86: + return g_register_infos_i386; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } -uint32_t -RegisterContextFreeBSD_i386::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0])); +uint32_t RegisterContextFreeBSD_i386::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_i386) / + sizeof(g_register_infos_i386[0])); } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h index 9527fc03f72..35a79c14abf 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h @@ -12,20 +12,15 @@ #include "RegisterInfoInterface.h" -class RegisterContextFreeBSD_i386 - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_i386 : public lldb_private::RegisterInfoInterface { public: - RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch); + RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp index 53fa4169bff..c114cfb829f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp @@ -7,87 +7,79 @@ // //===---------------------------------------------------------------------===// -#include <vector> -#include "RegisterContextPOSIX_mips64.h" #include "RegisterContextFreeBSD_mips64.h" +#include "RegisterContextPOSIX_mips64.h" +#include <vector> using namespace lldb_private; using namespace lldb; // http://svnweb.freebsd.org/base/head/sys/mips/include/regnum.h -typedef struct _GPR -{ - uint64_t zero; - uint64_t r1; - uint64_t r2; - uint64_t r3; - uint64_t r4; - uint64_t r5; - uint64_t r6; - uint64_t r7; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t r16; - uint64_t r17; - uint64_t r18; - uint64_t r19; - uint64_t r20; - uint64_t r21; - uint64_t r22; - uint64_t r23; - uint64_t r24; - uint64_t r25; - uint64_t r26; - uint64_t r27; - uint64_t gp; - uint64_t sp; - uint64_t r30; - uint64_t ra; - uint64_t sr; - uint64_t mullo; - uint64_t mulhi; - uint64_t badvaddr; - uint64_t cause; - uint64_t pc; - uint64_t ic; - uint64_t dummy; +typedef struct _GPR { + uint64_t zero; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t gp; + uint64_t sp; + uint64_t r30; + uint64_t ra; + uint64_t sr; + uint64_t mullo; + uint64_t mulhi; + uint64_t badvaddr; + uint64_t cause; + uint64_t pc; + uint64_t ic; + uint64_t dummy; } GPR_freebsd_mips; //--------------------------------------------------------------------------- -// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 structure. +// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 +// structure. //--------------------------------------------------------------------------- #define DECLARE_REGISTER_INFOS_MIPS64_STRUCT #include "RegisterInfos_mips64.h" #undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT -RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &target_arch) : - RegisterInfoInterface(target_arch) -{ -} +RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} -size_t -RegisterContextFreeBSD_mips64::GetGPRSize() const -{ - return sizeof(GPR_freebsd_mips); +size_t RegisterContextFreeBSD_mips64::GetGPRSize() const { + return sizeof(GPR_freebsd_mips); } -const RegisterInfo * -RegisterContextFreeBSD_mips64::GetRegisterInfo() const -{ - assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64); - return g_register_infos_mips64; +const RegisterInfo *RegisterContextFreeBSD_mips64::GetRegisterInfo() const { + assert(m_target_arch.GetCore() == ArchSpec::eCore_mips64); + return g_register_infos_mips64; } -uint32_t -RegisterContextFreeBSD_mips64::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_mips64) / sizeof (g_register_infos_mips64 [0])); +uint32_t RegisterContextFreeBSD_mips64::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_mips64) / + sizeof(g_register_infos_mips64[0])); } - - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h index 5c042af20ea..043e638758d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h @@ -12,20 +12,16 @@ #include "RegisterInfoInterface.h" -class RegisterContextFreeBSD_mips64: - public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_mips64 + : public lldb_private::RegisterInfoInterface { public: - RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch); + RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 5133d6088bd..efa4cc6d818 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -7,263 +7,233 @@ // //===---------------------------------------------------------------------===// -#include <vector> -#include "RegisterContextPOSIX_powerpc.h" #include "RegisterContextFreeBSD_powerpc.h" +#include "RegisterContextPOSIX_powerpc.h" +#include <vector> using namespace lldb_private; using namespace lldb; // http://svnweb.freebsd.org/base/head/sys/powerpc/include/reg.h -typedef struct _GPR64 -{ - uint64_t r0; - uint64_t r1; - uint64_t r2; - uint64_t r3; - uint64_t r4; - uint64_t r5; - uint64_t r6; - uint64_t r7; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t r16; - uint64_t r17; - uint64_t r18; - uint64_t r19; - uint64_t r20; - uint64_t r21; - uint64_t r22; - uint64_t r23; - uint64_t r24; - uint64_t r25; - uint64_t r26; - uint64_t r27; - uint64_t r28; - uint64_t r29; - uint64_t r30; - uint64_t r31; - uint64_t lr; - uint64_t cr; - uint64_t xer; - uint64_t ctr; - uint64_t pc; +typedef struct _GPR64 { + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t r28; + uint64_t r29; + uint64_t r30; + uint64_t r31; + uint64_t lr; + uint64_t cr; + uint64_t xer; + uint64_t ctr; + uint64_t pc; } GPR64; -typedef struct _GPR32 -{ - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t r12; - uint32_t r13; - uint32_t r14; - uint32_t r15; - uint32_t r16; - uint32_t r17; - uint32_t r18; - uint32_t r19; - uint32_t r20; - uint32_t r21; - uint32_t r22; - uint32_t r23; - uint32_t r24; - uint32_t r25; - uint32_t r26; - uint32_t r27; - uint32_t r28; - uint32_t r29; - uint32_t r30; - uint32_t r31; - uint32_t lr; - uint32_t cr; - uint32_t xer; - uint32_t ctr; - uint32_t pc; +typedef struct _GPR32 { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13; + uint32_t r14; + uint32_t r15; + uint32_t r16; + uint32_t r17; + uint32_t r18; + uint32_t r19; + uint32_t r20; + uint32_t r21; + uint32_t r22; + uint32_t r23; + uint32_t r24; + uint32_t r25; + uint32_t r26; + uint32_t r27; + uint32_t r28; + uint32_t r29; + uint32_t r30; + uint32_t r31; + uint32_t lr; + uint32_t cr; + uint32_t xer; + uint32_t ctr; + uint32_t pc; } GPR32; -typedef struct _FPR -{ - uint64_t f0; - uint64_t f1; - uint64_t f2; - uint64_t f3; - uint64_t f4; - uint64_t f5; - uint64_t f6; - uint64_t f7; - uint64_t f8; - uint64_t f9; - uint64_t f10; - uint64_t f11; - uint64_t f12; - uint64_t f13; - uint64_t f14; - uint64_t f15; - uint64_t f16; - uint64_t f17; - uint64_t f18; - uint64_t f19; - uint64_t f20; - uint64_t f21; - uint64_t f22; - uint64_t f23; - uint64_t f24; - uint64_t f25; - uint64_t f26; - uint64_t f27; - uint64_t f28; - uint64_t f29; - uint64_t f30; - uint64_t f31; - uint64_t fpscr; +typedef struct _FPR { + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; + uint64_t f6; + uint64_t f7; + uint64_t f8; + uint64_t f9; + uint64_t f10; + uint64_t f11; + uint64_t f12; + uint64_t f13; + uint64_t f14; + uint64_t f15; + uint64_t f16; + uint64_t f17; + uint64_t f18; + uint64_t f19; + uint64_t f20; + uint64_t f21; + uint64_t f22; + uint64_t f23; + uint64_t f24; + uint64_t f25; + uint64_t f26; + uint64_t f27; + uint64_t f28; + uint64_t f29; + uint64_t f30; + uint64_t f31; + uint64_t fpscr; } FPR; -typedef struct _VMX -{ - uint32_t v0[4]; - uint32_t v1[4]; - uint32_t v2[4]; - uint32_t v3[4]; - uint32_t v4[4]; - uint32_t v5[4]; - uint32_t v6[4]; - uint32_t v7[4]; - uint32_t v8[4]; - uint32_t v9[4]; - uint32_t v10[4]; - uint32_t v11[4]; - uint32_t v12[4]; - uint32_t v13[4]; - uint32_t v14[4]; - uint32_t v15[4]; - uint32_t v16[4]; - uint32_t v17[4]; - uint32_t v18[4]; - uint32_t v19[4]; - uint32_t v20[4]; - uint32_t v21[4]; - uint32_t v22[4]; - uint32_t v23[4]; - uint32_t v24[4]; - uint32_t v25[4]; - uint32_t v26[4]; - uint32_t v27[4]; - uint32_t v28[4]; - uint32_t v29[4]; - uint32_t v30[4]; - uint32_t v31[4]; - uint32_t pad[2]; - uint32_t vrsave; - uint32_t vscr; +typedef struct _VMX { + uint32_t v0[4]; + uint32_t v1[4]; + uint32_t v2[4]; + uint32_t v3[4]; + uint32_t v4[4]; + uint32_t v5[4]; + uint32_t v6[4]; + uint32_t v7[4]; + uint32_t v8[4]; + uint32_t v9[4]; + uint32_t v10[4]; + uint32_t v11[4]; + uint32_t v12[4]; + uint32_t v13[4]; + uint32_t v14[4]; + uint32_t v15[4]; + uint32_t v16[4]; + uint32_t v17[4]; + uint32_t v18[4]; + uint32_t v19[4]; + uint32_t v20[4]; + uint32_t v21[4]; + uint32_t v22[4]; + uint32_t v23[4]; + uint32_t v24[4]; + uint32_t v25[4]; + uint32_t v26[4]; + uint32_t v27[4]; + uint32_t v28[4]; + uint32_t v29[4]; + uint32_t v30[4]; + uint32_t v31[4]; + uint32_t pad[2]; + uint32_t vrsave; + uint32_t vscr; } VMX; //--------------------------------------------------------------------------- -// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure. +// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc +// structure. //--------------------------------------------------------------------------- #define DECLARE_REGISTER_INFOS_POWERPC_STRUCT #include "RegisterInfos_powerpc.h" #undef DECLARE_REGISTER_INFOS_POWERPC_STRUCT -RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(const ArchSpec &target_arch) : - RegisterInfoInterface(target_arch) -{ -} +RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} -RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() -{ -} +RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() {} -size_t -RegisterContextFreeBSD_powerpc::GetGPRSize() const -{ - // This is an 'abstract' base, so no GPR struct. - return 0; +size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const { + // This is an 'abstract' base, so no GPR struct. + return 0; } -const RegisterInfo * -RegisterContextFreeBSD_powerpc::GetRegisterInfo() const -{ - //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); - llvm_unreachable("Abstract class!"); - return NULL; +const RegisterInfo *RegisterContextFreeBSD_powerpc::GetRegisterInfo() const { + // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + llvm_unreachable("Abstract class!"); + return NULL; } -uint32_t -RegisterContextFreeBSD_powerpc::GetRegisterCount () const -{ - return 0; -} +uint32_t RegisterContextFreeBSD_powerpc::GetRegisterCount() const { return 0; } -RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(const ArchSpec &target_arch) : - RegisterContextFreeBSD_powerpc(target_arch) -{ -} +RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32( + const ArchSpec &target_arch) + : RegisterContextFreeBSD_powerpc(target_arch) {} -RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() -{ -} +RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() {} -size_t -RegisterContextFreeBSD_powerpc32::GetGPRSize() const -{ - return sizeof(GPR32); +size_t RegisterContextFreeBSD_powerpc32::GetGPRSize() const { + return sizeof(GPR32); } -const RegisterInfo * -RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const -{ - //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); - return g_register_infos_powerpc32; +const RegisterInfo *RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const { + // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + return g_register_infos_powerpc32; } -uint32_t -RegisterContextFreeBSD_powerpc32::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_powerpc32) / sizeof (g_register_infos_powerpc32 [0])); +uint32_t RegisterContextFreeBSD_powerpc32::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_powerpc32) / + sizeof(g_register_infos_powerpc32[0])); } -RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(const ArchSpec &target_arch) : - RegisterContextFreeBSD_powerpc(target_arch) -{ -} +RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64( + const ArchSpec &target_arch) + : RegisterContextFreeBSD_powerpc(target_arch) {} -RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() -{ -} +RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() {} -size_t -RegisterContextFreeBSD_powerpc64::GetGPRSize() const -{ - return sizeof(GPR64); +size_t RegisterContextFreeBSD_powerpc64::GetGPRSize() const { + return sizeof(GPR64); } -const RegisterInfo * -RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const -{ - //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); - if (m_target_arch.GetMachine() == llvm::Triple::ppc) - return g_register_infos_powerpc64_32; - return g_register_infos_powerpc64; +const RegisterInfo *RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const { + // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + if (m_target_arch.GetMachine() == llvm::Triple::ppc) + return g_register_infos_powerpc64_32; + return g_register_infos_powerpc64; } -uint32_t -RegisterContextFreeBSD_powerpc64::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_powerpc64) / sizeof (g_register_infos_powerpc64 [0])); +uint32_t RegisterContextFreeBSD_powerpc64::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_powerpc64) / + sizeof(g_register_infos_powerpc64[0])); } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h index 930683f8a87..c9a65b1cacc 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h @@ -1,4 +1,5 @@ -//===-- RegisterContextFreeBSD_powerpc.h -------------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_powerpc.h -------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,55 +17,41 @@ // Project includes #include "RegisterInfoInterface.h" -class RegisterContextFreeBSD_powerpc: - public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_powerpc + : public lldb_private::RegisterInfoInterface { public: - RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch); - ~RegisterContextFreeBSD_powerpc() override; + RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch); + ~RegisterContextFreeBSD_powerpc() override; - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount() const override; + uint32_t GetRegisterCount() const override; }; -class RegisterContextFreeBSD_powerpc32: - public RegisterContextFreeBSD_powerpc -{ +class RegisterContextFreeBSD_powerpc32 : public RegisterContextFreeBSD_powerpc { public: - RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch); - ~RegisterContextFreeBSD_powerpc32() override; + RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch); + ~RegisterContextFreeBSD_powerpc32() override; - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount() const override; + uint32_t GetRegisterCount() const override; }; -class RegisterContextFreeBSD_powerpc64: - public RegisterContextFreeBSD_powerpc -{ +class RegisterContextFreeBSD_powerpc64 : public RegisterContextFreeBSD_powerpc { public: - RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch); - ~RegisterContextFreeBSD_powerpc64() override; + RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch); + ~RegisterContextFreeBSD_powerpc64() override; - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount() const override; + uint32_t GetRegisterCount() const override; }; #endif // liblldb_RegisterContextFreeBSD_powerpc_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp index 34f2d185da8..4bbbd5c3d0a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp @@ -7,158 +7,142 @@ // //===---------------------------------------------------------------------===// -#include <vector> -#include "RegisterContextPOSIX_x86.h" -#include "RegisterContextFreeBSD_i386.h" #include "RegisterContextFreeBSD_x86_64.h" +#include "RegisterContextFreeBSD_i386.h" +#include "RegisterContextPOSIX_x86.h" +#include <vector> using namespace lldb_private; using namespace lldb; // http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h -typedef struct _GPR -{ - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rdi; - uint64_t rsi; - uint64_t rbp; - uint64_t rbx; - uint64_t rdx; - uint64_t rcx; - uint64_t rax; - uint32_t trapno; - uint16_t fs; - uint16_t gs; - uint32_t err; - uint16_t es; - uint16_t ds; - uint64_t rip; - uint64_t cs; - uint64_t rflags; - uint64_t rsp; - uint64_t ss; +typedef struct _GPR { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rbx; + uint64_t rdx; + uint64_t rcx; + uint64_t rax; + uint32_t trapno; + uint16_t fs; + uint16_t gs; + uint32_t err; + uint16_t es; + uint16_t ds; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; } GPR; struct DBG { - uint64_t dr[16]; /* debug registers */ - /* Index 0-3: debug address registers */ - /* Index 4-5: reserved */ - /* Index 6: debug status */ - /* Index 7: debug control */ - /* Index 8-15: reserved */ + uint64_t dr[16]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ + /* Index 8-15: reserved */ }; -struct UserArea -{ - GPR gpr; - FPR fpr; - DBG dbg; +struct UserArea { + GPR gpr; + FPR fpr; + DBG dbg; }; -#define DR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(DBG, dr[reg_index])) +#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(DBG, dr[reg_index])) //--------------------------------------------------------------------------- -// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure. +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 +// structure. //--------------------------------------------------------------------------- #define DECLARE_REGISTER_INFOS_X86_64_STRUCT #include "RegisterInfos_x86_64.h" #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT -static std::vector<lldb_private::RegisterInfo>& -GetSharedRegisterInfoVector () -{ - static std::vector<lldb_private::RegisterInfo> register_infos; - return register_infos; +static std::vector<lldb_private::RegisterInfo> &GetSharedRegisterInfoVector() { + static std::vector<lldb_private::RegisterInfo> register_infos; + return register_infos; } static const RegisterInfo * -GetRegisterInfo_i386(const lldb_private::ArchSpec& arch) -{ - static std::vector<lldb_private::RegisterInfo> g_register_infos (GetSharedRegisterInfoVector ()); - - // Allocate RegisterInfo only once - if (g_register_infos.empty()) - { - // Copy the register information from base class - std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(new RegisterContextFreeBSD_i386 (arch)); - const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); - g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]); - - //--------------------------------------------------------------------------- - // Include RegisterInfos_x86_64 to update the g_register_infos structure - // with x86_64 offsets. - //--------------------------------------------------------------------------- - #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS - #include "RegisterInfos_x86_64.h" - #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS - } - - return &g_register_infos[0]; +GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) { + static std::vector<lldb_private::RegisterInfo> g_register_infos( + GetSharedRegisterInfoVector()); + + // Allocate RegisterInfo only once + if (g_register_infos.empty()) { + // Copy the register information from base class + std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface( + new RegisterContextFreeBSD_i386(arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], + &base_info[k_num_registers_i386]); + +//--------------------------------------------------------------------------- +// Include RegisterInfos_x86_64 to update the g_register_infos structure +// with x86_64 offsets. +//--------------------------------------------------------------------------- +#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS +#include "RegisterInfos_x86_64.h" +#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + } + + return &g_register_infos[0]; } static const RegisterInfo * -PrivateGetRegisterInfoPtr (const lldb_private::ArchSpec& target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86: - return GetRegisterInfo_i386 (target_arch); - case llvm::Triple::x86_64: - return g_register_infos_x86_64; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return GetRegisterInfo_i386(target_arch); + case llvm::Triple::x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } static uint32_t -PrivateGetRegisterCount (const lldb_private::ArchSpec& target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86: - // This vector should have already been filled. - assert (!GetSharedRegisterInfoVector ().empty () && "i386 register info vector not filled."); - return static_cast<uint32_t> (GetSharedRegisterInfoVector().size ()); - case llvm::Triple::x86_64: - return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + // This vector should have already been filled. + assert(!GetSharedRegisterInfoVector().empty() && + "i386 register info vector not filled."); + return static_cast<uint32_t>(GetSharedRegisterInfoVector().size()); + case llvm::Triple::x86_64: + return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / + sizeof(g_register_infos_x86_64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p (PrivateGetRegisterInfoPtr (target_arch)), - m_register_count (PrivateGetRegisterCount (target_arch)) -{ -} +RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)), + m_register_count(PrivateGetRegisterCount(target_arch)) {} -size_t -RegisterContextFreeBSD_x86_64::GetGPRSize() const -{ - return sizeof(GPR); -} +size_t RegisterContextFreeBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } -const RegisterInfo * -RegisterContextFreeBSD_x86_64::GetRegisterInfo() const -{ - return m_register_info_p; +const RegisterInfo *RegisterContextFreeBSD_x86_64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextFreeBSD_x86_64::GetRegisterCount () const -{ - return m_register_count; +uint32_t RegisterContextFreeBSD_x86_64::GetRegisterCount() const { + return m_register_count; } - - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h index e739fa50ed6..dc30f1783b4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h @@ -12,24 +12,20 @@ #include "RegisterInfoInterface.h" -class RegisterContextFreeBSD_x86_64: - public lldb_private::RegisterInfoInterface -{ +class RegisterContextFreeBSD_x86_64 + : public lldb_private::RegisterInfoInterface { public: - RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch); + RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - const uint32_t m_register_count; + const lldb_private::RegisterInfo *m_register_info_p; + const uint32_t m_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp index 9d2181376e0..0fc47fcd8e3 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextHistory.cpp ---------------------------------*- C++ -*-===// +//===-- RegisterContextHistory.cpp ---------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +8,6 @@ // //===----------------------------------------------------------------------===// - -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/DataBufferHeap.h" @@ -20,119 +19,105 @@ #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/DynamicLoader.h" +#include "lldb/lldb-private.h" #include "RegisterContextHistory.h" using namespace lldb; using namespace lldb_private; -RegisterContextHistory::RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, addr_t pc_value) : -RegisterContext (thread, concrete_frame_idx), - m_pc_value (pc_value) -{ - m_reg_set0.name = "General Purpose Registers"; - m_reg_set0.short_name = "GPR"; - m_reg_set0.num_registers = 1; - m_reg_set0.registers = new uint32_t(0); - - m_pc_reg_info.name = "pc"; - m_pc_reg_info.alt_name = "pc"; - m_pc_reg_info.byte_offset = 0; - m_pc_reg_info.byte_size = address_byte_size; - m_pc_reg_info.encoding = eEncodingUint; - m_pc_reg_info.format = eFormatPointer; - m_pc_reg_info.invalidate_regs = NULL; - m_pc_reg_info.value_regs = NULL; - m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; - m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM; - m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM; +RegisterContextHistory::RegisterContextHistory(Thread &thread, + uint32_t concrete_frame_idx, + uint32_t address_byte_size, + addr_t pc_value) + : RegisterContext(thread, concrete_frame_idx), m_pc_value(pc_value) { + m_reg_set0.name = "General Purpose Registers"; + m_reg_set0.short_name = "GPR"; + m_reg_set0.num_registers = 1; + m_reg_set0.registers = new uint32_t(0); + + m_pc_reg_info.name = "pc"; + m_pc_reg_info.alt_name = "pc"; + m_pc_reg_info.byte_offset = 0; + m_pc_reg_info.byte_size = address_byte_size; + m_pc_reg_info.encoding = eEncodingUint; + m_pc_reg_info.format = eFormatPointer; + m_pc_reg_info.invalidate_regs = NULL; + m_pc_reg_info.value_regs = NULL; + m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM; + m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM; } -RegisterContextHistory::~RegisterContextHistory () -{ - delete m_reg_set0.registers; - delete m_pc_reg_info.invalidate_regs; - delete m_pc_reg_info.value_regs; +RegisterContextHistory::~RegisterContextHistory() { + delete m_reg_set0.registers; + delete m_pc_reg_info.invalidate_regs; + delete m_pc_reg_info.value_regs; } -void -RegisterContextHistory::InvalidateAllRegisters () {} +void RegisterContextHistory::InvalidateAllRegisters() {} -size_t -RegisterContextHistory::GetRegisterCount () -{ - return 1; -} +size_t RegisterContextHistory::GetRegisterCount() { return 1; } const lldb_private::RegisterInfo * -RegisterContextHistory::GetRegisterInfoAtIndex (size_t reg) -{ - if (reg) - return NULL; - return &m_pc_reg_info; +RegisterContextHistory::GetRegisterInfoAtIndex(size_t reg) { + if (reg) + return NULL; + return &m_pc_reg_info; } -size_t -RegisterContextHistory::GetRegisterSetCount () -{ - return 1; -} +size_t RegisterContextHistory::GetRegisterSetCount() { return 1; } const lldb_private::RegisterSet * -RegisterContextHistory::GetRegisterSet (size_t reg_set) -{ - if (reg_set) - return NULL; - return &m_reg_set0; +RegisterContextHistory::GetRegisterSet(size_t reg_set) { + if (reg_set) + return NULL; + return &m_reg_set0; } -bool -RegisterContextHistory::ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) -{ - if (!reg_info) - return false; - uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric]; - if (reg_number == LLDB_REGNUM_GENERIC_PC) - { - value.SetUInt(m_pc_value, reg_info->byte_size); - return true; - } +bool RegisterContextHistory::ReadRegister( + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) { + if (!reg_info) return false; + uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric]; + if (reg_number == LLDB_REGNUM_GENERIC_PC) { + value.SetUInt(m_pc_value, reg_info->byte_size); + return true; + } + return false; } -bool -RegisterContextHistory::WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) -{ - return false; +bool RegisterContextHistory::WriteRegister( + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) { + return false; } -bool -RegisterContextHistory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextHistory::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextHistory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextHistory::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -uint32_t -RegisterContextHistory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC) - return 0; - return LLDB_INVALID_REGNUM; +uint32_t RegisterContextHistory::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC) + return 0; + return LLDB_INVALID_REGNUM; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h index 3f44a1fde68..acaf8fe5c04 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h @@ -1,4 +1,5 @@ -//===-- RegisterContextHistory.h ----------------------------------------*- C++ -*-===// +//===-- RegisterContextHistory.h ----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,64 +17,55 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" namespace lldb_private { - -class RegisterContextHistory : public lldb_private::RegisterContext -{ + +class RegisterContextHistory : public lldb_private::RegisterContext { public: - typedef std::shared_ptr<RegisterContextHistory> SharedPtr; - - RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, lldb::addr_t pc_value); - - ~RegisterContextHistory() override; + typedef std::shared_ptr<RegisterContextHistory> SharedPtr; + + RegisterContextHistory(Thread &thread, uint32_t concrete_frame_idx, + uint32_t address_byte_size, lldb::addr_t pc_value); - void - InvalidateAllRegisters() override; + ~RegisterContextHistory() override; - size_t - GetRegisterCount() override; + void InvalidateAllRegisters() override; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + size_t GetRegisterCount() override; - size_t - GetRegisterSetCount() override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t reg_set) override; + size_t GetRegisterSetCount() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - private: - //------------------------------------------------------------------ - // For RegisterContextLLDB only - //------------------------------------------------------------------ - - lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only) - lldb_private::RegisterInfo m_pc_reg_info; - - lldb::addr_t m_pc_value; - - DISALLOW_COPY_AND_ASSIGN (RegisterContextHistory); + //------------------------------------------------------------------ + // For RegisterContextLLDB only + //------------------------------------------------------------------ + + lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only) + lldb_private::RegisterInfo m_pc_reg_info; + + lldb::addr_t m_pc_value; + + DISALLOW_COPY_AND_ASSIGN(RegisterContextHistory); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 8bbaeb8e9a5..50fc0c20961 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// - -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/DataBufferHeap.h" @@ -33,1829 +31,1824 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" #include "RegisterContextLLDB.h" using namespace lldb; using namespace lldb_private; -static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) -{ - if (sym_ctx.symbol) - return sym_ctx.symbol->GetName(); - else if (sym_ctx.function) - return sym_ctx.function->GetName(); - return ConstString(); +static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) { + if (sym_ctx.symbol) + return sym_ctx.symbol->GetName(); + else if (sym_ctx.function) + return sym_ctx.function->GetName(); + return ConstString(); } -RegisterContextLLDB::RegisterContextLLDB -( - Thread& thread, - const SharedPtr &next_frame, - SymbolContext& sym_ctx, - uint32_t frame_number, - UnwindLLDB& unwind_lldb -) : - RegisterContext (thread, frame_number), - m_thread(thread), - m_fast_unwind_plan_sp (), - m_full_unwind_plan_sp (), - m_fallback_unwind_plan_sp (), - m_all_registers_available(false), - m_frame_type (-1), - m_cfa (LLDB_INVALID_ADDRESS), - m_start_pc (), - m_current_pc (), - m_current_offset (0), - m_current_offset_backed_up_one (0), - m_sym_ctx(sym_ctx), - m_sym_ctx_valid (false), - m_frame_number (frame_number), - m_registers(), - m_parent_unwind (unwind_lldb) -{ - m_sym_ctx.Clear(false); - m_sym_ctx_valid = false; - - if (IsFrameZero ()) - { - InitializeZerothFrame (); - } - else - { - InitializeNonZerothFrame (); - } - - // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet - if (IsFrameZero() - || next_frame->m_frame_type == eTrapHandlerFrame - || next_frame->m_frame_type == eDebuggerFrame) - { - m_all_registers_available = true; - } +RegisterContextLLDB::RegisterContextLLDB(Thread &thread, + const SharedPtr &next_frame, + SymbolContext &sym_ctx, + uint32_t frame_number, + UnwindLLDB &unwind_lldb) + : RegisterContext(thread, frame_number), m_thread(thread), + m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(), + m_fallback_unwind_plan_sp(), m_all_registers_available(false), + m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), m_start_pc(), + m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0), + m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number), + m_registers(), m_parent_unwind(unwind_lldb) { + m_sym_ctx.Clear(false); + m_sym_ctx_valid = false; + + if (IsFrameZero()) { + InitializeZerothFrame(); + } else { + InitializeNonZerothFrame(); + } + + // This same code exists over in the GetFullUnwindPlanForFrame() but it may + // not have been executed yet + if (IsFrameZero() || next_frame->m_frame_type == eTrapHandlerFrame || + next_frame->m_frame_type == eDebuggerFrame) { + m_all_registers_available = true; + } } -bool -RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) -{ - if (!unwind_plan_sp) - return false; +bool RegisterContextLLDB::IsUnwindPlanValidForCurrentPC( + lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) { + if (!unwind_plan_sp) + return false; - // check if m_current_pc is valid - if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) - { - // yes - current offset can be used as is - valid_pc_offset = m_current_offset; - return true; - } + // check if m_current_pc is valid + if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + // yes - current offset can be used as is + valid_pc_offset = m_current_offset; + return true; + } - // if m_current_offset <= 0, we've got nothing else to try - if (m_current_offset <= 0) - return false; + // if m_current_offset <= 0, we've got nothing else to try + if (m_current_offset <= 0) + return false; - // check pc - 1 to see if it's valid - Address pc_minus_one (m_current_pc); - pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); - if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) - { - // *valid_pc_offset = m_current_offset - 1; - valid_pc_offset = m_current_pc.GetOffset() - 1; - return true; - } + // check pc - 1 to see if it's valid + Address pc_minus_one(m_current_pc); + pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); + if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) { + // *valid_pc_offset = m_current_offset - 1; + valid_pc_offset = m_current_pc.GetOffset() - 1; + return true; + } - return false; + return false; } -// Initialize a RegisterContextLLDB which is the first frame of a stack -- the zeroth frame or currently +// Initialize a RegisterContextLLDB which is the first frame of a stack -- the +// zeroth frame or currently // executing frame. -void -RegisterContextLLDB::InitializeZerothFrame() -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - ExecutionContext exe_ctx(m_thread.shared_from_this()); - RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); - - if (reg_ctx_sp.get() == NULL) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("frame does not have a register context"); - return; - } - - addr_t current_pc = reg_ctx_sp->GetPC(); +void RegisterContextLLDB::InitializeZerothFrame() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + ExecutionContext exe_ctx(m_thread.shared_from_this()); + RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); - if (current_pc == LLDB_INVALID_ADDRESS) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("frame does not have a pc"); - return; - } - - Process *process = exe_ctx.GetProcessPtr(); - - // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs - // this will strip bit zero in case we read a PC from memory or from the LR. - // (which would be a no-op in frame 0 where we get it from the register set, - // but still a good idea to make the call here for other ABIs that may exist.) - ABI *abi = process->GetABI().get(); - if (abi) - current_pc = abi->FixCodeAddress(current_pc); - - // Initialize m_current_pc, an Address object, based on current_pc, an addr_t. - m_current_pc.SetLoadAddress (current_pc, &process->GetTarget()); - - // If we don't have a Module for some reason, we're not going to find symbol/function information - just - // stick in some reasonable defaults and hope we can unwind past this frame. - ModuleSP pc_module_sp (m_current_pc.GetModule()); - if (!m_current_pc.IsValid() || !pc_module_sp) - { - UnwindLogMsg ("using architectural default unwind method"); - } + if (reg_ctx_sp.get() == NULL) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("frame does not have a register context"); + return; + } - // We require either a symbol or function in the symbols context to be successfully - // filled in or this context is of no use to us. - const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; - if (pc_module_sp.get() - && (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, resolve_scope, m_sym_ctx) & resolve_scope)) - { - m_sym_ctx_valid = true; - } + addr_t current_pc = reg_ctx_sp->GetPC(); - if (m_sym_ctx.symbol) - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", - current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - } - else if (m_sym_ctx.function) - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", - current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - } - else - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", current_pc); - } - - AddressRange addr_range; - m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range); + if (current_pc == LLDB_INVALID_ADDRESS) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("frame does not have a pc"); + return; + } + + Process *process = exe_ctx.GetProcessPtr(); + + // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs + // this will strip bit zero in case we read a PC from memory or from the LR. + // (which would be a no-op in frame 0 where we get it from the register set, + // but still a good idea to make the call here for other ABIs that may exist.) + ABI *abi = process->GetABI().get(); + if (abi) + current_pc = abi->FixCodeAddress(current_pc); + + // Initialize m_current_pc, an Address object, based on current_pc, an addr_t. + m_current_pc.SetLoadAddress(current_pc, &process->GetTarget()); + + // If we don't have a Module for some reason, we're not going to find + // symbol/function information - just + // stick in some reasonable defaults and hope we can unwind past this frame. + ModuleSP pc_module_sp(m_current_pc.GetModule()); + if (!m_current_pc.IsValid() || !pc_module_sp) { + UnwindLogMsg("using architectural default unwind method"); + } + + // We require either a symbol or function in the symbols context to be + // successfully + // filled in or this context is of no use to us. + const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; + if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress( + m_current_pc, resolve_scope, m_sym_ctx) & + resolve_scope)) { + m_sym_ctx_valid = true; + } + + if (m_sym_ctx.symbol) { + UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", + current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + } else if (m_sym_ctx.function) { + UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", + current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + } else { + UnwindLogMsg("with pc value of 0x%" PRIx64 + ", no symbol/function name is known.", + current_pc); + } + + AddressRange addr_range; + m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range); + + if (IsTrapHandlerSymbol(process, m_sym_ctx)) { + m_frame_type = eTrapHandlerFrame; + } else { + // FIXME: Detect eDebuggerFrame here. + m_frame_type = eNormalFrame; + } + + // If we were able to find a symbol/function, set addr_range to the bounds of + // that symbol/function. + // else treat the current pc value as the start_pc and record no offset. + if (addr_range.GetBaseAddress().IsValid()) { + m_start_pc = addr_range.GetBaseAddress(); + if (m_current_pc.GetSection() == m_start_pc.GetSection()) { + m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset(); + } else if (m_current_pc.GetModule() == m_start_pc.GetModule()) { + // This means that whatever symbol we kicked up isn't really correct + // --- we should not cross section boundaries ... We really should NULL + // out + // the function/symbol in this case unless there is a bad assumption + // here due to inlined functions? + m_current_offset = + m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress(); + } + m_current_offset_backed_up_one = m_current_offset; + } else { + m_start_pc = m_current_pc; + m_current_offset = -1; + m_current_offset_backed_up_one = -1; + } + + // We've set m_frame_type and m_sym_ctx before these calls. + + m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); + m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); + + UnwindPlan::RowSP active_row; + lldb::RegisterKind row_register_kind = eRegisterKindGeneric; + if (m_full_unwind_plan_sp && + m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + active_row = + m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); + if (active_row.get() && log) { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, + m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); + UnwindLogMsg("%s", active_row_strm.GetString().c_str()); + } + } + + if (!active_row.get()) { + UnwindLogMsg("could not find an unwindplan row for this frame's pc"); + m_frame_type = eNotAValidFrame; + return; + } - if (IsTrapHandlerSymbol (process, m_sym_ctx)) - { - m_frame_type = eTrapHandlerFrame; - } - else - { - // FIXME: Detect eDebuggerFrame here. - m_frame_type = eNormalFrame; - } + if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) { + // Try the fall back unwind plan since the + // full unwind plan failed. + FuncUnwindersSP func_unwinders_sp; + UnwindPlanSP call_site_unwind_plan; + bool cfa_status = false; - // If we were able to find a symbol/function, set addr_range to the bounds of that symbol/function. - // else treat the current pc value as the start_pc and record no offset. - if (addr_range.GetBaseAddress().IsValid()) - { - m_start_pc = addr_range.GetBaseAddress(); - if (m_current_pc.GetSection() == m_start_pc.GetSection()) - { - m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset(); - } - else if (m_current_pc.GetModule() == m_start_pc.GetModule()) - { - // This means that whatever symbol we kicked up isn't really correct - // --- we should not cross section boundaries ... We really should NULL out - // the function/symbol in this case unless there is a bad assumption - // here due to inlined functions? - m_current_offset = m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress(); - } - m_current_offset_backed_up_one = m_current_offset; - } - else - { - m_start_pc = m_current_pc; - m_current_offset = -1; - m_current_offset_backed_up_one = -1; + if (m_sym_ctx_valid) { + func_unwinders_sp = + pc_module_sp->GetObjectFile() + ->GetUnwindTable() + .GetFuncUnwindersContainingAddress(m_current_pc, m_sym_ctx); } - // We've set m_frame_type and m_sym_ctx before these calls. + if (func_unwinders_sp.get() != nullptr) + call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_current_offset_backed_up_one); - m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame (); - m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); - - UnwindPlan::RowSP active_row; - lldb::RegisterKind row_register_kind = eRegisterKindGeneric; - if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc)) - { - active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); - if (active_row.get() && log) - { - StreamString active_row_strm; - active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - UnwindLogMsg ("%s", active_row_strm.GetString().c_str()); - } + if (call_site_unwind_plan.get() != nullptr) { + m_fallback_unwind_plan_sp = call_site_unwind_plan; + if (TryFallbackUnwindPlan()) + cfa_status = true; } - - if (!active_row.get()) - { - UnwindLogMsg ("could not find an unwindplan row for this frame's pc"); - m_frame_type = eNotAValidFrame; - return; - } - - - if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa)) - { - // Try the fall back unwind plan since the - // full unwind plan failed. - FuncUnwindersSP func_unwinders_sp; - UnwindPlanSP call_site_unwind_plan; - bool cfa_status = false; - - if (m_sym_ctx_valid) - { - func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); - } - - if(func_unwinders_sp.get() != nullptr) - call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one); - - if (call_site_unwind_plan.get() != nullptr) - { - m_fallback_unwind_plan_sp = call_site_unwind_plan; - if(TryFallbackUnwindPlan()) - cfa_status = true; - } - if (!cfa_status) - { - UnwindLogMsg ("could not read CFA value for first frame."); - m_frame_type = eNotAValidFrame; - return; - } + if (!cfa_status) { + UnwindLogMsg("could not read CFA value for first frame."); + m_frame_type = eNotAValidFrame; + return; } + } - UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan", - (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), - (uint64_t) m_cfa, - m_full_unwind_plan_sp->GetSourceName().GetCString()); + UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 + " using %s UnwindPlan", + (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), + (uint64_t)m_cfa, + m_full_unwind_plan_sp->GetSourceName().GetCString()); } -// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it +// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the +// RegisterContextLLDB "below" it // to provide things like its current pc value. -void -RegisterContextLLDB::InitializeNonZerothFrame() -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (IsFrameZero ()) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("non-zeroth frame tests positive for IsFrameZero -- that shouldn't happen."); - return; - } - - if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("Could not get next frame, marking this frame as invalid."); - return; - } - if (!m_thread.GetRegisterContext()) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("Could not get register context for this thread, marking this frame as invalid."); - return; - } +void RegisterContextLLDB::InitializeNonZerothFrame() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (IsFrameZero()) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("non-zeroth frame tests positive for IsFrameZero -- that " + "shouldn't happen."); + return; + } - addr_t pc; - if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) - { - UnwindLogMsg ("could not get pc value"); + if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("Could not get next frame, marking this frame as invalid."); + return; + } + if (!m_thread.GetRegisterContext()) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("Could not get register context for this thread, marking this " + "frame as invalid."); + return; + } + + addr_t pc; + if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { + UnwindLogMsg("could not get pc value"); + m_frame_type = eNotAValidFrame; + return; + } + + if (log) { + UnwindLogMsg("pc = 0x%" PRIx64, pc); + addr_t reg_val; + if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) + UnwindLogMsg("fp = 0x%" PRIx64, reg_val); + if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) + UnwindLogMsg("sp = 0x%" PRIx64, reg_val); + } + + // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap + // handler function + bool above_trap_handler = false; + if (GetNextFrame().get() && GetNextFrame()->IsValid() && + GetNextFrame()->IsTrapHandlerFrame()) + above_trap_handler = true; + + if (pc == 0 || pc == 0x1) { + if (above_trap_handler == false) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("this frame has a pc of 0x0"); + return; + } + } + + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs + // this will strip bit zero in case we read a PC from memory or from the LR. + ABI *abi = process->GetABI().get(); + if (abi) + pc = abi->FixCodeAddress(pc); + + m_current_pc.SetLoadAddress(pc, &process->GetTarget()); + + // If we don't have a Module for some reason, we're not going to find + // symbol/function information - just + // stick in some reasonable defaults and hope we can unwind past this frame. + ModuleSP pc_module_sp(m_current_pc.GetModule()); + if (!m_current_pc.IsValid() || !pc_module_sp) { + UnwindLogMsg("using architectural default unwind method"); + + // Test the pc value to see if we know it's in an unmapped/non-executable + // region of memory. + uint32_t permissions; + if (process->GetLoadAddressPermissions(pc, permissions) && + (permissions & ePermissionsExecutable) == 0) { + // If this is the second frame off the stack, we may have unwound the + // first frame + // incorrectly. But using the architecture default unwind plan may get us + // back on + // track -- albeit possibly skipping a real frame. Give this frame a + // clearly-invalid + // pc and see if we can get any further. + if (GetNextFrame().get() && GetNextFrame()->IsValid() && + GetNextFrame()->IsFrameZero()) { + UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable " + "memory but on frame 1 -- " + "allowing it once.", + (uint64_t)pc); + m_frame_type = eSkipFrame; + } else { + // anywhere other than the second frame, a non-executable pc means we're + // off in the weeds -- stop now. m_frame_type = eNotAValidFrame; + UnwindLogMsg("pc is in a non-executable section of memory and this " + "isn't the 2nd frame in the stack walk."); return; + } } - if (log) - { - UnwindLogMsg ("pc = 0x%" PRIx64, pc); - addr_t reg_val; - if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) - UnwindLogMsg ("fp = 0x%" PRIx64, reg_val); - if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) - UnwindLogMsg ("sp = 0x%" PRIx64, reg_val); - } - - // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap handler function - bool above_trap_handler = false; - if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame()) - above_trap_handler = true; - - if (pc == 0 || pc == 0x1) - { - if (above_trap_handler == false) - { + if (abi) { + m_fast_unwind_plan_sp.reset(); + m_full_unwind_plan_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp); + if (m_frame_type != eSkipFrame) // don't override eSkipFrame + { + m_frame_type = eNormalFrame; + } + m_all_registers_available = false; + m_current_offset = -1; + m_current_offset_backed_up_one = -1; + RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); + UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0); + if (row.get()) { + if (!ReadCFAValueForRow(row_register_kind, row, m_cfa)) { + UnwindLogMsg("failed to get cfa value"); + if (m_frame_type != eSkipFrame) // don't override eSkipFrame + { m_frame_type = eNotAValidFrame; - UnwindLogMsg ("this frame has a pc of 0x0"); - return; + } + return; } - } - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs - // this will strip bit zero in case we read a PC from memory or from the LR. - ABI *abi = process->GetABI().get(); - if (abi) - pc = abi->FixCodeAddress(pc); - - m_current_pc.SetLoadAddress (pc, &process->GetTarget()); - - // If we don't have a Module for some reason, we're not going to find symbol/function information - just - // stick in some reasonable defaults and hope we can unwind past this frame. - ModuleSP pc_module_sp (m_current_pc.GetModule()); - if (!m_current_pc.IsValid() || !pc_module_sp) - { - UnwindLogMsg ("using architectural default unwind method"); - - // Test the pc value to see if we know it's in an unmapped/non-executable region of memory. - uint32_t permissions; - if (process->GetLoadAddressPermissions(pc, permissions) - && (permissions & ePermissionsExecutable) == 0) - { - // If this is the second frame off the stack, we may have unwound the first frame - // incorrectly. But using the architecture default unwind plan may get us back on - // track -- albeit possibly skipping a real frame. Give this frame a clearly-invalid - // pc and see if we can get any further. - if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero()) - { - UnwindLogMsg ("had a pc of 0x%" PRIx64 " which is not in executable memory but on frame 1 -- allowing it once.", - (uint64_t) pc); - m_frame_type = eSkipFrame; - } - else - { - // anywhere other than the second frame, a non-executable pc means we're off in the weeds -- stop now. - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("pc is in a non-executable section of memory and this isn't the 2nd frame in the stack walk."); - return; - } + // A couple of sanity checks.. + if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) { + UnwindLogMsg("could not find a valid cfa address"); + m_frame_type = eNotAValidFrame; + return; } - if (abi) - { - m_fast_unwind_plan_sp.reset (); - m_full_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp); - if (m_frame_type != eSkipFrame) // don't override eSkipFrame - { - m_frame_type = eNormalFrame; - } - m_all_registers_available = false; - m_current_offset = -1; - m_current_offset_backed_up_one = -1; - RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); - UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0); - if (row.get()) - { - if (!ReadCFAValueForRow (row_register_kind, row, m_cfa)) - { - UnwindLogMsg ("failed to get cfa value"); - if (m_frame_type != eSkipFrame) // don't override eSkipFrame - { - m_frame_type = eNotAValidFrame; - } - return; - } - - // A couple of sanity checks.. - if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) - { - UnwindLogMsg ("could not find a valid cfa address"); - m_frame_type = eNotAValidFrame; - return; - } - - // m_cfa should point into the stack memory; if we can query memory region permissions, - // see if the memory is allocated & readable. - if (process->GetLoadAddressPermissions(m_cfa, permissions) - && (permissions & ePermissionsReadable) == 0) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("the CFA points to a region of memory that is not readable"); - return; - } - } - else - { - UnwindLogMsg ("could not find a row for function offset zero"); - m_frame_type = eNotAValidFrame; - return; - } - - if (CheckIfLoopingStack ()) - { - TryFallbackUnwindPlan(); - if (CheckIfLoopingStack ()) - { - UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); - m_frame_type = eNotAValidFrame; - return; - } - } - - UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa); - return; + // m_cfa should point into the stack memory; if we can query memory + // region permissions, + // see if the memory is allocated & readable. + if (process->GetLoadAddressPermissions(m_cfa, permissions) && + (permissions & ePermissionsReadable) == 0) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg( + "the CFA points to a region of memory that is not readable"); + return; } + } else { + UnwindLogMsg("could not find a row for function offset zero"); m_frame_type = eNotAValidFrame; - UnwindLogMsg ("could not find any symbol for this pc, or a default unwind plan, to continue unwind."); return; - } - - bool resolve_tail_call_address = false; // m_current_pc can be one past the address range of the function... - // If the saved pc does not point to a function/symbol because it is - // beyond the bounds of the correct function and there's no symbol there, - // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1, - // because then we might not find the correct unwind information later. - // Instead, let ResolveSymbolContextForAddress fail, and handle the case - // via decr_pc_and_recompute_addr_range below. - const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; - uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, - resolve_scope, - m_sym_ctx, resolve_tail_call_address); - - // We require either a symbol or function in the symbols context to be successfully - // filled in or this context is of no use to us. - if (resolve_scope & resolved_scope) - { - m_sym_ctx_valid = true; - } - - if (m_sym_ctx.symbol) - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", - pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - } - else if (m_sym_ctx.function) - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", - pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - } - else - { - UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", pc); - } + } - AddressRange addr_range; - if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range)) - { - m_sym_ctx_valid = false; - } - - bool decr_pc_and_recompute_addr_range = false; - - // If the symbol lookup failed... - if (m_sym_ctx_valid == false) - decr_pc_and_recompute_addr_range = true; - - // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), - // and our "current" pc is the start of a function... - if (m_sym_ctx_valid - && GetNextFrame()->m_frame_type != eTrapHandlerFrame - && GetNextFrame()->m_frame_type != eDebuggerFrame - && addr_range.GetBaseAddress().IsValid() - && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() - && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) - { - decr_pc_and_recompute_addr_range = true; - } - - // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc" - // value is pointing to the next function, e.g. if a function ends with a CALL instruction. - // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function - // to the ABI plugin and consult that. - if (decr_pc_and_recompute_addr_range) - { - UnwindLogMsg ("Backing up the pc value of 0x%" PRIx64 " by 1 and re-doing symbol lookup; old symbol was %s", - pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - Address temporary_pc; - temporary_pc.SetLoadAddress (pc - 1, &process->GetTarget()); - m_sym_ctx.Clear (false); - m_sym_ctx_valid = false; - uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; - - ModuleSP temporary_module_sp = temporary_pc.GetModule(); - if (temporary_module_sp && - temporary_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope) - { - if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range)) - m_sym_ctx_valid = true; - } - UnwindLogMsg ("Symbol is now %s", GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - } - - // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function. - // else treat the current pc value as the start_pc and record no offset. - if (addr_range.GetBaseAddress().IsValid()) - { - m_start_pc = addr_range.GetBaseAddress(); - m_current_offset = pc - m_start_pc.GetLoadAddress (&process->GetTarget()); - m_current_offset_backed_up_one = m_current_offset; - if (decr_pc_and_recompute_addr_range && m_current_offset_backed_up_one > 0) - { - m_current_offset_backed_up_one--; - if (m_sym_ctx_valid) - { - m_current_pc.SetLoadAddress (pc - 1, &process->GetTarget()); - } - } - } - else - { - m_start_pc = m_current_pc; - m_current_offset = -1; - m_current_offset_backed_up_one = -1; - } - - if (IsTrapHandlerSymbol (process, m_sym_ctx)) - { - m_frame_type = eTrapHandlerFrame; - } - else - { - // FIXME: Detect eDebuggerFrame here. - if (m_frame_type != eSkipFrame) // don't override eSkipFrame - { - m_frame_type = eNormalFrame; + if (CheckIfLoopingStack()) { + TryFallbackUnwindPlan(); + if (CheckIfLoopingStack()) { + UnwindLogMsg("same CFA address as next frame, assuming the unwind is " + "looping - stopping"); + m_frame_type = eNotAValidFrame; + return; } - } - - // We've set m_frame_type and m_sym_ctx before this call. - m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame (); + } - UnwindPlan::RowSP active_row; - RegisterKind row_register_kind = eRegisterKindGeneric; - - // Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get - // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.) - - if (m_fast_unwind_plan_sp && m_fast_unwind_plan_sp->PlanValidAtAddress (m_current_pc)) - { - active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind (); - if (active_row.get() && log) - { - StreamString active_row_strm; - active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str()); - } - } - else - { - m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); - int valid_offset = -1; - if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) - { - active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (valid_offset); - row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); - if (active_row.get() && log) - { - StreamString active_row_strm; - active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str()); - } - } + UnwindLogMsg("initialized frame cfa is 0x%" PRIx64, (uint64_t)m_cfa); + return; } - - if (!active_row.get()) - { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("could not find unwind row for this pc"); - return; + m_frame_type = eNotAValidFrame; + UnwindLogMsg("could not find any symbol for this pc, or a default unwind " + "plan, to continue unwind."); + return; + } + + bool resolve_tail_call_address = false; // m_current_pc can be one past the + // address range of the function... + // If the saved pc does not point to a function/symbol because it is + // beyond the bounds of the correct function and there's no symbol there, + // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1, + // because then we might not find the correct unwind information later. + // Instead, let ResolveSymbolContextForAddress fail, and handle the case + // via decr_pc_and_recompute_addr_range below. + const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; + uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress( + m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address); + + // We require either a symbol or function in the symbols context to be + // successfully + // filled in or this context is of no use to us. + if (resolve_scope & resolved_scope) { + m_sym_ctx_valid = true; + } + + if (m_sym_ctx.symbol) { + UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc, + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + } else if (m_sym_ctx.function) { + UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", pc, + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + } else { + UnwindLogMsg("with pc value of 0x%" PRIx64 + ", no symbol/function name is known.", + pc); + } + + AddressRange addr_range; + if (!m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) { + m_sym_ctx_valid = false; + } + + bool decr_pc_and_recompute_addr_range = false; + + // If the symbol lookup failed... + if (m_sym_ctx_valid == false) + decr_pc_and_recompute_addr_range = true; + + // Or if we're in the middle of the stack (and not "above" an asynchronous + // event like sigtramp), + // and our "current" pc is the start of a function... + if (m_sym_ctx_valid && GetNextFrame()->m_frame_type != eTrapHandlerFrame && + GetNextFrame()->m_frame_type != eDebuggerFrame && + addr_range.GetBaseAddress().IsValid() && + addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && + addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) { + decr_pc_and_recompute_addr_range = true; + } + + // We need to back up the pc by 1 byte and re-search for the Symbol to handle + // the case where the "saved pc" + // value is pointing to the next function, e.g. if a function ends with a CALL + // instruction. + // FIXME this may need to be an architectural-dependent behavior; if so we'll + // need to add a member function + // to the ABI plugin and consult that. + if (decr_pc_and_recompute_addr_range) { + UnwindLogMsg("Backing up the pc value of 0x%" PRIx64 + " by 1 and re-doing symbol lookup; old symbol was %s", + pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + Address temporary_pc; + temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget()); + m_sym_ctx.Clear(false); + m_sym_ctx_valid = false; + uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; + + ModuleSP temporary_module_sp = temporary_pc.GetModule(); + if (temporary_module_sp && + temporary_module_sp->ResolveSymbolContextForAddress( + temporary_pc, resolve_scope, m_sym_ctx) & + resolve_scope) { + if (m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) + m_sym_ctx_valid = true; } + UnwindLogMsg("Symbol is now %s", + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + } + + // If we were able to find a symbol/function, set addr_range_ptr to the bounds + // of that symbol/function. + // else treat the current pc value as the start_pc and record no offset. + if (addr_range.GetBaseAddress().IsValid()) { + m_start_pc = addr_range.GetBaseAddress(); + m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget()); + m_current_offset_backed_up_one = m_current_offset; + if (decr_pc_and_recompute_addr_range && + m_current_offset_backed_up_one > 0) { + m_current_offset_backed_up_one--; + if (m_sym_ctx_valid) { + m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget()); + } + } + } else { + m_start_pc = m_current_pc; + m_current_offset = -1; + m_current_offset_backed_up_one = -1; + } + + if (IsTrapHandlerSymbol(process, m_sym_ctx)) { + m_frame_type = eTrapHandlerFrame; + } else { + // FIXME: Detect eDebuggerFrame here. + if (m_frame_type != eSkipFrame) // don't override eSkipFrame + { + m_frame_type = eNormalFrame; + } + } + + // We've set m_frame_type and m_sym_ctx before this call. + m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame(); + + UnwindPlan::RowSP active_row; + RegisterKind row_register_kind = eRegisterKindGeneric; + + // Try to get by with just the fast UnwindPlan if possible - the full + // UnwindPlan may be expensive to get + // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for + // the first time.) + + if (m_fast_unwind_plan_sp && + m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + active_row = + m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind(); + if (active_row.get() && log) { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, + m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); + UnwindLogMsg("active row: %s", active_row_strm.GetString().c_str()); + } + } else { + m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); + int valid_offset = -1; + if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { + active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset); + row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); + if (active_row.get() && log) { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), + &m_thread, + m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); + UnwindLogMsg("active row: %s", active_row_strm.GetString().c_str()); + } + } + } + + if (!active_row.get()) { + m_frame_type = eNotAValidFrame; + UnwindLogMsg("could not find unwind row for this pc"); + return; + } - if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa)) - { - UnwindLogMsg ("failed to get cfa"); - m_frame_type = eNotAValidFrame; - return; - } + if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) { + UnwindLogMsg("failed to get cfa"); + m_frame_type = eNotAValidFrame; + return; + } - UnwindLogMsg ("m_cfa = 0x%" PRIx64, m_cfa); + UnwindLogMsg("m_cfa = 0x%" PRIx64, m_cfa); - if (CheckIfLoopingStack ()) - { - TryFallbackUnwindPlan(); - if (CheckIfLoopingStack ()) - { - UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); - m_frame_type = eNotAValidFrame; - return; - } + if (CheckIfLoopingStack()) { + TryFallbackUnwindPlan(); + if (CheckIfLoopingStack()) { + UnwindLogMsg("same CFA address as next frame, assuming the unwind is " + "looping - stopping"); + m_frame_type = eNotAValidFrame; + return; } + } - UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64, - (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa); + UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 + " cfa is 0x%" PRIx64, + (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), + (uint64_t)m_cfa); } -bool -RegisterContextLLDB::CheckIfLoopingStack () -{ - // If we have a bad stack setup, we can get the same CFA value multiple times -- or even - // more devious, we can actually oscillate between two CFA values. Detect that here and - // break out to avoid a possible infinite loop in lldb trying to unwind the stack. - // To detect when we have the same CFA value multiple times, we compare the CFA of the current - // frame with the 2nd next frame because in some specail case (e.g. signal hanlders, hand - // written assembly without ABI compiance) we can have 2 frames with the same CFA (in theory we - // can have arbitrary number of frames with the same CFA, but more then 2 is very very unlikely) - - RegisterContextLLDB::SharedPtr next_frame = GetNextFrame(); - if (next_frame) - { - RegisterContextLLDB::SharedPtr next_next_frame = next_frame->GetNextFrame(); - addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; - if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) - { - if (next_next_frame_cfa == m_cfa) - { - // We have a loop in the stack unwind - return true; - } - } +bool RegisterContextLLDB::CheckIfLoopingStack() { + // If we have a bad stack setup, we can get the same CFA value multiple times + // -- or even + // more devious, we can actually oscillate between two CFA values. Detect that + // here and + // break out to avoid a possible infinite loop in lldb trying to unwind the + // stack. + // To detect when we have the same CFA value multiple times, we compare the + // CFA of the current + // frame with the 2nd next frame because in some specail case (e.g. signal + // hanlders, hand + // written assembly without ABI compiance) we can have 2 frames with the same + // CFA (in theory we + // can have arbitrary number of frames with the same CFA, but more then 2 is + // very very unlikely) + + RegisterContextLLDB::SharedPtr next_frame = GetNextFrame(); + if (next_frame) { + RegisterContextLLDB::SharedPtr next_next_frame = next_frame->GetNextFrame(); + addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; + if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) { + if (next_next_frame_cfa == m_cfa) { + // We have a loop in the stack unwind + return true; + } } - return false; -} - -bool -RegisterContextLLDB::IsFrameZero () const -{ - return m_frame_number == 0; + } + return false; } +bool RegisterContextLLDB::IsFrameZero() const { return m_frame_number == 0; } // Find a fast unwind plan for this frame, if possible. // // On entry to this method, // -// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame if either of those are correct, +// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame +// if either of those are correct, // 2. m_sym_ctx should already be filled in, and // 3. m_current_pc should have the current pc value for this frame -// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown +// 4. m_current_offset_backed_up_one should have the current byte offset into +// the function, maybe backed up by 1, -1 if unknown -UnwindPlanSP -RegisterContextLLDB::GetFastUnwindPlanForFrame () -{ - UnwindPlanSP unwind_plan_sp; - ModuleSP pc_module_sp (m_current_pc.GetModule()); +UnwindPlanSP RegisterContextLLDB::GetFastUnwindPlanForFrame() { + UnwindPlanSP unwind_plan_sp; + ModuleSP pc_module_sp(m_current_pc.GetModule()); - if (!m_current_pc.IsValid() || !pc_module_sp || pc_module_sp->GetObjectFile() == NULL) - return unwind_plan_sp; + if (!m_current_pc.IsValid() || !pc_module_sp || + pc_module_sp->GetObjectFile() == NULL) + return unwind_plan_sp; - if (IsFrameZero ()) - return unwind_plan_sp; + if (IsFrameZero()) + return unwind_plan_sp; - FuncUnwindersSP func_unwinders_sp (pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx)); - if (!func_unwinders_sp) - return unwind_plan_sp; + FuncUnwindersSP func_unwinders_sp( + pc_module_sp->GetObjectFile() + ->GetUnwindTable() + .GetFuncUnwindersContainingAddress(m_current_pc, m_sym_ctx)); + if (!func_unwinders_sp) + return unwind_plan_sp; - // If we're in _sigtramp(), unwinding past this frame requires special knowledge. - if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) - return unwind_plan_sp; + // If we're in _sigtramp(), unwinding past this frame requires special + // knowledge. + if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) + return unwind_plan_sp; - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (*m_thread.CalculateTarget(), m_thread); - if (unwind_plan_sp) - { - if (unwind_plan_sp->PlanValidAtAddress (m_current_pc)) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log && log->GetVerbose()) - { - if (m_fast_unwind_plan_sp) - UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan"); - else - UnwindLogMsgVerbose ("frame"); - } - m_frame_type = eNormalFrame; - return unwind_plan_sp; - } + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind( + *m_thread.CalculateTarget(), m_thread); + if (unwind_plan_sp) { + if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) { + if (m_fast_unwind_plan_sp) + UnwindLogMsgVerbose("frame, and has a fast UnwindPlan"); else - { - unwind_plan_sp.reset(); - } - } - return unwind_plan_sp; + UnwindLogMsgVerbose("frame"); + } + m_frame_type = eNormalFrame; + return unwind_plan_sp; + } else { + unwind_plan_sp.reset(); + } + } + return unwind_plan_sp; } // On entry to this method, // -// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame if either of those are correct, +// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame +// if either of those are correct, // 2. m_sym_ctx should already be filled in, and // 3. m_current_pc should have the current pc value for this frame -// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown - -UnwindPlanSP -RegisterContextLLDB::GetFullUnwindPlanForFrame () -{ - UnwindPlanSP unwind_plan_sp; - UnwindPlanSP arch_default_unwind_plan_sp; - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - ABI *abi = process ? process->GetABI().get() : NULL; - if (abi) - { - arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); - } - else - { - UnwindLogMsg ("unable to get architectural default UnwindPlan from ABI plugin"); - } - - bool behaves_like_zeroth_frame = false; - if (IsFrameZero () - || GetNextFrame()->m_frame_type == eTrapHandlerFrame - || GetNextFrame()->m_frame_type == eDebuggerFrame) - { - behaves_like_zeroth_frame = true; - // If this frame behaves like a 0th frame (currently executing or - // interrupted asynchronously), all registers can be retrieved. - m_all_registers_available = true; - } - - // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) so the pc is 0x0 - // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan - // Also, if this Process can report on memory region attributes, any non-executable region means - // we jumped through a bad function pointer - handle the same way as 0x0. - // Note, if we have a symbol context & a symbol, we don't want to follow this code path. This is - // for jumping to memory regions without any information available. - - if ((!m_sym_ctx_valid || (m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) && behaves_like_zeroth_frame && m_current_pc.IsValid()) - { - uint32_t permissions; - addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()); - if (current_pc_addr == 0 - || (process && - process->GetLoadAddressPermissions (current_pc_addr, permissions) - && (permissions & ePermissionsExecutable) == 0)) - { - if (abi) - { - unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); - m_frame_type = eNormalFrame; - return unwind_plan_sp; - } - } - } - - // No Module for the current pc, try using the architecture default unwind. - ModuleSP pc_module_sp (m_current_pc.GetModule()); - if (!m_current_pc.IsValid() || !pc_module_sp || pc_module_sp->GetObjectFile() == NULL) - { +// 4. m_current_offset_backed_up_one should have the current byte offset into +// the function, maybe backed up by 1, -1 if unknown + +UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { + UnwindPlanSP unwind_plan_sp; + UnwindPlanSP arch_default_unwind_plan_sp; + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + ABI *abi = process ? process->GetABI().get() : NULL; + if (abi) { + arch_default_unwind_plan_sp.reset( + new UnwindPlan(lldb::eRegisterKindGeneric)); + abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); + } else { + UnwindLogMsg( + "unable to get architectural default UnwindPlan from ABI plugin"); + } + + bool behaves_like_zeroth_frame = false; + if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame || + GetNextFrame()->m_frame_type == eDebuggerFrame) { + behaves_like_zeroth_frame = true; + // If this frame behaves like a 0th frame (currently executing or + // interrupted asynchronously), all registers can be retrieved. + m_all_registers_available = true; + } + + // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) + // so the pc is 0x0 + // in the zeroth frame, we need to use the "unwind at first instruction" arch + // default UnwindPlan + // Also, if this Process can report on memory region attributes, any + // non-executable region means + // we jumped through a bad function pointer - handle the same way as 0x0. + // Note, if we have a symbol context & a symbol, we don't want to follow this + // code path. This is + // for jumping to memory regions without any information available. + + if ((!m_sym_ctx_valid || + (m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) && + behaves_like_zeroth_frame && m_current_pc.IsValid()) { + uint32_t permissions; + addr_t current_pc_addr = + m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()); + if (current_pc_addr == 0 || + (process && + process->GetLoadAddressPermissions(current_pc_addr, permissions) && + (permissions & ePermissionsExecutable) == 0)) { + if (abi) { + unwind_plan_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); m_frame_type = eNormalFrame; - return arch_default_unwind_plan_sp; - } - - FuncUnwindersSP func_unwinders_sp; - if (m_sym_ctx_valid) - { - func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); - } - - // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its - // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). - // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall - // back to the architectural default unwind. - if (!func_unwinders_sp) - { - m_frame_type = eNormalFrame; - - if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid()) - return arch_default_unwind_plan_sp; - - // Even with -fomit-frame-pointer, we can try eh_frame to get back on track. - DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo(); - if (eh_frame) - { - unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp)) - return unwind_plan_sp; - else - unwind_plan_sp.reset(); - } - - ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo(); - if (arm_exidx) - { - unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp)) - return unwind_plan_sp; - else - unwind_plan_sp.reset(); - } - - return arch_default_unwind_plan_sp; - } - - // If we're in _sigtramp(), unwinding past this frame requires special knowledge. On Mac OS X this knowledge - // is properly encoded in the eh_frame section, so prefer that if available. - // On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of - // how to unwind out of sigtramp. - if (m_frame_type == eTrapHandlerFrame && process) - { - m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) - { - return unwind_plan_sp; - } - } - - // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame even when it's frame zero - // This comes up if we have hand-written functions in a Module and hand-written eh_frame. The assembly - // instruction inspection may fail and the eh_frame CFI were probably written with some care to do the - // right thing. It'd be nice if there was a way to ask the eh_frame directly if it is asynchronous - // (can be trusted at every instruction point) or synchronous (the normal case - only at call sites). - // But there is not. - if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) - { - // We must specifically call the GetEHFrameUnwindPlan() method here -- normally we would - // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind plan sourced from - // either eh_frame (that's what we intend) or compact unwind (this won't work) - unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) - { - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", - unwind_plan_sp->GetSourceName().GetCString()); - return unwind_plan_sp; - } + return unwind_plan_sp; + } } + } - // Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions - if (behaves_like_zeroth_frame && process) - { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) - { - if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) - { - // We probably have an UnwindPlan created by inspecting assembly instructions. The - // assembly profilers work really well with compiler-generated functions but hand- - // written assembly can be problematic. We set the eh_frame based unwind plan as our - // fallback unwind plan if instruction emulation doesn't work out even for non call - // sites if it is available and use the architecture default unwind plan if it is - // not available. The eh_frame unwind plan is more reliable even on non call sites - // then the architecture default plan and for hand written assembly code it is often - // written in a way that it valid at all location what helps in the most common - // cases when the instruction emulation fails. - UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one); - if (call_site_unwind_plan && - call_site_unwind_plan.get() != unwind_plan_sp.get() && - call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) - { - m_fallback_unwind_plan_sp = call_site_unwind_plan; - } - else - { - m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; - } - } - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); - return unwind_plan_sp; - } + // No Module for the current pc, try using the architecture default unwind. + ModuleSP pc_module_sp(m_current_pc.GetModule()); + if (!m_current_pc.IsValid() || !pc_module_sp || + pc_module_sp->GetObjectFile() == NULL) { + m_frame_type = eNormalFrame; + return arch_default_unwind_plan_sp; + } + + FuncUnwindersSP func_unwinders_sp; + if (m_sym_ctx_valid) { + func_unwinders_sp = + pc_module_sp->GetObjectFile() + ->GetUnwindTable() + .GetFuncUnwindersContainingAddress(m_current_pc, m_sym_ctx); + } + + // No FuncUnwinders available for this pc (stripped function symbols, lldb + // could not augment its + // function table with another source, like LC_FUNCTION_STARTS or eh_frame in + // ObjectFileMachO). + // See if eh_frame or the .ARM.exidx tables have unwind information for this + // address, else fall + // back to the architectural default unwind. + if (!func_unwinders_sp) { + m_frame_type = eNormalFrame; + + if (!pc_module_sp || !pc_module_sp->GetObjectFile() || + !m_current_pc.IsValid()) + return arch_default_unwind_plan_sp; + + // Even with -fomit-frame-pointer, we can try eh_frame to get back on track. + DWARFCallFrameInfo *eh_frame = + pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo(); + if (eh_frame) { + unwind_plan_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (eh_frame->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) + return unwind_plan_sp; + else + unwind_plan_sp.reset(); } - // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites - if (process) - { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); - } - int valid_offset = -1; - if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) - { - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); + ArmUnwindInfo *arm_exidx = + pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo(); + if (arm_exidx) { + unwind_plan_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (arm_exidx->GetUnwindPlan(exe_ctx.GetTargetRef(), m_current_pc, + *unwind_plan_sp)) return unwind_plan_sp; + else + unwind_plan_sp.reset(); } - // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've - // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. - if (process) - { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one); - } - if (unwind_plan_sp && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) - { - // We probably have an UnwindPlan created by inspecting assembly instructions. The assembly - // profilers work really well with compiler-generated functions but hand- written assembly - // can be problematic. We set the eh_frame based unwind plan as our fallback unwind plan if - // instruction emulation doesn't work out even for non call sites if it is available and use - // the architecture default unwind plan if it is not available. The eh_frame unwind plan is - // more reliable even on non call sites then the architecture default plan and for hand - // written assembly code it is often written in a way that it valid at all location what - // helps in the most common cases when the instruction emulation fails. - UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one); + return arch_default_unwind_plan_sp; + } + + // If we're in _sigtramp(), unwinding past this frame requires special + // knowledge. On Mac OS X this knowledge + // is properly encoded in the eh_frame section, so prefer that if available. + // On other platforms we may need to provide a platform-specific UnwindPlan + // which encodes the details of + // how to unwind out of sigtramp. + if (m_frame_type == eTrapHandlerFrame && process) { + m_fast_unwind_plan_sp.reset(); + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan( + process->GetTarget(), m_current_offset_backed_up_one); + if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) && + unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { + return unwind_plan_sp; + } + } + + // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame + // even when it's frame zero + // This comes up if we have hand-written functions in a Module and + // hand-written eh_frame. The assembly + // instruction inspection may fail and the eh_frame CFI were probably written + // with some care to do the + // right thing. It'd be nice if there was a way to ask the eh_frame directly + // if it is asynchronous + // (can be trusted at every instruction point) or synchronous (the normal case + // - only at call sites). + // But there is not. + if (process && process->GetDynamicLoader() && + process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) { + // We must specifically call the GetEHFrameUnwindPlan() method here -- + // normally we would + // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind + // plan sourced from + // either eh_frame (that's what we intend) or compact unwind (this won't + // work) + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan( + process->GetTarget(), m_current_offset_backed_up_one); + if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the " + "DynamicLoader suggested we prefer it", + unwind_plan_sp->GetSourceName().GetCString()); + return unwind_plan_sp; + } + } + + // Typically the NonCallSite UnwindPlan is the unwind created by inspecting + // the assembly language instructions + if (behaves_like_zeroth_frame && process) { + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( + process->GetTarget(), m_thread, m_current_offset_backed_up_one); + if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { + if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { + // We probably have an UnwindPlan created by inspecting assembly + // instructions. The + // assembly profilers work really well with compiler-generated functions + // but hand- + // written assembly can be problematic. We set the eh_frame based unwind + // plan as our + // fallback unwind plan if instruction emulation doesn't work out even + // for non call + // sites if it is available and use the architecture default unwind plan + // if it is + // not available. The eh_frame unwind plan is more reliable even on non + // call sites + // then the architecture default plan and for hand written assembly code + // it is often + // written in a way that it valid at all location what helps in the most + // common + // cases when the instruction emulation fails. + UnwindPlanSP call_site_unwind_plan = + func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_current_offset_backed_up_one); if (call_site_unwind_plan && call_site_unwind_plan.get() != unwind_plan_sp.get() && - call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) - { - m_fallback_unwind_plan_sp = call_site_unwind_plan; - } - else - { - m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + call_site_unwind_plan->GetSourceName() != + unwind_plan_sp->GetSourceName()) { + m_fallback_unwind_plan_sp = call_site_unwind_plan; + } else { + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; } - } - - if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) - { - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); - return unwind_plan_sp; - } - - // If we're on the first instruction of a function, and we have an architectural default UnwindPlan - // for the initial instruction of a function, use that. - if (m_current_offset_backed_up_one == 0) - { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry (m_thread); - if (unwind_plan_sp) - { - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); - return unwind_plan_sp; - } - } - - // If nothing else, use the architectural default UnwindPlan and hope that does the job. - if (arch_default_unwind_plan_sp) - UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString()); - else - UnwindLogMsg ("Unable to find any UnwindPlan for full unwind of this frame."); - - return arch_default_unwind_plan_sp; + } + UnwindLogMsgVerbose("frame uses %s for full UnwindPlan", + unwind_plan_sp->GetSourceName().GetCString()); + return unwind_plan_sp; + } + } + + // Typically this is unwind info from an eh_frame section intended for + // exception handling; only valid at call sites + if (process) { + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_current_offset_backed_up_one); + } + int valid_offset = -1; + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { + UnwindLogMsgVerbose("frame uses %s for full UnwindPlan", + unwind_plan_sp->GetSourceName().GetCString()); + return unwind_plan_sp; + } + + // We'd prefer to use an UnwindPlan intended for call sites when we're at a + // call site but if we've + // struck out on that, fall back to using the non-call-site assembly + // inspection UnwindPlan if possible. + if (process) { + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite( + process->GetTarget(), m_thread, m_current_offset_backed_up_one); + } + if (unwind_plan_sp && + unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { + // We probably have an UnwindPlan created by inspecting assembly + // instructions. The assembly + // profilers work really well with compiler-generated functions but hand- + // written assembly + // can be problematic. We set the eh_frame based unwind plan as our fallback + // unwind plan if + // instruction emulation doesn't work out even for non call sites if it is + // available and use + // the architecture default unwind plan if it is not available. The eh_frame + // unwind plan is + // more reliable even on non call sites then the architecture default plan + // and for hand + // written assembly code it is often written in a way that it valid at all + // location what + // helps in the most common cases when the instruction emulation fails. + UnwindPlanSP call_site_unwind_plan = + func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_current_offset_backed_up_one); + if (call_site_unwind_plan && + call_site_unwind_plan.get() != unwind_plan_sp.get() && + call_site_unwind_plan->GetSourceName() != + unwind_plan_sp->GetSourceName()) { + m_fallback_unwind_plan_sp = call_site_unwind_plan; + } else { + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + } + } + + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { + UnwindLogMsgVerbose("frame uses %s for full UnwindPlan", + unwind_plan_sp->GetSourceName().GetCString()); + return unwind_plan_sp; + } + + // If we're on the first instruction of a function, and we have an + // architectural default UnwindPlan + // for the initial instruction of a function, use that. + if (m_current_offset_backed_up_one == 0) { + unwind_plan_sp = + func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry( + m_thread); + if (unwind_plan_sp) { + UnwindLogMsgVerbose("frame uses %s for full UnwindPlan", + unwind_plan_sp->GetSourceName().GetCString()); + return unwind_plan_sp; + } + } + + // If nothing else, use the architectural default UnwindPlan and hope that + // does the job. + if (arch_default_unwind_plan_sp) + UnwindLogMsgVerbose( + "frame uses %s for full UnwindPlan", + arch_default_unwind_plan_sp->GetSourceName().GetCString()); + else + UnwindLogMsg( + "Unable to find any UnwindPlan for full unwind of this frame."); + + return arch_default_unwind_plan_sp; } - -void -RegisterContextLLDB::InvalidateAllRegisters () -{ - m_frame_type = eNotAValidFrame; +void RegisterContextLLDB::InvalidateAllRegisters() { + m_frame_type = eNotAValidFrame; } -size_t -RegisterContextLLDB::GetRegisterCount () -{ - return m_thread.GetRegisterContext()->GetRegisterCount(); +size_t RegisterContextLLDB::GetRegisterCount() { + return m_thread.GetRegisterContext()->GetRegisterCount(); } -const RegisterInfo * -RegisterContextLLDB::GetRegisterInfoAtIndex (size_t reg) -{ - return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg); +const RegisterInfo *RegisterContextLLDB::GetRegisterInfoAtIndex(size_t reg) { + return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); } -size_t -RegisterContextLLDB::GetRegisterSetCount () -{ - return m_thread.GetRegisterContext()->GetRegisterSetCount (); +size_t RegisterContextLLDB::GetRegisterSetCount() { + return m_thread.GetRegisterContext()->GetRegisterSetCount(); } -const RegisterSet * -RegisterContextLLDB::GetRegisterSet (size_t reg_set) -{ - return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); +const RegisterSet *RegisterContextLLDB::GetRegisterSet(size_t reg_set) { + return m_thread.GetRegisterContext()->GetRegisterSet(reg_set); } -uint32_t -RegisterContextLLDB::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); +uint32_t RegisterContextLLDB::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + kind, num); } -bool -RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, - const RegisterInfo *reg_info, - RegisterValue &value) -{ - if (!IsValid()) - return false; - bool success = false; - - switch (regloc.type) - { - case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: - { - const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - - if (!other_reg_info) - return false; - - success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value); - } - break; - case UnwindLLDB::RegisterLocation::eRegisterInRegister: - { - const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - - if (!other_reg_info) - return false; - - if (IsFrameZero ()) - { - success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value); - } - else - { - success = GetNextFrame()->ReadRegister (other_reg_info, value); - } - } - break; - case UnwindLLDB::RegisterLocation::eRegisterValueInferred: - success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size); - break; - - case UnwindLLDB::RegisterLocation::eRegisterNotSaved: - break; - case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: - assert ("FIXME debugger inferior function call unwind"); - break; - case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: - { - Error error (ReadRegisterValueFromMemory(reg_info, - regloc.location.target_memory_location, - reg_info->byte_size, - value)); - success = error.Success(); - } - break; - default: - assert ("Unknown RegisterLocation type."); - break; - } - return success; +bool RegisterContextLLDB::ReadRegisterValueFromRegisterLocation( + lldb_private::UnwindLLDB::RegisterLocation regloc, + const RegisterInfo *reg_info, RegisterValue &value) { + if (!IsValid()) + return false; + bool success = false; + + switch (regloc.type) { + case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { + const RegisterInfo *other_reg_info = + GetRegisterInfoAtIndex(regloc.location.register_number); + + if (!other_reg_info) + return false; + + success = + m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); + } break; + case UnwindLLDB::RegisterLocation::eRegisterInRegister: { + const RegisterInfo *other_reg_info = + GetRegisterInfoAtIndex(regloc.location.register_number); + + if (!other_reg_info) + return false; + + if (IsFrameZero()) { + success = + m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value); + } else { + success = GetNextFrame()->ReadRegister(other_reg_info, value); + } + } break; + case UnwindLLDB::RegisterLocation::eRegisterValueInferred: + success = + value.SetUInt(regloc.location.inferred_value, reg_info->byte_size); + break; + + case UnwindLLDB::RegisterLocation::eRegisterNotSaved: + break; + case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: + assert("FIXME debugger inferior function call unwind"); + break; + case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { + Error error(ReadRegisterValueFromMemory( + reg_info, regloc.location.target_memory_location, reg_info->byte_size, + value)); + success = error.Success(); + } break; + default: + assert("Unknown RegisterLocation type."); + break; + } + return success; } -bool -RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, - const RegisterInfo *reg_info, - const RegisterValue &value) -{ - if (!IsValid()) - return false; - - bool success = false; +bool RegisterContextLLDB::WriteRegisterValueToRegisterLocation( + lldb_private::UnwindLLDB::RegisterLocation regloc, + const RegisterInfo *reg_info, const RegisterValue &value) { + if (!IsValid()) + return false; - switch (regloc.type) - { - case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: - { - const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value); - } - break; - case UnwindLLDB::RegisterLocation::eRegisterInRegister: - { - const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - if (IsFrameZero ()) - { - success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value); - } - else - { - success = GetNextFrame()->WriteRegister (other_reg_info, value); - } - } - break; - case UnwindLLDB::RegisterLocation::eRegisterValueInferred: - case UnwindLLDB::RegisterLocation::eRegisterNotSaved: - break; - case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: - assert ("FIXME debugger inferior function call unwind"); - break; - case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: - { - Error error (WriteRegisterValueToMemory (reg_info, - regloc.location.target_memory_location, - reg_info->byte_size, - value)); - success = error.Success(); - } - break; - default: - assert ("Unknown RegisterLocation type."); - break; - } - return success; + bool success = false; + + switch (regloc.type) { + case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: { + const RegisterInfo *other_reg_info = + GetRegisterInfoAtIndex(regloc.location.register_number); + success = + m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); + } break; + case UnwindLLDB::RegisterLocation::eRegisterInRegister: { + const RegisterInfo *other_reg_info = + GetRegisterInfoAtIndex(regloc.location.register_number); + if (IsFrameZero()) { + success = + m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value); + } else { + success = GetNextFrame()->WriteRegister(other_reg_info, value); + } + } break; + case UnwindLLDB::RegisterLocation::eRegisterValueInferred: + case UnwindLLDB::RegisterLocation::eRegisterNotSaved: + break; + case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: + assert("FIXME debugger inferior function call unwind"); + break; + case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { + Error error(WriteRegisterValueToMemory( + reg_info, regloc.location.target_memory_location, reg_info->byte_size, + value)); + success = error.Success(); + } break; + default: + assert("Unknown RegisterLocation type."); + break; + } + return success; } - -bool -RegisterContextLLDB::IsValid () const -{ - return m_frame_type != eNotAValidFrame; +bool RegisterContextLLDB::IsValid() const { + return m_frame_type != eNotAValidFrame; } -// After the final stack frame in a stack walk we'll get one invalid (eNotAValidFrame) stack frame -- -// one past the end of the stack walk. But higher-level code will need to tell the differnece between -// "the unwind plan below this frame failed" versus "we successfully completed the stack walk" so +// After the final stack frame in a stack walk we'll get one invalid +// (eNotAValidFrame) stack frame -- +// one past the end of the stack walk. But higher-level code will need to tell +// the differnece between +// "the unwind plan below this frame failed" versus "we successfully completed +// the stack walk" so // this method helps to disambiguate that. -bool -RegisterContextLLDB::IsTrapHandlerFrame () const -{ - return m_frame_type == eTrapHandlerFrame; +bool RegisterContextLLDB::IsTrapHandlerFrame() const { + return m_frame_type == eTrapHandlerFrame; } -// A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther -// up the stack if we keep looking. It's always the second frame in an unwind (i.e. the first frame after -// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this frame in some way so the -// user knows we're displaying bad data and we may have skipped one frame of their real program in the +// A skip frame is a bogus frame on the stack -- but one where we're likely to +// find a real frame farther +// up the stack if we keep looking. It's always the second frame in an unwind +// (i.e. the first frame after +// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this +// frame in some way so the +// user knows we're displaying bad data and we may have skipped one frame of +// their real program in the // process of getting back on track. -bool -RegisterContextLLDB::IsSkipFrame () const -{ - return m_frame_type == eSkipFrame; +bool RegisterContextLLDB::IsSkipFrame() const { + return m_frame_type == eSkipFrame; } -bool -RegisterContextLLDB::IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const -{ - PlatformSP platform_sp (process->GetTarget().GetPlatform()); - if (platform_sp) - { - const std::vector<ConstString> trap_handler_names (platform_sp->GetTrapHandlerSymbolNames()); - for (ConstString name : trap_handler_names) - { - if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || - (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) - { - return true; - } - } +bool RegisterContextLLDB::IsTrapHandlerSymbol( + lldb_private::Process *process, + const lldb_private::SymbolContext &m_sym_ctx) const { + PlatformSP platform_sp(process->GetTarget().GetPlatform()); + if (platform_sp) { + const std::vector<ConstString> trap_handler_names( + platform_sp->GetTrapHandlerSymbolNames()); + for (ConstString name : trap_handler_names) { + if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || + (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { + return true; + } } - const std::vector<ConstString> user_specified_trap_handler_names (m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames()); - for (ConstString name : user_specified_trap_handler_names) - { - if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || - (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) - { - return true; - } - } + } + const std::vector<ConstString> user_specified_trap_handler_names( + m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames()); + for (ConstString name : user_specified_trap_handler_names) { + if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) || + (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) { + return true; + } + } - return false; + return false; } -// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value? +// Answer the question: Where did THIS frame save the CALLER frame ("previous" +// frame)'s register value? enum UnwindLLDB::RegisterSearchResult -RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) -{ - RegisterNumber regnum (m_thread, eRegisterKindLLDB, lldb_regnum); - - // Have we already found this register location? - if (!m_registers.empty()) - { - std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>::const_iterator iterator; - iterator = m_registers.find (regnum.GetAsKind (eRegisterKindLLDB)); - if (iterator != m_registers.end()) - { - regloc = iterator->second; - UnwindLogMsg ("supplying caller's saved %s (%d)'s location, cached", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; +RegisterContextLLDB::SavedLocationForRegister( + uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { + RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum); + + // Have we already found this register location? + if (!m_registers.empty()) { + std::map<uint32_t, + lldb_private::UnwindLLDB::RegisterLocation>::const_iterator + iterator; + iterator = m_registers.find(regnum.GetAsKind(eRegisterKindLLDB)); + if (iterator != m_registers.end()) { + regloc = iterator->second; + UnwindLogMsg("supplying caller's saved %s (%d)'s location, cached", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + } + + // Look through the available UnwindPlans for the register location. + + UnwindPlan::Row::RegisterLocation unwindplan_regloc; + bool have_unwindplan_regloc = false; + RegisterKind unwindplan_registerkind = kNumRegisterKinds; + + if (m_fast_unwind_plan_sp) { + UnwindPlan::RowSP active_row = + m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind(); + if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { + UnwindLogMsg("could not convert lldb regnum %s (%d) into %d RegisterKind " + "reg numbering scheme", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), + (int)unwindplan_registerkind); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } + if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), + unwindplan_regloc)) { + UnwindLogMsg( + "supplying caller's saved %s (%d)'s location using FastUnwindPlan", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + have_unwindplan_regloc = true; + } + } + + if (!have_unwindplan_regloc) { + // m_full_unwind_plan_sp being NULL means that we haven't tried to find a + // full UnwindPlan yet + if (!m_full_unwind_plan_sp) + m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); + + if (m_full_unwind_plan_sp) { + RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + + UnwindPlan::RowSP active_row = + m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); + + RegisterNumber return_address_reg; + + // If we're fetching the saved pc and this UnwindPlan defines a + // ReturnAddress register (e.g. lr on arm), + // look for the return address register number in the UnwindPlan's row. + if (pc_regnum.IsValid() && pc_regnum == regnum && + m_full_unwind_plan_sp->GetReturnAddressRegister() != + LLDB_INVALID_REGNUM) { + + return_address_reg.init( + m_thread, m_full_unwind_plan_sp->GetRegisterKind(), + m_full_unwind_plan_sp->GetReturnAddressRegister()); + regnum = return_address_reg; + UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a " + "RA reg; getting %s (%d) instead", + return_address_reg.GetName(), + return_address_reg.GetAsKind(eRegisterKindLLDB)); + } else { + if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) { + if (unwindplan_registerkind == eRegisterKindGeneric) { + UnwindLogMsg("could not convert lldb regnum %s (%d) into " + "eRegisterKindGeneric reg numbering scheme", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + } else { + UnwindLogMsg("could not convert lldb regnum %s (%d) into %d " + "RegisterKind reg numbering scheme", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), + (int)unwindplan_registerkind); + } + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } - } - - // Look through the available UnwindPlans for the register location. - - UnwindPlan::Row::RegisterLocation unwindplan_regloc; - bool have_unwindplan_regloc = false; - RegisterKind unwindplan_registerkind = kNumRegisterKinds; - - if (m_fast_unwind_plan_sp) - { - UnwindPlan::RowSP active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind (); - if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM) - { - UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - if (active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) - { - UnwindLogMsg ("supplying caller's saved %s (%d)'s location using FastUnwindPlan", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - have_unwindplan_regloc = true; + } + + if (regnum.IsValid() && + active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), + unwindplan_regloc)) { + have_unwindplan_regloc = true; + UnwindLogMsg( + "supplying caller's saved %s (%d)'s location using %s UnwindPlan", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), + m_full_unwind_plan_sp->GetSourceName().GetCString()); + } + + // This is frame 0 and we're retrieving the PC and it's saved in a Return + // Address register and + // it hasn't been saved anywhere yet -- that is, it's still live in the + // actual register. + // Handle this specially. + + if (have_unwindplan_regloc == false && return_address_reg.IsValid() && + IsFrameZero()) { + if (return_address_reg.GetAsKind(eRegisterKindLLDB) != + LLDB_INVALID_REGNUM) { + lldb_private::UnwindLLDB::RegisterLocation new_regloc; + new_regloc.type = + UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; + new_regloc.location.register_number = + return_address_reg.GetAsKind(eRegisterKindLLDB); + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; + regloc = new_regloc; + UnwindLogMsg("supplying caller's register %s (%d) from the live " + "RegisterContext at frame 0, saved in %d", + return_address_reg.GetName(), + return_address_reg.GetAsKind(eRegisterKindLLDB), + return_address_reg.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; } - } - - if (!have_unwindplan_regloc) - { - // m_full_unwind_plan_sp being NULL means that we haven't tried to find a full UnwindPlan yet - if (!m_full_unwind_plan_sp) - m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); - - if (m_full_unwind_plan_sp) - { - RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - - UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind (); - - RegisterNumber return_address_reg; - - // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm), - // look for the return address register number in the UnwindPlan's row. - if (pc_regnum.IsValid() - && pc_regnum == regnum - && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) - { - - return_address_reg.init (m_thread, m_full_unwind_plan_sp->GetRegisterKind(), m_full_unwind_plan_sp->GetReturnAddressRegister()); - regnum = return_address_reg; - UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting %s (%d) instead", - return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB)); - } - else - { - if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM) - { - if (unwindplan_registerkind == eRegisterKindGeneric) - { - UnwindLogMsg ("could not convert lldb regnum %s (%d) into eRegisterKindGeneric reg numbering scheme", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - } - else - { - UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind); - } - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } + } + + // If this architecture stores the return address in a register (it + // defines a Return Address register) + // and we're on a non-zero stack frame and the Full UnwindPlan says that + // the pc is stored in the + // RA registers (e.g. lr on arm), then we know that the full unwindplan is + // not trustworthy -- this + // is an impossible situation and the instruction emulation code has + // likely been misled. + // If this stack frame meets those criteria, we need to throw away the + // Full UnwindPlan that the + // instruction emulation came up with and fall back to the architecture's + // Default UnwindPlan so + // the stack walk can get past this point. + + // Special note: If the Full UnwindPlan was generated from the compiler, + // don't second-guess it + // when we're at a call site location. + + // arch_default_ra_regnum is the return address register # in the Full + // UnwindPlan register numbering + RegisterNumber arch_default_ra_regnum(m_thread, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA); + + if (arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) != + LLDB_INVALID_REGNUM && + pc_regnum == regnum && unwindplan_regloc.IsInOtherRegister() && + unwindplan_regloc.GetRegisterNumber() == + arch_default_ra_regnum.GetAsKind(unwindplan_registerkind) && + m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes && + !m_all_registers_available) { + UnwindLogMsg("%s UnwindPlan tried to restore the pc from the link " + "register but this is a non-zero frame", + m_full_unwind_plan_sp->GetSourceName().GetCString()); + + // Throw away the full unwindplan; install the arch default unwindplan + if (ForceSwitchToFallbackUnwindPlan()) { + // Update for the possibly new unwind plan + unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); + UnwindPlan::RowSP active_row = + m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + + // Sanity check: Verify that we can fetch a pc value and CFA value + // with this unwind plan + + RegisterNumber arch_default_pc_reg(m_thread, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + bool can_fetch_pc_value = false; + bool can_fetch_cfa = false; + addr_t cfa_value; + if (active_row) { + if (arch_default_pc_reg.GetAsKind(unwindplan_registerkind) != + LLDB_INVALID_REGNUM && + active_row->GetRegisterInfo( + arch_default_pc_reg.GetAsKind(unwindplan_registerkind), + unwindplan_regloc)) { + can_fetch_pc_value = true; } - - if (regnum.IsValid() - && active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) - { - have_unwindplan_regloc = true; - UnwindLogMsg ("supplying caller's saved %s (%d)'s location using %s UnwindPlan", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - m_full_unwind_plan_sp->GetSourceName().GetCString()); - } - - // This is frame 0 and we're retrieving the PC and it's saved in a Return Address register and - // it hasn't been saved anywhere yet -- that is, it's still live in the actual register. - // Handle this specially. - - if (have_unwindplan_regloc == false - && return_address_reg.IsValid() - && IsFrameZero()) - { - if (return_address_reg.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM) - { - lldb_private::UnwindLLDB::RegisterLocation new_regloc; - new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; - new_regloc.location.register_number = return_address_reg.GetAsKind (eRegisterKindLLDB); - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; - regloc = new_regloc; - UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0, saved in %d", - return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB), - return_address_reg.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - } - - // If this architecture stores the return address in a register (it defines a Return Address register) - // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the - // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this - // is an impossible situation and the instruction emulation code has likely been misled. - // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the - // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so - // the stack walk can get past this point. - - // Special note: If the Full UnwindPlan was generated from the compiler, don't second-guess it - // when we're at a call site location. - - // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering - RegisterNumber arch_default_ra_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); - - if (arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM - && pc_regnum == regnum - && unwindplan_regloc.IsInOtherRegister() - && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) - && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes - && !m_all_registers_available) - { - UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame", - m_full_unwind_plan_sp->GetSourceName().GetCString()); - - // Throw away the full unwindplan; install the arch default unwindplan - if (ForceSwitchToFallbackUnwindPlan()) - { - // Update for the possibly new unwind plan - unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind (); - UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - - // Sanity check: Verify that we can fetch a pc value and CFA value with this unwind plan - - RegisterNumber arch_default_pc_reg (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - bool can_fetch_pc_value = false; - bool can_fetch_cfa = false; - addr_t cfa_value; - if (active_row) - { - if (arch_default_pc_reg.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM - && active_row->GetRegisterInfo (arch_default_pc_reg.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) - { - can_fetch_pc_value = true; - } - if (ReadCFAValueForRow (unwindplan_registerkind, active_row, cfa_value)) - { - can_fetch_cfa = true; - } - } - - if (can_fetch_pc_value && can_fetch_cfa) - { - have_unwindplan_regloc = true; - } - else - { - have_unwindplan_regloc = false; - } - } - else - { - // We were unable to fall back to another unwind plan - have_unwindplan_regloc = false; - } + if (ReadCFAValueForRow(unwindplan_registerkind, active_row, + cfa_value)) { + can_fetch_cfa = true; } - } - } + } - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - if (have_unwindplan_regloc == false) - { - // If the UnwindPlan failed to give us an unwind location for this register, we may be able to fall back - // to some ABI-defined default. For example, some ABIs allow to determine the caller's SP via the CFA. - // Also, the ABI may set volatile registers to the undefined state. - ABI *abi = process ? process->GetABI().get() : NULL; - if (abi) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB)); - if (reg_info && abi->GetFallbackRegisterLocation (reg_info, unwindplan_regloc)) - { - UnwindLogMsg ("supplying caller's saved %s (%d)'s location using ABI default", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - have_unwindplan_regloc = true; - } - } - } - - if (have_unwindplan_regloc == false) - { - if (IsFrameZero ()) - { - // This is frame 0 - we should return the actual live register context value - lldb_private::UnwindLLDB::RegisterLocation new_regloc; - new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; - new_regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; - regloc = new_regloc; - UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - else - { - std::string unwindplan_name (""); - if (m_full_unwind_plan_sp) - { - unwindplan_name += "via '"; - unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString(); - unwindplan_name += "'"; - } - UnwindLogMsg ("no save location for %s (%d) %s", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - unwindplan_name.c_str()); - } - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - - // unwindplan_regloc has valid contents about where to retrieve the register - if (unwindplan_regloc.IsUnspecified()) - { - lldb_private::UnwindLLDB::RegisterLocation new_regloc; - new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; - UnwindLogMsg ("save location for %s (%d) is unspecified, continue searching", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - - if (unwindplan_regloc.IsUndefined()) - { - UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; - } - - if (unwindplan_regloc.IsSame()) - { - if (IsFrameZero() == false - && (regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC - || regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) - { - UnwindLogMsg ("register %s (%d) is marked as 'IsSame' - it is a pc or return address reg on a non-zero frame -- treat as if we have no information", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - else - { - regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; + if (can_fetch_pc_value && can_fetch_cfa) { + have_unwindplan_regloc = true; + } else { + have_unwindplan_regloc = false; + } + } else { + // We were unable to fall back to another unwind plan + have_unwindplan_regloc = false; } + } + } + } + + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + if (have_unwindplan_regloc == false) { + // If the UnwindPlan failed to give us an unwind location for this register, + // we may be able to fall back + // to some ABI-defined default. For example, some ABIs allow to determine + // the caller's SP via the CFA. + // Also, the ABI may set volatile registers to the undefined state. + ABI *abi = process ? process->GetABI().get() : NULL; + if (abi) { + const RegisterInfo *reg_info = + GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB)); + if (reg_info && + abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) { + UnwindLogMsg( + "supplying caller's saved %s (%d)'s location using ABI default", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + have_unwindplan_regloc = true; + } + } + } + + if (have_unwindplan_regloc == false) { + if (IsFrameZero()) { + // This is frame 0 - we should return the actual live register context + // value + lldb_private::UnwindLLDB::RegisterLocation new_regloc; + new_regloc.type = + UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; + new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; + regloc = new_regloc; + UnwindLogMsg("supplying caller's register %s (%d) from the live " + "RegisterContext at frame 0", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } else { + std::string unwindplan_name(""); + if (m_full_unwind_plan_sp) { + unwindplan_name += "via '"; + unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString(); + unwindplan_name += "'"; + } + UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(), + regnum.GetAsKind(eRegisterKindLLDB), + unwindplan_name.c_str()); } - - if (unwindplan_regloc.IsCFAPlusOffset()) - { - int offset = unwindplan_regloc.GetOffset(); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } + + // unwindplan_regloc has valid contents about where to retrieve the register + if (unwindplan_regloc.IsUnspecified()) { + lldb_private::UnwindLLDB::RegisterLocation new_regloc; + new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; + UnwindLogMsg("save location for %s (%d) is unspecified, continue searching", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } + + if (unwindplan_regloc.IsUndefined()) { + UnwindLogMsg( + "did not supply reg location for %s (%d) because it is volatile", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; + } + + if (unwindplan_regloc.IsSame()) { + if (IsFrameZero() == false && + (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC || + regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) { + UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or " + "return address reg on a non-zero frame -- treat as if we " + "have no information", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } else { + regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; + regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg( + "supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + } + + if (unwindplan_regloc.IsCFAPlusOffset()) { + int offset = unwindplan_regloc.GetOffset(); + regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; + regloc.location.inferred_value = m_cfa + offset; + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg("supplying caller's register %s (%d), value is CFA plus " + "offset %d [value is 0x%" PRIx64 "]", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, + regloc.location.inferred_value); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + + if (unwindplan_regloc.IsAtCFAPlusOffset()) { + int offset = unwindplan_regloc.GetOffset(); + regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; + regloc.location.target_memory_location = m_cfa + offset; + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " + "CFA plus offset %d [saved at 0x%" PRIx64 "]", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, + regloc.location.target_memory_location); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + + if (unwindplan_regloc.IsInOtherRegister()) { + uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber(); + RegisterNumber row_regnum(m_thread, unwindplan_registerkind, + unwindplan_regnum); + if (row_regnum.GetAsKind(eRegisterKindLLDB) == LLDB_INVALID_REGNUM) { + UnwindLogMsg("could not supply caller's %s (%d) location - was saved in " + "another reg but couldn't convert that regnum", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } + regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; + regloc.location.register_number = row_regnum.GetAsKind(eRegisterKindLLDB); + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg( + "supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), + row_regnum.GetName(), row_regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + + if (unwindplan_regloc.IsDWARFExpression() || + unwindplan_regloc.IsAtDWARFExpression()) { + DataExtractor dwarfdata(unwindplan_regloc.GetDWARFExpressionBytes(), + unwindplan_regloc.GetDWARFExpressionLength(), + process->GetByteOrder(), + process->GetAddressByteSize()); + ModuleSP opcode_ctx; + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, + unwindplan_regloc.GetDWARFExpressionLength()); + dwarfexpr.SetRegisterKind(unwindplan_registerkind); + Value result; + Error error; + if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, + nullptr, result, &error)) { + addr_t val; + val = result.GetScalar().ULongLong(); + if (unwindplan_regloc.IsDWARFExpression()) { regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; - regloc.location.inferred_value = m_cfa + offset; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d), value is CFA plus offset %d [value is 0x%" PRIx64 "]", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - offset, regloc.location.inferred_value); + regloc.location.inferred_value = val; + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " + "(IsDWARFExpression)", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - - if (unwindplan_regloc.IsAtCFAPlusOffset()) - { - int offset = unwindplan_regloc.GetOffset(); - regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; - regloc.location.target_memory_location = m_cfa + offset; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d) from the stack, saved at CFA plus offset %d [saved at 0x%" PRIx64 "]", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - offset, regloc.location.target_memory_location); + } else { + regloc.type = + UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; + regloc.location.target_memory_location = val; + m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; + UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression " + "(IsAtDWARFExpression)", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } } + UnwindLogMsg("tried to use IsDWARFExpression or IsAtDWARFExpression for %s " + "(%d) but failed", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } - if (unwindplan_regloc.IsInOtherRegister()) - { - uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber(); - RegisterNumber row_regnum (m_thread, unwindplan_registerkind, unwindplan_regnum); - if (row_regnum.GetAsKind (eRegisterKindLLDB) == LLDB_INVALID_REGNUM) - { - UnwindLogMsg ("could not supply caller's %s (%d) location - was saved in another reg but couldn't convert that regnum", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - regloc.location.register_number = row_regnum.GetAsKind (eRegisterKindLLDB); - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - row_regnum.GetName(), row_regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - - if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression()) - { - DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), - unwindplan_regloc.GetDWARFExpressionLength(), - process->GetByteOrder(), process->GetAddressByteSize()); - ModuleSP opcode_ctx; - DWARFExpression dwarfexpr (opcode_ctx, - dwarfdata, - nullptr, - 0, - unwindplan_regloc.GetDWARFExpressionLength()); - dwarfexpr.SetRegisterKind (unwindplan_registerkind); - Value result; - Error error; - if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error)) - { - addr_t val; - val = result.GetScalar().ULongLong(); - if (unwindplan_regloc.IsDWARFExpression()) - { - regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; - regloc.location.inferred_value = val; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsDWARFExpression)", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - else - { - regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; - regloc.location.target_memory_location = val; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsAtDWARFExpression)", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - } - UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for %s (%d) but failed", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - - UnwindLogMsg ("no save location for %s (%d) in this stack frame", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + UnwindLogMsg("no save location for %s (%d) in this stack frame", + regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); - // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported. + // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are + // unsupported. - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } // TryFallbackUnwindPlan() -- this method is a little tricky. -// -// When this is called, the frame above -- the caller frame, the "previous" frame -- -// is invalid or bad. // -// Instead of stopping the stack walk here, we'll try a different UnwindPlan and see -// if we can get a valid frame above us. +// When this is called, the frame above -- the caller frame, the "previous" +// frame -- +// is invalid or bad. +// +// Instead of stopping the stack walk here, we'll try a different UnwindPlan and +// see +// if we can get a valid frame above us. // -// This most often happens when an unwind plan based on assembly instruction inspection -// is not correct -- mostly with hand-written assembly functions or functions where the -// stack frame is set up "out of band", e.g. the kernel saved the register context and +// This most often happens when an unwind plan based on assembly instruction +// inspection +// is not correct -- mostly with hand-written assembly functions or functions +// where the +// stack frame is set up "out of band", e.g. the kernel saved the register +// context and // then called an asynchronous trap handler like _sigtramp. // -// Often in these cases, if we just do a dumb stack walk we'll get past this tricky +// Often in these cases, if we just do a dumb stack walk we'll get past this +// tricky // frame and our usual techniques can continue to be used. -bool -RegisterContextLLDB::TryFallbackUnwindPlan () -{ - if (m_fallback_unwind_plan_sp.get() == nullptr) - return false; - - if (m_full_unwind_plan_sp.get() == nullptr) - return false; - - if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() - || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName()) - { - return false; - } +bool RegisterContextLLDB::TryFallbackUnwindPlan() { + if (m_fallback_unwind_plan_sp.get() == nullptr) + return false; - // If a compiler generated unwind plan failed, trying the arch default unwindplan - // isn't going to do any better. - if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) - return false; + if (m_full_unwind_plan_sp.get() == nullptr) + return false; + if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || + m_full_unwind_plan_sp->GetSourceName() == + m_fallback_unwind_plan_sp->GetSourceName()) { + return false; + } - // Get the caller's pc value and our own CFA value. - // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA value. - // If they're the same, then the fallback unwind plan provides no benefit. + // If a compiler generated unwind plan failed, trying the arch default + // unwindplan + // isn't going to do any better. + if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) + return false; - RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + // Get the caller's pc value and our own CFA value. + // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA + // value. + // If they're the same, then the fallback unwind plan provides no benefit. + + RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC); + + addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS; + addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS; + addr_t old_this_frame_cfa_value = m_cfa; + UnwindLLDB::RegisterLocation regloc; + if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), + regloc) == + UnwindLLDB::RegisterSearchResult::eRegisterFound) { + const RegisterInfo *reg_info = + GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); + if (reg_info) { + RegisterValue reg_value; + if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { + old_caller_pc_value = reg_value.GetAsUInt64(); + } + } + } + + // This is a tricky wrinkle! If SavedLocationForRegister() detects a really + // impossible + // register location for the full unwind plan, it may call + // ForceSwitchToFallbackUnwindPlan() + // which in turn replaces the full unwindplan with the fallback... in short, + // we're done, + // we're using the fallback UnwindPlan. + // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only + // way it + // became nullptr since then is via SavedLocationForRegister(). + if (m_fallback_unwind_plan_sp.get() == nullptr) + return true; - addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS; - addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS; - addr_t old_this_frame_cfa_value = m_cfa; - UnwindLLDB::RegisterLocation regloc; - if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB)); - if (reg_info) - { - RegisterValue reg_value; - if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value)) - { - old_caller_pc_value = reg_value.GetAsUInt64(); - } + // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide + // this isn't + // working, we need to restore. + // We'll also need to save & restore the value of the m_cfa ivar. Save is + // down below a bit in 'old_cfa'. + UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; + addr_t old_cfa = m_cfa; + + m_registers.clear(); + + m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; + + UnwindPlan::RowSP active_row = + m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); + + if (active_row && + active_row->GetCFAValue().GetValueType() != + UnwindPlan::Row::CFAValue::unspecified) { + addr_t new_cfa; + if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), + active_row, new_cfa) || + new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { + UnwindLogMsg("failed to get cfa with fallback unwindplan"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } + m_cfa = new_cfa; + + if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB), + regloc) == + UnwindLLDB::RegisterSearchResult::eRegisterFound) { + const RegisterInfo *reg_info = + GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB)); + if (reg_info) { + RegisterValue reg_value; + if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, + reg_value)) { + new_caller_pc_value = reg_value.GetAsUInt64(); } + } } - // This is a tricky wrinkle! If SavedLocationForRegister() detects a really impossible - // register location for the full unwind plan, it may call ForceSwitchToFallbackUnwindPlan() - // which in turn replaces the full unwindplan with the fallback... in short, we're done, - // we're using the fallback UnwindPlan. - // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only way it - // became nullptr since then is via SavedLocationForRegister(). - if (m_fallback_unwind_plan_sp.get() == nullptr) - return true; - - - // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide this isn't - // working, we need to restore. - // We'll also need to save & restore the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'. - UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; - addr_t old_cfa = m_cfa; - - m_registers.clear(); - - m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; - - UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - - if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified) - { - addr_t new_cfa; - if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) - || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) - { - UnwindLogMsg ("failed to get cfa with fallback unwindplan"); - m_fallback_unwind_plan_sp.reset(); - m_full_unwind_plan_sp = original_full_unwind_plan_sp; - m_cfa = old_cfa; - return false; - } - m_cfa = new_cfa; - - if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB)); - if (reg_info) - { - RegisterValue reg_value; - if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value)) - { - new_caller_pc_value = reg_value.GetAsUInt64(); - } - } - } + if (new_caller_pc_value == LLDB_INVALID_ADDRESS) { + UnwindLogMsg("failed to get a pc value for the caller frame with the " + "fallback unwind plan"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } + if (old_caller_pc_value != LLDB_INVALID_ADDRESS) { + if (old_caller_pc_value == new_caller_pc_value && + new_cfa == old_this_frame_cfa_value) { + UnwindLogMsg("fallback unwind plan got the same values for this frame " + "CFA and caller frame pc, not using"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } + } - if (new_caller_pc_value == LLDB_INVALID_ADDRESS) - { - UnwindLogMsg ("failed to get a pc value for the caller frame with the fallback unwind plan"); - m_fallback_unwind_plan_sp.reset(); - m_full_unwind_plan_sp = original_full_unwind_plan_sp; - m_cfa = old_cfa; - return false; - } + UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' " + "because UnwindPlan '%s' failed.", + m_fallback_unwind_plan_sp->GetSourceName().GetCString(), + original_full_unwind_plan_sp->GetSourceName().GetCString()); - if (old_caller_pc_value != LLDB_INVALID_ADDRESS) - { - if (old_caller_pc_value == new_caller_pc_value && new_cfa == old_this_frame_cfa_value) - { - UnwindLogMsg ("fallback unwind plan got the same values for this frame CFA and caller frame pc, not using"); - m_fallback_unwind_plan_sp.reset(); - m_full_unwind_plan_sp = original_full_unwind_plan_sp; - m_cfa = old_cfa; - return false; - } - } + // We've copied the fallback unwind plan into the full - now clear the + // fallback. + m_fallback_unwind_plan_sp.reset(); + } - UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.", - m_fallback_unwind_plan_sp->GetSourceName().GetCString(), - original_full_unwind_plan_sp->GetSourceName().GetCString()); + return true; +} - // We've copied the fallback unwind plan into the full - now clear the fallback. - m_fallback_unwind_plan_sp.reset(); - } +bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { + if (m_fallback_unwind_plan_sp.get() == NULL) + return false; - return true; -} + if (m_full_unwind_plan_sp.get() == NULL) + return false; -bool -RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan () -{ - if (m_fallback_unwind_plan_sp.get() == NULL) - return false; + if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || + m_full_unwind_plan_sp->GetSourceName() == + m_fallback_unwind_plan_sp->GetSourceName()) { + return false; + } - if (m_full_unwind_plan_sp.get() == NULL) - return false; + UnwindPlan::RowSP active_row = + m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); - if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() - || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName()) - { - return false; + if (active_row && + active_row->GetCFAValue().GetValueType() != + UnwindPlan::Row::CFAValue::unspecified) { + addr_t new_cfa; + if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), + active_row, new_cfa) || + new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) { + UnwindLogMsg("failed to get cfa with fallback unwindplan"); + m_fallback_unwind_plan_sp.reset(); + return false; } - UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - - if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified) - { - addr_t new_cfa; - if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) - || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) - { - UnwindLogMsg ("failed to get cfa with fallback unwindplan"); - m_fallback_unwind_plan_sp.reset(); - return false; - } - - m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; - m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; + m_fallback_unwind_plan_sp.reset(); - m_registers.clear(); + m_registers.clear(); - m_cfa = new_cfa; + m_cfa = new_cfa; - UnwindLogMsg ("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString()); - return true; - } - return false; + UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", + m_full_unwind_plan_sp->GetSourceName().GetCString()); + return true; + } + return false; } -bool -RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, - const UnwindPlan::RowSP &row, - addr_t &cfa_value) -{ - RegisterValue reg_value; - - cfa_value = LLDB_INVALID_ADDRESS; - addr_t cfa_reg_contents; - - switch (row->GetCFAValue().GetValueType()) - { - case UnwindPlan::Row::CFAValue::isRegisterDereferenced: - { - RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber()); - if (ReadGPRValue (cfa_reg, cfa_reg_contents)) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB)); - RegisterValue reg_value; - if (reg_info) - { - Error error = ReadRegisterValueFromMemory(reg_info, - cfa_reg_contents, - reg_info->byte_size, - reg_value); - if (error.Success ()) - { - cfa_value = reg_value.GetAsUInt64(); - UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64, - cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), - cfa_reg_contents, cfa_value); - return true; - } - else - { - UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.", - cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), - cfa_reg_contents); - } - } - } - break; - } - case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: - { - RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber()); - if (ReadGPRValue (cfa_reg, cfa_reg_contents)) - { - if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1) - { - UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, - cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), - cfa_reg_contents); - cfa_reg_contents = LLDB_INVALID_ADDRESS; - return false; - } - cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset(); - UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d", - cfa_value, - cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), - cfa_reg_contents, row->GetCFAValue().GetOffset()); - return true; - } - break; +bool RegisterContextLLDB::ReadCFAValueForRow( + lldb::RegisterKind row_register_kind, const UnwindPlan::RowSP &row, + addr_t &cfa_value) { + RegisterValue reg_value; + + cfa_value = LLDB_INVALID_ADDRESS; + addr_t cfa_reg_contents; + + switch (row->GetCFAValue().GetValueType()) { + case UnwindPlan::Row::CFAValue::isRegisterDereferenced: { + RegisterNumber cfa_reg(m_thread, row_register_kind, + row->GetCFAValue().GetRegisterNumber()); + if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { + const RegisterInfo *reg_info = + GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB)); + RegisterValue reg_value; + if (reg_info) { + Error error = ReadRegisterValueFromMemory( + reg_info, cfa_reg_contents, reg_info->byte_size, reg_value); + if (error.Success()) { + cfa_value = reg_value.GetAsUInt64(); + UnwindLogMsg( + "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 + ", CFA value is 0x%" PRIx64, + cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), + cfa_reg_contents, cfa_value); + return true; + } else { + UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64 + "] but memory read failed.", + cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), + cfa_reg_contents); } - case UnwindPlan::Row::CFAValue::isDWARFExpression: - { - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - DataExtractor dwarfdata (row->GetCFAValue().GetDWARFExpressionBytes(), - row->GetCFAValue().GetDWARFExpressionLength(), - process->GetByteOrder(), process->GetAddressByteSize()); - ModuleSP opcode_ctx; - DWARFExpression dwarfexpr (opcode_ctx, - dwarfdata, - nullptr, - 0, - row->GetCFAValue().GetDWARFExpressionLength()); - dwarfexpr.SetRegisterKind (row_register_kind); - Value result; - Error error; - if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error)) - { - cfa_value = result.GetScalar().ULongLong(); - - UnwindLogMsg ("CFA value set by DWARF expression is 0x%" PRIx64, cfa_value); - return true; - } - UnwindLogMsg ("Failed to set CFA value via DWARF expression: %s", error.AsCString()); - break; - } - default: + } + } + break; + } + case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: { + RegisterNumber cfa_reg(m_thread, row_register_kind, + row->GetCFAValue().GetRegisterNumber()); + if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { + if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || + cfa_reg_contents == 1) { + UnwindLogMsg( + "Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, + cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), + cfa_reg_contents); + cfa_reg_contents = LLDB_INVALID_ADDRESS; return false; - } + } + cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset(); + UnwindLogMsg( + "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 + ", offset is %d", + cfa_value, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), + cfa_reg_contents, row->GetCFAValue().GetOffset()); + return true; + } + break; + } + case UnwindPlan::Row::CFAValue::isDWARFExpression: { + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + DataExtractor dwarfdata(row->GetCFAValue().GetDWARFExpressionBytes(), + row->GetCFAValue().GetDWARFExpressionLength(), + process->GetByteOrder(), + process->GetAddressByteSize()); + ModuleSP opcode_ctx; + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, + row->GetCFAValue().GetDWARFExpressionLength()); + dwarfexpr.SetRegisterKind(row_register_kind); + Value result; + Error error; + if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, + nullptr, result, &error)) { + cfa_value = result.GetScalar().ULongLong(); + + UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, + cfa_value); + return true; + } + UnwindLogMsg("Failed to set CFA value via DWARF expression: %s", + error.AsCString()); + break; + } + default: return false; + } + return false; } -// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that +// Retrieve a general purpose register value for THIS frame, as saved by the +// NEXT frame, i.e. the frame that // this frame called. e.g. // // foo () { } @@ -1866,278 +1859,241 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, // frame 0 - foo // frame 1 - bar // frame 2 - main -// and this RegisterContext is for frame 1 (bar) - if we want to get the pc value for frame 1, we need to ask +// and this RegisterContext is for frame 1 (bar) - if we want to get the pc +// value for frame 1, we need to ask // where frame 0 (the "next" frame) saved that and retrieve the value. -bool -RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, addr_t &value) -{ - if (!IsValid()) - return false; - - uint32_t lldb_regnum; - if (register_kind == eRegisterKindLLDB) - { - lldb_regnum = regnum; - } - else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) - { - return false; - } +bool RegisterContextLLDB::ReadGPRValue(lldb::RegisterKind register_kind, + uint32_t regnum, addr_t &value) { + if (!IsValid()) + return false; - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); - RegisterValue reg_value; - // if this is frame 0 (currently executing frame), get the requested reg contents from the actual thread registers - if (IsFrameZero ()) - { - if (m_thread.GetRegisterContext()->ReadRegister (reg_info, reg_value)) - { - value = reg_value.GetAsUInt64(); - return true; - } - return false; - } + uint32_t lldb_regnum; + if (register_kind == eRegisterKindLLDB) { + lldb_regnum = regnum; + } else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( + register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) { + return false; + } - bool pc_register = false; - uint32_t generic_regnum; - if (register_kind == eRegisterKindGeneric - && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) - { - pc_register = true; - } - else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum) - && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA)) - { - pc_register = true; - } - - lldb_private::UnwindLLDB::RegisterLocation regloc; - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_register)) - { - return false; - } - if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value)) - { - value = reg_value.GetAsUInt64(); - return true; + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); + RegisterValue reg_value; + // if this is frame 0 (currently executing frame), get the requested reg + // contents from the actual thread registers + if (IsFrameZero()) { + if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) { + value = reg_value.GetAsUInt64(); + return true; } return false; + } + + bool pc_register = false; + uint32_t generic_regnum; + if (register_kind == eRegisterKindGeneric && + (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) { + pc_register = true; + } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds( + register_kind, regnum, eRegisterKindGeneric, generic_regnum) && + (generic_regnum == LLDB_REGNUM_GENERIC_PC || + generic_regnum == LLDB_REGNUM_GENERIC_RA)) { + pc_register = true; + } + + lldb_private::UnwindLLDB::RegisterLocation regloc; + if (!m_parent_unwind.SearchForSavedLocationForRegister( + lldb_regnum, regloc, m_frame_number - 1, pc_register)) { + return false; + } + if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { + value = reg_value.GetAsUInt64(); + return true; + } + return false; } -bool -RegisterContextLLDB::ReadGPRValue (const RegisterNumber ®num, addr_t &value) -{ - return ReadGPRValue (regnum.GetRegisterKind(), regnum.GetRegisterNumber(), value); +bool RegisterContextLLDB::ReadGPRValue(const RegisterNumber ®num, + addr_t &value) { + return ReadGPRValue(regnum.GetRegisterKind(), regnum.GetRegisterNumber(), + value); } // Find the value of a register in THIS frame -bool -RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!IsValid()) - return false; - - const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; - UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum); - - // If this is the 0th frame, hand this over to the live register context - if (IsFrameZero ()) - { - UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum); - return m_thread.GetRegisterContext()->ReadRegister (reg_info, value); - } - - bool is_pc_regnum = false; - if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC - || reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) - { - is_pc_regnum = true; - } +bool RegisterContextLLDB::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + if (!IsValid()) + return false; - lldb_private::UnwindLLDB::RegisterLocation regloc; - // Find out where the NEXT frame saved THIS frame's register contents - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) - return false; + const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; + UnwindLogMsgVerbose("looking for register saved location for reg %d", + lldb_regnum); + + // If this is the 0th frame, hand this over to the live register context + if (IsFrameZero()) { + UnwindLogMsgVerbose("passing along to the live register context for reg %d", + lldb_regnum); + return m_thread.GetRegisterContext()->ReadRegister(reg_info, value); + } + + bool is_pc_regnum = false; + if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC || + reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) { + is_pc_regnum = true; + } + + lldb_private::UnwindLLDB::RegisterLocation regloc; + // Find out where the NEXT frame saved THIS frame's register contents + if (!m_parent_unwind.SearchForSavedLocationForRegister( + lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) + return false; - return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value); + return ReadRegisterValueFromRegisterLocation(regloc, reg_info, value); } -bool -RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) -{ - if (!IsValid()) - return false; - - const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; - UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum); - - // If this is the 0th frame, hand this over to the live register context - if (IsFrameZero ()) - { - UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum); - return m_thread.GetRegisterContext()->WriteRegister (reg_info, value); - } +bool RegisterContextLLDB::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + if (!IsValid()) + return false; - lldb_private::UnwindLLDB::RegisterLocation regloc; - // Find out where the NEXT frame saved THIS frame's register contents - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false)) - return false; + const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; + UnwindLogMsgVerbose("looking for register saved location for reg %d", + lldb_regnum); + + // If this is the 0th frame, hand this over to the live register context + if (IsFrameZero()) { + UnwindLogMsgVerbose("passing along to the live register context for reg %d", + lldb_regnum); + return m_thread.GetRegisterContext()->WriteRegister(reg_info, value); + } + + lldb_private::UnwindLLDB::RegisterLocation regloc; + // Find out where the NEXT frame saved THIS frame's register contents + if (!m_parent_unwind.SearchForSavedLocationForRegister( + lldb_regnum, regloc, m_frame_number - 1, false)) + return false; - return WriteRegisterValueToRegisterLocation (regloc, reg_info, value); + return WriteRegisterValueToRegisterLocation(regloc, reg_info, value); } // Don't need to implement this one -bool -RegisterContextLLDB::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextLLDB::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) { + return false; } // Don't need to implement this one -bool -RegisterContextLLDB::WriteAllRegisterValues (const lldb::DataBufferSP& data_sp) -{ - return false; +bool RegisterContextLLDB::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } // Retrieve the pc value for THIS from -bool -RegisterContextLLDB::GetCFA (addr_t& cfa) -{ - if (!IsValid()) - { - return false; - } - if (m_cfa == LLDB_INVALID_ADDRESS) - { - return false; - } - cfa = m_cfa; - return true; +bool RegisterContextLLDB::GetCFA(addr_t &cfa) { + if (!IsValid()) { + return false; + } + if (m_cfa == LLDB_INVALID_ADDRESS) { + return false; + } + cfa = m_cfa; + return true; } - -RegisterContextLLDB::SharedPtr -RegisterContextLLDB::GetNextFrame () const -{ - RegisterContextLLDB::SharedPtr regctx; - if (m_frame_number == 0) - return regctx; - return m_parent_unwind.GetRegisterContextForFrameNum (m_frame_number - 1); +RegisterContextLLDB::SharedPtr RegisterContextLLDB::GetNextFrame() const { + RegisterContextLLDB::SharedPtr regctx; + if (m_frame_number == 0) + return regctx; + return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number - 1); } -RegisterContextLLDB::SharedPtr -RegisterContextLLDB::GetPrevFrame () const -{ - RegisterContextLLDB::SharedPtr regctx; - return m_parent_unwind.GetRegisterContextForFrameNum (m_frame_number + 1); +RegisterContextLLDB::SharedPtr RegisterContextLLDB::GetPrevFrame() const { + RegisterContextLLDB::SharedPtr regctx; + return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number + 1); } // Retrieve the address of the start of the function of THIS frame -bool -RegisterContextLLDB::GetStartPC (addr_t& start_pc) -{ - if (!IsValid()) - return false; +bool RegisterContextLLDB::GetStartPC(addr_t &start_pc) { + if (!IsValid()) + return false; - if (!m_start_pc.IsValid()) - { - return ReadPC (start_pc); - } - start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get()); - return true; + if (!m_start_pc.IsValid()) { + return ReadPC(start_pc); + } + start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get()); + return true; } // Retrieve the current pc value for THIS frame, as saved by the NEXT frame. -bool -RegisterContextLLDB::ReadPC (addr_t& pc) -{ - if (!IsValid()) - return false; - - bool above_trap_handler = false; - if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame()) - above_trap_handler = true; +bool RegisterContextLLDB::ReadPC(addr_t &pc) { + if (!IsValid()) + return false; - if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) - { - // A pc value of 0 or 1 is impossible in the middle of the stack -- it indicates the end of a stack walk. - // On the currently executing frame (or such a frame interrupted asynchronously by sigtramp et al) this may - // occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help - // find the bug. - - if (m_all_registers_available == false - && above_trap_handler == false - && (pc == 0 || pc == 1)) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } + bool above_trap_handler = false; + if (GetNextFrame().get() && GetNextFrame()->IsValid() && + GetNextFrame()->IsTrapHandlerFrame()) + above_trap_handler = true; + + if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { + // A pc value of 0 or 1 is impossible in the middle of the stack -- it + // indicates the end of a stack walk. + // On the currently executing frame (or such a frame interrupted + // asynchronously by sigtramp et al) this may + // occur if code has jumped through a NULL pointer -- we want to be able to + // unwind past that frame to help + // find the bug. + + if (m_all_registers_available == false && above_trap_handler == false && + (pc == 0 || pc == 1)) { + return false; + } else { + return true; + } + } else { + return false; + } } - -void -RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...) -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - va_list args; - va_start (args, fmt); - - char *logmsg; - if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL) - { - if (logmsg) - free (logmsg); - va_end (args); - return; - } - va_end (args); - - log->Printf ("%*sth%d/fr%u %s", - m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number, - logmsg); - free (logmsg); - } +void RegisterContextLLDB::UnwindLogMsg(const char *fmt, ...) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + va_list args; + va_start(args, fmt); + + char *logmsg; + if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == NULL) { + if (logmsg) + free(logmsg); + va_end(args); + return; + } + va_end(args); + + log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, + "", m_thread.GetIndexID(), m_frame_number, logmsg); + free(logmsg); + } } -void -RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...) -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log && log->GetVerbose()) - { - va_list args; - va_start (args, fmt); - - char *logmsg; - if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL) - { - if (logmsg) - free (logmsg); - va_end (args); - return; - } - va_end (args); - - log->Printf ("%*sth%d/fr%u %s", - m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number, - logmsg); - free (logmsg); - } +void RegisterContextLLDB::UnwindLogMsgVerbose(const char *fmt, ...) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) { + va_list args; + va_start(args, fmt); + + char *logmsg; + if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == NULL) { + if (logmsg) + free(logmsg); + va_end(args); + return; + } + va_end(args); + + log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, + "", m_thread.GetIndexID(), m_frame_number, logmsg); + free(logmsg); + } } - - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 68dca3d4965..cb22eedd560 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -1,4 +1,5 @@ -//===-- RegisterContextLLDB.h --------------------------------------------*- C++ -*-===// +//===-- RegisterContextLLDB.h --------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,253 +17,247 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Symbol/UnwindPlan.h" +#include "UnwindLLDB.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Utility/RegisterNumber.h" -#include "UnwindLLDB.h" +#include "lldb/lldb-private.h" namespace lldb_private { class UnwindLLDB; -class RegisterContextLLDB : public lldb_private::RegisterContext -{ +class RegisterContextLLDB : public lldb_private::RegisterContext { public: - typedef std::shared_ptr<RegisterContextLLDB> SharedPtr; + typedef std::shared_ptr<RegisterContextLLDB> SharedPtr; - RegisterContextLLDB (lldb_private::Thread &thread, - const SharedPtr& next_frame, - lldb_private::SymbolContext& sym_ctx, - uint32_t frame_number, lldb_private::UnwindLLDB& unwind_lldb); + RegisterContextLLDB(lldb_private::Thread &thread, const SharedPtr &next_frame, + lldb_private::SymbolContext &sym_ctx, + uint32_t frame_number, + lldb_private::UnwindLLDB &unwind_lldb); - ~RegisterContextLLDB() override = default; + ~RegisterContextLLDB() override = default; - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t reg_set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - bool - IsValid () const; + bool IsValid() const; - bool - IsTrapHandlerFrame () const; + bool IsTrapHandlerFrame() const; - bool - GetCFA (lldb::addr_t& cfa); + bool GetCFA(lldb::addr_t &cfa); - bool - GetStartPC (lldb::addr_t& start_pc); + bool GetStartPC(lldb::addr_t &start_pc); - bool - ReadPC (lldb::addr_t& start_pc); + bool ReadPC(lldb::addr_t &start_pc); private: - - enum FrameType - { - eNormalFrame, - eTrapHandlerFrame, - eDebuggerFrame, // a debugger inferior function call frame; we get caller's registers from debugger - eSkipFrame, // The unwind resulted in a bogus frame but may get back on track so we don't want to give up yet - eNotAValidFrame // this frame is invalid for some reason - most likely it is past the top (end) of the stack - }; - - // UnwindLLDB needs to pass around references to RegisterLocations - friend class UnwindLLDB; - - // Returns true if we have an unwind loop -- the same stack frame unwinding - // multiple times. - bool - CheckIfLoopingStack (); - - // Indicates whether this frame is frame zero -- the currently - // executing frame -- or not. - bool - IsFrameZero () const; - - void - InitializeZerothFrame (); - - void - InitializeNonZerothFrame(); - - SharedPtr - GetNextFrame () const; - - SharedPtr - GetPrevFrame () const; - - // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1. - // There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate - // on this ABI) so we allow one invalid frame to be in the stack. Ideally we'll mark this frame specially at some - // point and indicate to the user that the unwinder had a hiccup. Often when this happens we will miss a frame of - // the program's actual stack in the unwind and we want to flag that for the user somehow. - bool - IsSkipFrame () const; - - //------------------------------------------------------------------ - /// Determines if a SymbolContext is a trap handler or not - /// - /// Given a SymbolContext, determines if this is a trap handler function - /// aka asynchronous signal handler. - /// - /// @return - /// Returns true if the SymbolContext is a trap handler. - //------------------------------------------------------------------ - bool - IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const; - - // Provide a location for where THIS function saved the CALLER's register value - // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this - // function didn't modify/use. - // - // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register - // being queried mid-stack. Instead of floating frame 0's contents of that register up the stack (which may - // or may not be the value of that reg when the function was executing), we won't return any value. - // - // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested - // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same - // as the requesting frame's. - lldb_private::UnwindLLDB::RegisterSearchResult - SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc); - - bool - ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, - const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, - const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - //------------------------------------------------------------------ - /// If the unwind has to the caller frame has failed, try something else - /// - /// If lldb is using an assembly language based UnwindPlan for a frame and - /// the unwind to the caller frame fails, try falling back to a generic - /// UnwindPlan (architecture default unwindplan) to see if that might work - /// better. This is mostly helping to work around problems where the - /// assembly language inspection fails on hand-written assembly code. - /// - /// @return - /// Returns true if a fallback unwindplan was found & was installed. - //------------------------------------------------------------------ - bool - TryFallbackUnwindPlan (); - - //------------------------------------------------------------------ - /// Switch to the fallback unwind plan unconditionally without any safety - /// checks that it is providing better results than the normal unwind plan. - /// - /// The only time it is valid to call this method is if the full unwindplan is - /// found to be fundamentally incorrect/impossible. - /// - /// Returns true if it was able to install the fallback unwind plan. - //------------------------------------------------------------------ - bool - ForceSwitchToFallbackUnwindPlan (); - - // Get the contents of a general purpose (address-size) register for this frame - // (usually retrieved from the next frame) - bool - ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value); - - bool - ReadGPRValue (const RegisterNumber ®_num, lldb::addr_t &value); - - // Get the CFA register for a given frame. - bool - ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value); - - lldb::UnwindPlanSP - GetFastUnwindPlanForFrame (); - - lldb::UnwindPlanSP - GetFullUnwindPlanForFrame (); - - void - UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); - - void - UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); - - bool - IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset); - - lldb_private::Thread& m_thread; - - /// - // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above) - // i.e. where THIS frame saved them - /// - - lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL - lldb::UnwindPlanSP m_full_unwind_plan_sp; - lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL - - bool m_all_registers_available; // Can we retrieve all regs or just nonvolatile regs? - int m_frame_type; // enum FrameType - - lldb::addr_t m_cfa; - lldb_private::Address m_start_pc; - lldb_private::Address m_current_pc; - - int m_current_offset; // how far into the function we've executed; -1 if unknown - // 0 if no instructions have been executed yet. - - int m_current_offset_backed_up_one; // how far into the function we've executed; -1 if unknown - // 0 if no instructions have been executed yet. - // On architectures where the return address on the stack points - // to the instruction after the CALL, this value will have 1 - // subtracted from it. Else a function that ends in a CALL will - // have an offset pointing into the next function's address range. - // m_current_pc has the actual address of the "current" pc. - - lldb_private::SymbolContext& m_sym_ctx; - bool m_sym_ctx_valid; // if ResolveSymbolContextForAddress fails, don't try to use m_sym_ctx - - uint32_t m_frame_number; // What stack frame this RegisterContext is - - std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation> m_registers; // where to find reg values for this frame - - lldb_private::UnwindLLDB& m_parent_unwind; // The UnwindLLDB that is creating this RegisterContextLLDB - - //------------------------------------------------------------------ - // For RegisterContextLLDB only - //------------------------------------------------------------------ - - DISALLOW_COPY_AND_ASSIGN (RegisterContextLLDB); + enum FrameType { + eNormalFrame, + eTrapHandlerFrame, + eDebuggerFrame, // a debugger inferior function call frame; we get caller's + // registers from debugger + eSkipFrame, // The unwind resulted in a bogus frame but may get back on + // track so we don't want to give up yet + eNotAValidFrame // this frame is invalid for some reason - most likely it is + // past the top (end) of the stack + }; + + // UnwindLLDB needs to pass around references to RegisterLocations + friend class UnwindLLDB; + + // Returns true if we have an unwind loop -- the same stack frame unwinding + // multiple times. + bool CheckIfLoopingStack(); + + // Indicates whether this frame is frame zero -- the currently + // executing frame -- or not. + bool IsFrameZero() const; + + void InitializeZerothFrame(); + + void InitializeNonZerothFrame(); + + SharedPtr GetNextFrame() const; + + SharedPtr GetPrevFrame() const; + + // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've + // got one bogus frame at frame #1. + // There is a good chance we'll get back on track if we follow the frame + // pointer chain (or whatever is appropriate + // on this ABI) so we allow one invalid frame to be in the stack. Ideally + // we'll mark this frame specially at some + // point and indicate to the user that the unwinder had a hiccup. Often when + // this happens we will miss a frame of + // the program's actual stack in the unwind and we want to flag that for the + // user somehow. + bool IsSkipFrame() const; + + //------------------------------------------------------------------ + /// Determines if a SymbolContext is a trap handler or not + /// + /// Given a SymbolContext, determines if this is a trap handler function + /// aka asynchronous signal handler. + /// + /// @return + /// Returns true if the SymbolContext is a trap handler. + //------------------------------------------------------------------ + bool IsTrapHandlerSymbol(lldb_private::Process *process, + const lldb_private::SymbolContext &m_sym_ctx) const; + + // Provide a location for where THIS function saved the CALLER's register + // value + // Or a frame "below" this one saved it, i.e. a function called by this one, + // preserved a register that this + // function didn't modify/use. + // + // The RegisterLocation type may be set to eRegisterNotAvailable -- this will + // happen for a volatile register + // being queried mid-stack. Instead of floating frame 0's contents of that + // register up the stack (which may + // or may not be the value of that reg when the function was executing), we + // won't return any value. + // + // If a non-volatile register (a "preserved" register) is requested mid-stack + // and no frames "below" the requested + // stack have saved the register anywhere, it is safe to assume that frame 0's + // register values are still the same + // as the requesting frame's. + lldb_private::UnwindLLDB::RegisterSearchResult + SavedLocationForRegister(uint32_t lldb_regnum, + lldb_private::UnwindLLDB::RegisterLocation ®loc); + + bool ReadRegisterValueFromRegisterLocation( + lldb_private::UnwindLLDB::RegisterLocation regloc, + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); + + bool WriteRegisterValueToRegisterLocation( + lldb_private::UnwindLLDB::RegisterLocation regloc, + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); + + //------------------------------------------------------------------ + /// If the unwind has to the caller frame has failed, try something else + /// + /// If lldb is using an assembly language based UnwindPlan for a frame and + /// the unwind to the caller frame fails, try falling back to a generic + /// UnwindPlan (architecture default unwindplan) to see if that might work + /// better. This is mostly helping to work around problems where the + /// assembly language inspection fails on hand-written assembly code. + /// + /// @return + /// Returns true if a fallback unwindplan was found & was installed. + //------------------------------------------------------------------ + bool TryFallbackUnwindPlan(); + + //------------------------------------------------------------------ + /// Switch to the fallback unwind plan unconditionally without any safety + /// checks that it is providing better results than the normal unwind plan. + /// + /// The only time it is valid to call this method is if the full unwindplan is + /// found to be fundamentally incorrect/impossible. + /// + /// Returns true if it was able to install the fallback unwind plan. + //------------------------------------------------------------------ + bool ForceSwitchToFallbackUnwindPlan(); + + // Get the contents of a general purpose (address-size) register for this + // frame + // (usually retrieved from the next frame) + bool ReadGPRValue(lldb::RegisterKind register_kind, uint32_t regnum, + lldb::addr_t &value); + + bool ReadGPRValue(const RegisterNumber ®_num, lldb::addr_t &value); + + // Get the CFA register for a given frame. + bool ReadCFAValueForRow(lldb::RegisterKind register_kind, + const UnwindPlan::RowSP &row, lldb::addr_t &value); + + lldb::UnwindPlanSP GetFastUnwindPlanForFrame(); + + lldb::UnwindPlanSP GetFullUnwindPlanForFrame(); + + void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3))); + + void UnwindLogMsgVerbose(const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + + bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, + int &valid_pc_offset); + + lldb_private::Thread &m_thread; + + /// + // The following tell us how to retrieve the CALLER's register values (ie the + // "previous" frame, aka the frame above) + // i.e. where THIS frame saved them + /// + + lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL + lldb::UnwindPlanSP m_full_unwind_plan_sp; + lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL + + bool m_all_registers_available; // Can we retrieve all regs or just + // nonvolatile regs? + int m_frame_type; // enum FrameType + + lldb::addr_t m_cfa; + lldb_private::Address m_start_pc; + lldb_private::Address m_current_pc; + + int m_current_offset; // how far into the function we've executed; -1 if + // unknown + // 0 if no instructions have been executed yet. + + int m_current_offset_backed_up_one; // how far into the function we've + // executed; -1 if unknown + // 0 if no instructions have been executed yet. + // On architectures where the return address on the stack points + // to the instruction after the CALL, this value will have 1 + // subtracted from it. Else a function that ends in a CALL will + // have an offset pointing into the next function's address range. + // m_current_pc has the actual address of the "current" pc. + + lldb_private::SymbolContext &m_sym_ctx; + bool m_sym_ctx_valid; // if ResolveSymbolContextForAddress fails, don't try to + // use m_sym_ctx + + uint32_t m_frame_number; // What stack frame this RegisterContext is + + std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation> + m_registers; // where to find reg values for this frame + + lldb_private::UnwindLLDB &m_parent_unwind; // The UnwindLLDB that is creating + // this RegisterContextLLDB + + //------------------------------------------------------------------ + // For RegisterContextLLDB only + //------------------------------------------------------------------ + + DISALLOW_COPY_AND_ASSIGN(RegisterContextLLDB); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp index a4d8738d79b..afa105f2540 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp @@ -7,12 +7,12 @@ // //===---------------------------------------------------------------------===// +#include <cassert> #include <stddef.h> #include <vector> -#include <cassert> -#include "llvm/Support/Compiler.h" #include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" #include "RegisterContextLinux_arm.h" @@ -20,14 +20,31 @@ using namespace lldb; using namespace lldb_private; // Based on RegisterContextDarwin_arm.cpp -#define GPR_OFFSET(idx) ((idx) * 4) -#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR)) -#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextLinux_arm::FPU, fpscr) + sizeof (RegisterContextLinux_arm::GPR)) -#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU)) -#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextLinux_arm::DBG, reg) + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC))) +#define GPR_OFFSET(idx) ((idx)*4) +#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextLinux_arm::GPR)) +#define FPSCR_OFFSET \ + (LLVM_EXTENSION offsetof(RegisterContextLinux_arm::FPU, fpscr) + \ + sizeof(RegisterContextLinux_arm::GPR)) +#define EXC_OFFSET(idx) \ + ((idx)*4 + sizeof(RegisterContextLinux_arm::GPR) + \ + sizeof(RegisterContextLinux_arm::FPU)) +#define DBG_OFFSET(reg) \ + ((LLVM_EXTENSION offsetof(RegisterContextLinux_arm::DBG, reg) + \ + sizeof(RegisterContextLinux_arm::GPR) + \ + sizeof(RegisterContextLinux_arm::FPU) + \ + sizeof(RegisterContextLinux_arm::EXC))) -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextLinux_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC)) +#define DEFINE_DBG(reg, i) \ + #reg, NULL, sizeof(((RegisterContextLinux_arm::DBG *) NULL)->reg[i]), \ + DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + dbg_##reg##i }, \ + NULL, NULL, NULL, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextLinux_arm::GPR) + \ + sizeof(RegisterContextLinux_arm::FPU) + \ + sizeof(RegisterContextLinux_arm::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm to declare our g_register_infos_arm structure. @@ -37,52 +54,43 @@ using namespace lldb_private; #undef DECLARE_REGISTER_INFOS_ARM_STRUCT static const lldb_private::RegisterInfo * -GetRegisterInfoPtr (const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - return g_register_infos_arm; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + return g_register_infos_arm; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - return static_cast<uint32_t>(sizeof(g_register_infos_arm) / sizeof(g_register_infos_arm[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::arm: + return static_cast<uint32_t>(sizeof(g_register_infos_arm) / + sizeof(g_register_infos_arm[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextLinux_arm::RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) -{ -} +RegisterContextLinux_arm::RegisterContextLinux_arm( + const lldb_private::ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} -size_t -RegisterContextLinux_arm::GetGPRSize() const -{ - return sizeof(struct RegisterContextLinux_arm::GPR); +size_t RegisterContextLinux_arm::GetGPRSize() const { + return sizeof(struct RegisterContextLinux_arm::GPR); } const lldb_private::RegisterInfo * -RegisterContextLinux_arm::GetRegisterInfo() const -{ - return m_register_info_p; +RegisterContextLinux_arm::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextLinux_arm::GetRegisterCount() const -{ - return m_register_info_count; +uint32_t RegisterContextLinux_arm::GetRegisterCount() const { + return m_register_info_count; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h index c3d41f686dc..9065bc0e08d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h @@ -10,66 +10,53 @@ #ifndef liblldb_RegisterContextLinux_arm_h_ #define liblldb_RegisterContextLinux_arm_h_ -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" -class RegisterContextLinux_arm - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_arm : public lldb_private::RegisterInfoInterface { public: - - struct GPR - { - uint32_t r[16]; // R0-R15 - uint32_t cpsr; // CPSR - }; - - - struct QReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; - struct EXC - { - uint32_t exception; - uint32_t fsr; /* Fault status */ - uint32_t far; /* Virtual Fault Address */ - }; - - struct DBG - { - uint32_t bvr[16]; - uint32_t bcr[16]; - uint32_t wvr[16]; - uint32_t wcr[16]; - }; - - RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch); - - size_t - GetGPRSize() const override; - - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; - - uint32_t - GetRegisterCount () const override; + struct GPR { + uint32_t r[16]; // R0-R15 + uint32_t cpsr; // CPSR + }; + + struct QReg { + uint8_t bytes[16]; + }; + + struct FPU { + union { + uint32_t s[32]; + uint64_t d[32]; + QReg q[16]; // the 128-bit NEON registers + } floats; + uint32_t fpscr; + }; + struct EXC { + uint32_t exception; + uint32_t fsr; /* Fault status */ + uint32_t far; /* Virtual Fault Address */ + }; + + struct DBG { + uint32_t bvr[16]; + uint32_t bcr[16]; + uint32_t wvr[16]; + uint32_t wcr[16]; + }; + + RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; }; -#endif // liblldb_RegisterContextLinux_arm_h_ - +#endif // liblldb_RegisterContextLinux_arm_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp index e65537af729..5eb194e2ce1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp @@ -7,28 +7,47 @@ // //===---------------------------------------------------------------------===// +#include <cassert> #include <stddef.h> #include <vector> -#include <cassert> -#include "llvm/Support/Compiler.h" #include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" #include "RegisterContextLinux_arm64.h" // Based on RegisterContextDarwin_arm64.cpp -#define GPR_OFFSET(idx) ((idx) * 8) -#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::GPR, reg)) - -#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextLinux_arm64::GPR)) -#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg) + sizeof (RegisterContextLinux_arm64::GPR)) +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextLinux_arm64::GPR, reg)) -#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::EXC, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU)) -#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::DBG, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC)) +#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextLinux_arm64::GPR)) +#define FPU_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextLinux_arm64::FPU, reg) + \ + sizeof(RegisterContextLinux_arm64::GPR)) -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextLinux_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE (sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC)) +#define EXC_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextLinux_arm64::EXC, reg) + \ + sizeof(RegisterContextLinux_arm64::GPR) + \ + sizeof(RegisterContextLinux_arm64::FPU)) +#define DBG_OFFSET_NAME(reg) \ + (LLVM_EXTENSION offsetof(RegisterContextLinux_arm64::DBG, reg) + \ + sizeof(RegisterContextLinux_arm64::GPR) + \ + sizeof(RegisterContextLinux_arm64::FPU) + \ + sizeof(RegisterContextLinux_arm64::EXC)) +#define DEFINE_DBG(reg, i) \ + #reg, NULL, \ + sizeof(((RegisterContextLinux_arm64::DBG *) NULL)->reg[i]), \ + DBG_OFFSET_NAME(reg[i]), lldb::eEncodingUint, lldb::eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + dbg_##reg##i }, \ + NULL, NULL, NULL, 0 +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterContextLinux_arm64::GPR) + \ + sizeof(RegisterContextLinux_arm64::FPU) + \ + sizeof(RegisterContextLinux_arm64::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure. @@ -38,52 +57,43 @@ #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT static const lldb_private::RegisterInfo * -GetRegisterInfoPtr (const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - return g_register_infos_arm64; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + return g_register_infos_arm64; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - return static_cast<uint32_t>(sizeof(g_register_infos_arm64) / sizeof(g_register_infos_arm64[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + return static_cast<uint32_t>(sizeof(g_register_infos_arm64) / + sizeof(g_register_infos_arm64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextLinux_arm64::RegisterContextLinux_arm64(const lldb_private::ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) -{ -} +RegisterContextLinux_arm64::RegisterContextLinux_arm64( + const lldb_private::ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} -size_t -RegisterContextLinux_arm64::GetGPRSize() const -{ - return sizeof(struct RegisterContextLinux_arm64::GPR); +size_t RegisterContextLinux_arm64::GetGPRSize() const { + return sizeof(struct RegisterContextLinux_arm64::GPR); } const lldb_private::RegisterInfo * -RegisterContextLinux_arm64::GetRegisterInfo() const -{ - return m_register_info_p; +RegisterContextLinux_arm64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextLinux_arm64::GetRegisterCount() const -{ - return m_register_info_count; +uint32_t RegisterContextLinux_arm64::GetRegisterCount() const { + return m_register_info_count; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h index 3de94b86258..ad775b0d9af 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h @@ -10,71 +10,61 @@ #ifndef liblldb_RegisterContextLinux_arm64_H_ #define liblldb_RegisterContextLinux_arm64_H_ -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" -class RegisterContextLinux_arm64 - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_arm64 : public lldb_private::RegisterInfoInterface { public: - // based on RegisterContextDarwin_arm64.h - struct GPR - { - uint64_t x[29]; // x0-x28 - uint64_t fp; // x29 - uint64_t lr; // x30 - uint64_t sp; // x31 - uint64_t pc; // pc - uint32_t cpsr; // cpsr - }; + // based on RegisterContextDarwin_arm64.h + struct GPR { + uint64_t x[29]; // x0-x28 + uint64_t fp; // x29 + uint64_t lr; // x30 + uint64_t sp; // x31 + uint64_t pc; // pc + uint32_t cpsr; // cpsr + }; - // based on RegisterContextDarwin_arm64.h - struct VReg - { - uint8_t bytes[16]; - }; + // based on RegisterContextDarwin_arm64.h + struct VReg { + uint8_t bytes[16]; + }; - // based on RegisterContextDarwin_arm64.h - struct FPU - { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; + // based on RegisterContextDarwin_arm64.h + struct FPU { + VReg v[32]; + uint32_t fpsr; + uint32_t fpcr; + }; - // based on RegisterContextDarwin_arm64.h - struct EXC - { - uint64_t far; // Virtual Fault Address - uint32_t esr; // Exception syndrome - uint32_t exception; // number of arm exception token - }; + // based on RegisterContextDarwin_arm64.h + struct EXC { + uint64_t far; // Virtual Fault Address + uint32_t esr; // Exception syndrome + uint32_t exception; // number of arm exception token + }; - // based on RegisterContextDarwin_arm64.h - struct DBG - { - uint64_t bvr[16]; - uint64_t bcr[16]; - uint64_t wvr[16]; - uint64_t wcr[16]; - uint64_t mdscr_el1; - }; + // based on RegisterContextDarwin_arm64.h + struct DBG { + uint64_t bvr[16]; + uint64_t bcr[16]; + uint64_t wvr[16]; + uint64_t wcr[16]; + uint64_t mdscr_el1; + }; - RegisterContextLinux_arm64(const lldb_private::ArchSpec &target_arch); + RegisterContextLinux_arm64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index 510497e25fe..6563796db12 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -7,87 +7,81 @@ // //===---------------------------------------------------------------------===// -#include "RegisterContextPOSIX_x86.h" #include "RegisterContextLinux_i386.h" +#include "RegisterContextPOSIX_x86.h" using namespace lldb_private; using namespace lldb; -struct GPR -{ - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - uint32_t orig_eax; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; +struct GPR { + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t orig_eax; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; }; -struct FPR_i386 -{ - uint16_t fctrl; // FPU Control Word (fcw) - uint16_t fstat; // FPU Status Word (fsw) - uint8_t ftag; // FPU Tag Word (ftw) - uint8_t reserved_1; // Reserved - uint16_t fop; // Last Instruction Opcode (fop) - union - { - struct - { - uint64_t fip; // Instruction Pointer - uint64_t fdp; // Data Pointer - } x86_64; - struct - { - uint32_t fioff; // FPU IP Offset (fip) - uint32_t fiseg; // FPU IP Selector (fcs) - uint32_t fooff; // FPU Operand Pointer Offset (foo) - uint32_t foseg; // FPU Operand Pointer Selector (fos) - } i386_;// Added _ in the end to avoid error with gcc defining i386 in some cases - } ptr; - uint32_t mxcsr; // MXCSR Register State - uint32_t mxcsrmask; // MXCSR Mask - MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes - XMMReg xmm[8]; // 8*16 bytes for each XMM-reg = 128 bytes - uint32_t padding[56]; +struct FPR_i386 { + uint16_t fctrl; // FPU Control Word (fcw) + uint16_t fstat; // FPU Status Word (fsw) + uint8_t ftag; // FPU Tag Word (ftw) + uint8_t reserved_1; // Reserved + uint16_t fop; // Last Instruction Opcode (fop) + union { + struct { + uint64_t fip; // Instruction Pointer + uint64_t fdp; // Data Pointer + } x86_64; + struct { + uint32_t fioff; // FPU IP Offset (fip) + uint32_t fiseg; // FPU IP Selector (fcs) + uint32_t fooff; // FPU Operand Pointer Offset (foo) + uint32_t foseg; // FPU Operand Pointer Selector (fos) + } i386_; // Added _ in the end to avoid error with gcc defining i386 in some + // cases + } ptr; + uint32_t mxcsr; // MXCSR Register State + uint32_t mxcsrmask; // MXCSR Mask + MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes + XMMReg xmm[8]; // 8*16 bytes for each XMM-reg = 128 bytes + uint32_t padding[56]; }; -struct UserArea -{ - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - FPR_i386 i387; // FPU registers. - uint32_t tsize; // Text segment size. - uint32_t dsize; // Data segment size. - uint32_t ssize; // Stack segment size. - uint32_t start_code; // VM address of text. - uint32_t start_stack; // VM address of stack bottom (top in rsp). - int32_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - uint32_t ar0; // Location of GPR's. - uint32_t fpstate; // Location of FPR's. Should be a FXSTATE *, but this - // has to be 32-bits even on 64-bit systems. - uint32_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). +struct UserArea { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + FPR_i386 i387; // FPU registers. + uint32_t tsize; // Text segment size. + uint32_t dsize; // Data segment size. + uint32_t ssize; // Stack segment size. + uint32_t start_code; // VM address of text. + uint32_t start_stack; // VM address of stack bottom (top in rsp). + int32_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + uint32_t ar0; // Location of GPR's. + uint32_t fpstate; // Location of FPR's. Should be a FXSTATE *, but this + // has to be 32-bits even on 64-bit systems. + uint32_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). }; -#define DR_SIZE sizeof(((UserArea*)NULL)->u_debugreg[0]) +#define DR_SIZE sizeof(((UserArea *)NULL)->u_debugreg[0]) #define DR_0_OFFSET 0xFC -#define DR_OFFSET(reg_index) \ - (DR_0_OFFSET + (reg_index * 4)) -#define FPR_SIZE(reg) sizeof(((FPR_i386*)NULL)->reg) +#define DR_OFFSET(reg_index) (DR_0_OFFSET + (reg_index * 4)) +#define FPR_SIZE(reg) sizeof(((FPR_i386 *)NULL)->reg) //--------------------------------------------------------------------------- // Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. @@ -96,48 +90,48 @@ struct UserArea #include "RegisterInfos_i386.h" #undef DECLARE_REGISTER_INFOS_I386_STRUCT -RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) : - RegisterInfoInterface(target_arch) -{ - RegisterInfo orig_ax = { "orig_eax", NULL, sizeof(((GPR*)NULL)->orig_eax), (LLVM_EXTENSION offsetof(GPR, orig_eax)), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr, nullptr, 0 }; - d_register_infos.push_back(orig_ax); +RegisterContextLinux_i386::RegisterContextLinux_i386( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) { + RegisterInfo orig_ax = {"orig_eax", + NULL, + sizeof(((GPR *)NULL)->orig_eax), + (LLVM_EXTENSION offsetof(GPR, orig_eax)), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}; + d_register_infos.push_back(orig_ax); } -size_t -RegisterContextLinux_i386::GetGPRSize() const -{ - return sizeof(GPR); -} +size_t RegisterContextLinux_i386::GetGPRSize() const { return sizeof(GPR); } -const RegisterInfo * -RegisterContextLinux_i386::GetRegisterInfo() const -{ - switch (m_target_arch.GetMachine()) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - return g_register_infos_i386; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const { + switch (m_target_arch.GetMachine()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + return g_register_infos_i386; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } -uint32_t -RegisterContextLinux_i386::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0])); +uint32_t RegisterContextLinux_i386::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_i386) / + sizeof(g_register_infos_i386[0])); } -uint32_t -RegisterContextLinux_i386::GetUserRegisterCount () const -{ - return static_cast<uint32_t> (k_num_user_registers_i386); +uint32_t RegisterContextLinux_i386::GetUserRegisterCount() const { + return static_cast<uint32_t>(k_num_user_registers_i386); } const std::vector<lldb_private::RegisterInfo> * -RegisterContextLinux_i386::GetDynamicRegisterInfoP() const -{ - return &d_register_infos; +RegisterContextLinux_i386::GetDynamicRegisterInfoP() const { + return &d_register_infos; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index 6c4768f49ac..fbf803789cc 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -12,29 +12,23 @@ #include "RegisterInfoInterface.h" -class RegisterContextLinux_i386 - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_i386 : public lldb_private::RegisterInfoInterface { public: - RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch); + RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; - uint32_t - GetUserRegisterCount () const override; + uint32_t GetUserRegisterCount() const override; - const std::vector<lldb_private::RegisterInfo> * - GetDynamicRegisterInfoP() const override; + const std::vector<lldb_private::RegisterInfo> * + GetDynamicRegisterInfoP() const override; private: - std::vector<lldb_private::RegisterInfo> d_register_infos; + std::vector<lldb_private::RegisterInfo> d_register_infos; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp index 1b2281004d2..982eefea9ba 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp @@ -7,8 +7,8 @@ // //===---------------------------------------------------------------------===// -#include <vector> #include <stddef.h> +#include <vector> // For eh_frame and DWARF Register numbers #include "RegisterContextLinux_mips.h" @@ -29,48 +29,38 @@ using namespace lldb; #include "RegisterInfos_mips.h" #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT -uint32_t -GetUserRegisterInfoCount (bool msa_present) -{ - if (msa_present) - return static_cast<uint32_t> (k_num_user_registers_mips); - return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips); +uint32_t GetUserRegisterInfoCount(bool msa_present) { + if (msa_present) + return static_cast<uint32_t>(k_num_user_registers_mips); + return static_cast<uint32_t>(k_num_user_registers_mips - + k_num_msa_registers_mips); } -RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch, bool msa_present) : - RegisterInfoInterface(target_arch), - m_user_register_count (GetUserRegisterInfoCount (msa_present)) -{ -} +RegisterContextLinux_mips::RegisterContextLinux_mips( + const ArchSpec &target_arch, bool msa_present) + : RegisterInfoInterface(target_arch), + m_user_register_count(GetUserRegisterInfoCount(msa_present)) {} -size_t -RegisterContextLinux_mips::GetGPRSize() const -{ - return sizeof(GPR_linux_mips); +size_t RegisterContextLinux_mips::GetGPRSize() const { + return sizeof(GPR_linux_mips); } -const RegisterInfo * -RegisterContextLinux_mips::GetRegisterInfo() const -{ - switch (m_target_arch.GetMachine()) - { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return g_register_infos_mips; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const { + switch (m_target_arch.GetMachine()) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return g_register_infos_mips; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } } -uint32_t -RegisterContextLinux_mips::GetRegisterCount () const -{ - return static_cast<uint32_t> (sizeof (g_register_infos_mips) / sizeof (g_register_infos_mips [0])); +uint32_t RegisterContextLinux_mips::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_mips) / + sizeof(g_register_infos_mips[0])); } -uint32_t -RegisterContextLinux_mips::GetUserRegisterCount () const -{ - return static_cast<uint32_t> (m_user_register_count); +uint32_t RegisterContextLinux_mips::GetUserRegisterCount() const { + return static_cast<uint32_t>(m_user_register_count); } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h index c0bd5ad4f4f..cba4ee6cd2b 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h @@ -10,29 +10,24 @@ #ifndef liblldb_RegisterContextLinux_mips_H_ #define liblldb_RegisterContextLinux_mips_H_ -#include "lldb/lldb-private.h" #include "RegisterInfoInterface.h" +#include "lldb/lldb-private.h" -class RegisterContextLinux_mips - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_mips : public lldb_private::RegisterInfoInterface { public: - RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, bool msa_present = true); + RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, + bool msa_present = true); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; - uint32_t - GetUserRegisterCount () const override; + uint32_t GetUserRegisterCount() const override; private: - uint32_t m_user_register_count; + uint32_t m_user_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp index f2871e3b735..c40f6949262 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp @@ -7,10 +7,10 @@ // //===---------------------------------------------------------------------===// -#if defined (__mips__) +#if defined(__mips__) -#include <vector> #include <stddef.h> +#include <vector> // For eh_frame and DWARF Register numbers #include "RegisterContextLinux_mips64.h" @@ -25,7 +25,8 @@ using namespace lldb; using namespace lldb_private; //--------------------------------------------------------------------------- -// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 structure. +// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 +// structure. //--------------------------------------------------------------------------- #define DECLARE_REGISTER_INFOS_MIPS64_STRUCT #define LINUX_MIPS64 @@ -40,91 +41,79 @@ using namespace lldb_private; #include "RegisterInfos_mips.h" #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT -static const RegisterInfo * -GetRegisterInfoPtr (const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return g_register_infos_mips64; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return g_register_infos_mips; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return g_register_infos_mips64; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return g_register_infos_mips; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } -static uint32_t -GetRegisterInfoCount (const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return static_cast<uint32_t> (sizeof (g_register_infos_mips64) / sizeof (g_register_infos_mips64 [0])); - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return static_cast<uint32_t> (sizeof (g_register_infos_mips) / sizeof (g_register_infos_mips [0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return static_cast<uint32_t>(sizeof(g_register_infos_mips64) / + sizeof(g_register_infos_mips64[0])); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return static_cast<uint32_t>(sizeof(g_register_infos_mips) / + sizeof(g_register_infos_mips[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -uint32_t -GetUserRegisterInfoCount (const ArchSpec &target_arch, bool msa_present) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - if (msa_present) - return static_cast<uint32_t> (k_num_user_registers_mips); - return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips); - case llvm::Triple::mips64el: - case llvm::Triple::mips64: - if (msa_present) - return static_cast<uint32_t> (k_num_user_registers_mips64); - return static_cast<uint32_t> (k_num_user_registers_mips64 - k_num_msa_registers_mips64); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch, + bool msa_present) { + switch (target_arch.GetMachine()) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + if (msa_present) + return static_cast<uint32_t>(k_num_user_registers_mips); + return static_cast<uint32_t>(k_num_user_registers_mips - + k_num_msa_registers_mips); + case llvm::Triple::mips64el: + case llvm::Triple::mips64: + if (msa_present) + return static_cast<uint32_t>(k_num_user_registers_mips64); + return static_cast<uint32_t>(k_num_user_registers_mips64 - + k_num_msa_registers_mips64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch, bool msa_present) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p (GetRegisterInfoPtr (target_arch)), - m_register_info_count (GetRegisterInfoCount (target_arch)), - m_user_register_count (GetUserRegisterInfoCount (target_arch, msa_present)) -{ -} +RegisterContextLinux_mips64::RegisterContextLinux_mips64( + const ArchSpec &target_arch, bool msa_present) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)), + m_user_register_count( + GetUserRegisterInfoCount(target_arch, msa_present)) {} -size_t -RegisterContextLinux_mips64::GetGPRSize() const -{ - return sizeof(GPR_linux_mips); +size_t RegisterContextLinux_mips64::GetGPRSize() const { + return sizeof(GPR_linux_mips); } -const RegisterInfo * -RegisterContextLinux_mips64::GetRegisterInfo() const -{ - return m_register_info_p; +const RegisterInfo *RegisterContextLinux_mips64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextLinux_mips64::GetRegisterCount () const -{ - return m_register_info_count; +uint32_t RegisterContextLinux_mips64::GetRegisterCount() const { + return m_register_info_count; } -uint32_t -RegisterContextLinux_mips64::GetUserRegisterCount () const -{ - return m_user_register_count; +uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const { + return m_user_register_count; } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h index 843328c92e4..9669b0d8499 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h @@ -7,36 +7,31 @@ // //===----------------------------------------------------------------------===// -#if defined (__mips__) +#if defined(__mips__) #ifndef liblldb_RegisterContextLinux_mips64_H_ #define liblldb_RegisterContextLinux_mips64_H_ -#include "lldb/lldb-private.h" #include "RegisterInfoInterface.h" +#include "lldb/lldb-private.h" -class RegisterContextLinux_mips64 - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_mips64 : public lldb_private::RegisterInfoInterface { public: - RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, bool msa_present = true); + RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, + bool msa_present = true); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; - uint32_t - GetUserRegisterCount () const override; + uint32_t GetUserRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; - uint32_t m_user_register_count; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; + uint32_t m_user_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp index 9aef1e9830e..5a7f5a12524 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "RegisterContextPOSIX_s390x.h" #include "RegisterContextLinux_s390x.h" +#include "RegisterContextPOSIX_s390x.h" using namespace lldb_private; using namespace lldb; @@ -20,79 +20,58 @@ using namespace lldb; #include "RegisterInfos_s390x.h" #undef DECLARE_REGISTER_INFOS_S390X_STRUCT -static const RegisterInfo * -GetRegisterInfoPtr(const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: - return g_register_infos_s390x; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::systemz: + return g_register_infos_s390x; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } -static uint32_t -GetRegisterInfoCount(const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: - return k_num_registers_s390x; - default: - assert(false && "Unhandled target architecture."); - return 0; - } +static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::systemz: + return k_num_registers_s390x; + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -static uint32_t -GetUserRegisterInfoCount(const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: - return k_num_user_registers_s390x + k_num_linux_registers_s390x; - default: - assert(false && "Unhandled target architecture."); - return 0; - } +static uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::systemz: + return k_num_user_registers_s390x + k_num_linux_registers_s390x; + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextLinux_s390x::RegisterContextLinux_s390x(const ArchSpec &target_arch) +RegisterContextLinux_s390x::RegisterContextLinux_s390x( + const ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p(GetRegisterInfoPtr(target_arch)), m_register_info_count(GetRegisterInfoCount(target_arch)), - m_user_register_count(GetUserRegisterInfoCount(target_arch)) -{ -} + m_user_register_count(GetUserRegisterInfoCount(target_arch)) {} const std::vector<lldb_private::RegisterInfo> * -RegisterContextLinux_s390x::GetDynamicRegisterInfoP() const -{ - return &d_register_infos; +RegisterContextLinux_s390x::GetDynamicRegisterInfoP() const { + return &d_register_infos; } -const RegisterInfo * -RegisterContextLinux_s390x::GetRegisterInfo() const -{ - return m_register_info_p; +const RegisterInfo *RegisterContextLinux_s390x::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextLinux_s390x::GetRegisterCount() const -{ - return m_register_info_count; +uint32_t RegisterContextLinux_s390x::GetRegisterCount() const { + return m_register_info_count; } -uint32_t -RegisterContextLinux_s390x::GetUserRegisterCount() const -{ - return m_user_register_count; +uint32_t RegisterContextLinux_s390x::GetUserRegisterCount() const { + return m_user_register_count; } -size_t -RegisterContextLinux_s390x::GetGPRSize() const -{ - return 0; -} +size_t RegisterContextLinux_s390x::GetGPRSize() const { return 0; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h index bdc7f34f62e..556cc2e1248 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h @@ -12,31 +12,26 @@ #include "RegisterInfoInterface.h" -class RegisterContextLinux_s390x : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_s390x : public lldb_private::RegisterInfoInterface { public: - RegisterContextLinux_s390x(const lldb_private::ArchSpec &target_arch); + RegisterContextLinux_s390x(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount() const override; + uint32_t GetRegisterCount() const override; - uint32_t - GetUserRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; - const std::vector<lldb_private::RegisterInfo> * - GetDynamicRegisterInfoP() const override; + const std::vector<lldb_private::RegisterInfo> * + GetDynamicRegisterInfoP() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; - uint32_t m_user_register_count; - std::vector<lldb_private::RegisterInfo> d_register_infos; + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; + uint32_t m_user_register_count; + std::vector<lldb_private::RegisterInfo> d_register_infos; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index aa217d68747..526b3eca81a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -7,201 +7,191 @@ // //===---------------------------------------------------------------------===// -#include <vector> -#include "RegisterContextPOSIX_x86.h" -#include "RegisterContextLinux_i386.h" #include "RegisterContextLinux_x86_64.h" +#include "RegisterContextLinux_i386.h" +#include "RegisterContextPOSIX_x86.h" +#include <vector> using namespace lldb_private; using namespace lldb; -typedef struct _GPR -{ - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t rbp; - uint64_t rbx; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rax; - uint64_t rcx; - uint64_t rdx; - uint64_t rsi; - uint64_t rdi; - uint64_t orig_rax; - uint64_t rip; - uint64_t cs; - uint64_t rflags; - uint64_t rsp; - uint64_t ss; - uint64_t fs_base; - uint64_t gs_base; - uint64_t ds; - uint64_t es; - uint64_t fs; - uint64_t gs; +typedef struct _GPR { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t rbp; + uint64_t rbx; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t orig_rax; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; + uint64_t fs_base; + uint64_t gs_base; + uint64_t ds; + uint64_t es; + uint64_t fs; + uint64_t gs; } GPR; struct DBG { - uint64_t dr[8]; + uint64_t dr[8]; }; -struct UserArea -{ - GPR gpr; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - int32_t pad0; - FXSAVE fpr; // General purpose floating point registers (see FPR for extended register sets). - uint64_t tsize; // Text segment size. - uint64_t dsize; // Data segment size. - uint64_t ssize; // Stack segment size. - uint64_t start_code; // VM address of text. - uint64_t start_stack; // VM address of stack bottom (top in rsp). - int64_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - int32_t pad1; - uint64_t ar0; // Location of GPR's. - FXSAVE* fpstate; // Location of FPR's. - uint64_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - DBG dbg; // Debug registers. - uint64_t error_code; // CPU error code. - uint64_t fault_address; // Control register CR3. +struct UserArea { + GPR gpr; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + int32_t pad0; + FXSAVE fpr; // General purpose floating point registers (see FPR for extended + // register sets). + uint64_t tsize; // Text segment size. + uint64_t dsize; // Data segment size. + uint64_t ssize; // Stack segment size. + uint64_t start_code; // VM address of text. + uint64_t start_stack; // VM address of stack bottom (top in rsp). + int64_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + int32_t pad1; + uint64_t ar0; // Location of GPR's. + FXSAVE *fpstate; // Location of FPR's. + uint64_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + DBG dbg; // Debug registers. + uint64_t error_code; // CPU error code. + uint64_t fault_address; // Control register CR3. }; - -#define DR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, dbg) + \ - LLVM_EXTENSION offsetof(DBG, dr[reg_index])) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, dbg) + \ + LLVM_EXTENSION offsetof(DBG, dr[reg_index])) //--------------------------------------------------------------------------- -// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure. +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 +// structure. //--------------------------------------------------------------------------- #define DECLARE_REGISTER_INFOS_X86_64_STRUCT #include "RegisterInfos_x86_64.h" #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT -static std::vector<lldb_private::RegisterInfo>& -GetPrivateRegisterInfoVector () -{ - static std::vector<lldb_private::RegisterInfo> g_register_infos; - return g_register_infos; +static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() { + static std::vector<lldb_private::RegisterInfo> g_register_infos; + return g_register_infos; } static const RegisterInfo * -GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) -{ - std::vector<lldb_private::RegisterInfo> &g_register_infos = GetPrivateRegisterInfoVector (); - - // Allocate RegisterInfo only once - if (g_register_infos.empty()) - { - // Copy the register information from base class - std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch)); - const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); - g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]); - - //--------------------------------------------------------------------------- - // Include RegisterInfos_x86_64 to update the g_register_infos structure - // with x86_64 offsets. - //--------------------------------------------------------------------------- - #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS - #include "RegisterInfos_x86_64.h" - #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS - } - - return &g_register_infos[0]; -} +GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) { + std::vector<lldb_private::RegisterInfo> &g_register_infos = + GetPrivateRegisterInfoVector(); + + // Allocate RegisterInfo only once + if (g_register_infos.empty()) { + // Copy the register information from base class + std::unique_ptr<RegisterContextLinux_i386> reg_interface( + new RegisterContextLinux_i386(arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], + &base_info[k_num_registers_i386]); -static const RegisterInfo * -GetRegisterInfoPtr (const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86: - return GetRegisterInfo_i386 (target_arch); - case llvm::Triple::x86_64: - return g_register_infos_x86_64; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +//--------------------------------------------------------------------------- +// Include RegisterInfos_x86_64 to update the g_register_infos structure +// with x86_64 offsets. +//--------------------------------------------------------------------------- +#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS +#include "RegisterInfos_x86_64.h" +#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + } + + return &g_register_infos[0]; } -static uint32_t -GetRegisterInfoCount (const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86: - { - assert (!GetPrivateRegisterInfoVector ().empty () && "i386 register info not yet filled."); - return static_cast<uint32_t> (GetPrivateRegisterInfoVector ().size ()); - } - case llvm::Triple::x86_64: - return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return GetRegisterInfo_i386(target_arch); + case llvm::Triple::x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } -static uint32_t -GetUserRegisterInfoCount (const ArchSpec &target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86: - return static_cast<uint32_t> (k_num_user_registers_i386); - case llvm::Triple::x86_64: - return static_cast<uint32_t> (k_num_user_registers_x86_64); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: { + assert(!GetPrivateRegisterInfoVector().empty() && + "i386 register info not yet filled."); + return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size()); + } + case llvm::Triple::x86_64: + return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / + sizeof(g_register_infos_x86_64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p (GetRegisterInfoPtr (target_arch)), - m_register_info_count (GetRegisterInfoCount (target_arch)), - m_user_register_count (GetUserRegisterInfoCount (target_arch)) -{ - RegisterInfo orig_ax = { "orig_rax", NULL, sizeof(((GPR*)NULL)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr, nullptr, 0 }; - d_register_infos.push_back(orig_ax); +static uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86: + return static_cast<uint32_t>(k_num_user_registers_i386); + case llvm::Triple::x86_64: + return static_cast<uint32_t>(k_num_user_registers_x86_64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -size_t -RegisterContextLinux_x86_64::GetGPRSize() const -{ - return sizeof(GPR); +RegisterContextLinux_x86_64::RegisterContextLinux_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)), + m_user_register_count(GetUserRegisterInfoCount(target_arch)) { + RegisterInfo orig_ax = {"orig_rax", + NULL, + sizeof(((GPR *)NULL)->orig_rax), + (LLVM_EXTENSION offsetof(GPR, orig_rax)), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}; + d_register_infos.push_back(orig_ax); } +size_t RegisterContextLinux_x86_64::GetGPRSize() const { return sizeof(GPR); } + const std::vector<lldb_private::RegisterInfo> * -RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const -{ - return &d_register_infos; +RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const { + return &d_register_infos; } -const RegisterInfo * -RegisterContextLinux_x86_64::GetRegisterInfo() const -{ - return m_register_info_p; +const RegisterInfo *RegisterContextLinux_x86_64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextLinux_x86_64::GetRegisterCount () const -{ - return m_register_info_count; +uint32_t RegisterContextLinux_x86_64::GetRegisterCount() const { + return m_register_info_count; } -uint32_t -RegisterContextLinux_x86_64::GetUserRegisterCount () const -{ - return m_user_register_count; +uint32_t RegisterContextLinux_x86_64::GetUserRegisterCount() const { + return m_user_register_count; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index ed0b7de9aae..99a4cb73679 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -12,33 +12,26 @@ #include "RegisterInfoInterface.h" -class RegisterContextLinux_x86_64 - : public lldb_private::RegisterInfoInterface -{ +class RegisterContextLinux_x86_64 : public lldb_private::RegisterInfoInterface { public: - RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch); + RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; - uint32_t - GetUserRegisterCount () const override; + uint32_t GetUserRegisterCount() const override; - const std::vector<lldb_private::RegisterInfo> * - GetDynamicRegisterInfoP() const override; + const std::vector<lldb_private::RegisterInfo> * + GetDynamicRegisterInfoP() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; - uint32_t m_user_register_count; - std::vector<lldb_private::RegisterInfo> d_register_infos; - + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; + uint32_t m_user_register_count; + std::vector<lldb_private::RegisterInfo> d_register_infos; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp index a2ab67438b7..03f7a6272f4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp @@ -27,181 +27,143 @@ using namespace lldb_private; //---------------------------------------------------------------------- // RegisterContextMacOSXFrameBackchain constructor //---------------------------------------------------------------------- -RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain -( - Thread &thread, - uint32_t concrete_frame_idx, - const UnwindMacOSXFrameBackchain::Cursor &cursor -) : - RegisterContext (thread, concrete_frame_idx), - m_cursor (cursor), - m_cursor_is_valid (true) -{ -} +RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain( + Thread &thread, uint32_t concrete_frame_idx, + const UnwindMacOSXFrameBackchain::Cursor &cursor) + : RegisterContext(thread, concrete_frame_idx), m_cursor(cursor), + m_cursor_is_valid(true) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() -{ -} +RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() {} -void -RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters () -{ - m_cursor_is_valid = false; +void RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters() { + m_cursor_is_valid = false; } -size_t -RegisterContextMacOSXFrameBackchain::GetRegisterCount () -{ - return m_thread.GetRegisterContext()->GetRegisterCount(); +size_t RegisterContextMacOSXFrameBackchain::GetRegisterCount() { + return m_thread.GetRegisterContext()->GetRegisterCount(); } const RegisterInfo * -RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg) -{ - return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); +RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex(size_t reg) { + return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); } -size_t -RegisterContextMacOSXFrameBackchain::GetRegisterSetCount () -{ - return m_thread.GetRegisterContext()->GetRegisterSetCount(); +size_t RegisterContextMacOSXFrameBackchain::GetRegisterSetCount() { + return m_thread.GetRegisterContext()->GetRegisterSetCount(); } - - const RegisterSet * -RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set) -{ - return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); +RegisterContextMacOSXFrameBackchain::GetRegisterSet(size_t reg_set) { + return m_thread.GetRegisterContext()->GetRegisterSet(reg_set); } +bool RegisterContextMacOSXFrameBackchain::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (!m_cursor_is_valid) + return false; + + uint64_t reg_value = LLDB_INVALID_ADDRESS; + switch (reg_info->kinds[eRegisterKindGeneric]) { + case LLDB_REGNUM_GENERIC_PC: + if (m_cursor.pc == LLDB_INVALID_ADDRESS) + return false; + reg_value = m_cursor.pc; + break; -bool -RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info, - RegisterValue &value) -{ - if (!m_cursor_is_valid) - return false; - - uint64_t reg_value = LLDB_INVALID_ADDRESS; - - switch (reg_info->kinds[eRegisterKindGeneric]) - { - case LLDB_REGNUM_GENERIC_PC: - if (m_cursor.pc == LLDB_INVALID_ADDRESS) - return false; - reg_value = m_cursor.pc; - break; - - case LLDB_REGNUM_GENERIC_FP: - if (m_cursor.fp == LLDB_INVALID_ADDRESS) - return false; - reg_value = m_cursor.fp; - break; - - default: - return false; - } - - switch (reg_info->encoding) - { - case eEncodingInvalid: - case eEncodingVector: - break; - - case eEncodingUint: - case eEncodingSint: - value.SetUInt(reg_value, reg_info->byte_size); + case LLDB_REGNUM_GENERIC_FP: + if (m_cursor.fp == LLDB_INVALID_ADDRESS) + return false; + reg_value = m_cursor.fp; + break; + + default: + return false; + } + + switch (reg_info->encoding) { + case eEncodingInvalid: + case eEncodingVector: + break; + + case eEncodingUint: + case eEncodingSint: + value.SetUInt(reg_value, reg_info->byte_size); + return true; + + case eEncodingIEEE754: + switch (reg_info->byte_size) { + case sizeof(float): + if (sizeof(float) == sizeof(uint32_t)) { + value.SetUInt32(reg_value, RegisterValue::eTypeFloat); + return true; + } else if (sizeof(float) == sizeof(uint64_t)) { + value.SetUInt64(reg_value, RegisterValue::eTypeFloat); return true; + } + break; - case eEncodingIEEE754: - switch (reg_info->byte_size) - { - case sizeof (float): - if (sizeof (float) == sizeof(uint32_t)) - { - value.SetUInt32(reg_value, RegisterValue::eTypeFloat); - return true; - } - else if (sizeof (float) == sizeof(uint64_t)) - { - value.SetUInt64(reg_value, RegisterValue::eTypeFloat); - return true; - } - break; - - case sizeof (double): - if (sizeof (double) == sizeof(uint32_t)) - { - value.SetUInt32(reg_value, RegisterValue::eTypeDouble); - return true; - } - else if (sizeof (double) == sizeof(uint64_t)) - { - value.SetUInt64(reg_value, RegisterValue::eTypeDouble); - return true; - } - break; - - // TOOD: need a better way to detect when "long double" types are - // the same bytes size as "double" -#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \ - !defined(__mips__) && !defined(__powerpc__) && !defined(__ANDROID_NDK__) - case sizeof (long double): - if (sizeof (long double) == sizeof(uint32_t)) - { - value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble); - return true; - } - else if (sizeof (long double) == sizeof(uint64_t)) - { - value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble); - return true; - } - break; + case sizeof(double): + if (sizeof(double) == sizeof(uint32_t)) { + value.SetUInt32(reg_value, RegisterValue::eTypeDouble); + return true; + } else if (sizeof(double) == sizeof(uint64_t)) { + value.SetUInt64(reg_value, RegisterValue::eTypeDouble); + return true; + } + break; + +// TOOD: need a better way to detect when "long double" types are +// the same bytes size as "double" +#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && \ + !defined(_MSC_VER) && !defined(__mips__) && !defined(__powerpc__) && \ + !defined(__ANDROID_NDK__) + case sizeof(long double): + if (sizeof(long double) == sizeof(uint32_t)) { + value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble); + return true; + } else if (sizeof(long double) == sizeof(uint64_t)) { + value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble); + return true; + } + break; #endif - } - break; } - return false; + break; + } + return false; } -bool -RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - // Not supported yet. We could easily add support for this by remembering - // the address of each entry (it would need to be part of the cursor) - return false; +bool RegisterContextMacOSXFrameBackchain::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + // Not supported yet. We could easily add support for this by remembering + // the address of each entry (it would need to be part of the cursor) + return false; } -bool -RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - // libunwind frames can't handle this it doesn't always have all register - // values. This call should only be called on frame zero anyway so there - // shouldn't be any problem - return false; +bool RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + // libunwind frames can't handle this it doesn't always have all register + // values. This call should only be called on frame zero anyway so there + // shouldn't be any problem + return false; } -bool -RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - // Since this class doesn't respond to "ReadAllRegisterValues()", it must - // not have been the one that saved all the register values. So we just let - // the thread's register context (the register context for frame zero) do - // the writing. - return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp); +bool RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + // Since this class doesn't respond to "ReadAllRegisterValues()", it must + // not have been the one that saved all the register values. So we just let + // the thread's register context (the register context for frame zero) do + // the writing. + return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp); } - uint32_t -RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); +RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + kind, num); } - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h index 0ddadbed01e..4f5816aa490 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h @@ -14,57 +14,48 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" #include "UnwindMacOSXFrameBackchain.h" -class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext -{ +class RegisterContextMacOSXFrameBackchain + : public lldb_private::RegisterContext { public: - RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - const UnwindMacOSXFrameBackchain::Cursor &cursor); + RegisterContextMacOSXFrameBackchain( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + const UnwindMacOSXFrameBackchain::Cursor &cursor); + + ~RegisterContextMacOSXFrameBackchain() override; + + void InvalidateAllRegisters() override; - ~RegisterContextMacOSXFrameBackchain() override; + size_t GetRegisterCount() override; - void - InvalidateAllRegisters() override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; - size_t - GetRegisterSetCount() override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t reg_set) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - private: - UnwindMacOSXFrameBackchain::Cursor m_cursor; - bool m_cursor_is_valid; + UnwindMacOSXFrameBackchain::Cursor m_cursor; + bool m_cursor_is_valid; - DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain); + DISALLOW_COPY_AND_ASSIGN(RegisterContextMacOSXFrameBackchain); }; #endif // lldb_RegisterContextMacOSXFrameBackchain_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp index 7ceb536272f..a4cf0771019 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp @@ -22,66 +22,50 @@ using namespace lldb; using namespace lldb_private; +RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextDarwin_arm(thread, concrete_frame_idx) {} -RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_arm (thread, concrete_frame_idx) -{ -} - -RegisterContextMach_arm::~RegisterContextMach_arm() -{ -} +RegisterContextMach_arm::~RegisterContextMach_arm() {} -int -RegisterContextMach_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - mach_msg_type_number_t count = GPRWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); +int RegisterContextMach_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } -int -RegisterContextMach_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - mach_msg_type_number_t count = FPUWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); +int RegisterContextMach_arm::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } -int -RegisterContextMach_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - mach_msg_type_number_t count = EXCWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); +int RegisterContextMach_arm::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } -int -RegisterContextMach_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) -{ - mach_msg_type_number_t count = DBGWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&dbg, &count); +int RegisterContextMach_arm::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { + mach_msg_type_number_t count = DBGWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&dbg, &count); } -int -RegisterContextMach_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); +int RegisterContextMach_arm::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } -int -RegisterContextMach_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); +int RegisterContextMach_arm::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } -int -RegisterContextMach_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); +int RegisterContextMach_arm::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } -int -RegisterContextMach_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount); +int RegisterContextMach_arm::DoWriteDBG(lldb::tid_t tid, int flavor, + const DBG &dbg) { + return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount); } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h index e97a4bfff2b..a2cf6bfcbe4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h @@ -17,40 +17,29 @@ // Project includes #include "RegisterContextDarwin_arm.h" -class RegisterContextMach_arm : public RegisterContextDarwin_arm -{ +class RegisterContextMach_arm : public RegisterContextDarwin_arm { public: + RegisterContextMach_arm(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); - RegisterContextMach_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx); - - virtual - ~RegisterContextMach_arm(); + virtual ~RegisterContextMach_arm(); protected: + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); - - int - DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg); + int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); }; -#endif // liblldb_RegisterContextMach_arm_h_ +#endif // liblldb_RegisterContextMach_arm_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp index 3d6c9a6baca..959149edbc3 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp @@ -20,53 +20,40 @@ using namespace lldb; using namespace lldb_private; +RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextDarwin_i386(thread, concrete_frame_idx) {} -RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_i386 (thread, concrete_frame_idx) -{ -} - -RegisterContextMach_i386::~RegisterContextMach_i386() -{ -} +RegisterContextMach_i386::~RegisterContextMach_i386() {} -int -RegisterContextMach_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - mach_msg_type_number_t count = GPRWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); +int RegisterContextMach_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } -int -RegisterContextMach_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - mach_msg_type_number_t count = FPUWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); +int RegisterContextMach_i386::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } -int -RegisterContextMach_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - mach_msg_type_number_t count = EXCWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); +int RegisterContextMach_i386::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } -int -RegisterContextMach_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); +int RegisterContextMach_i386::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } -int -RegisterContextMach_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); +int RegisterContextMach_i386::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } -int -RegisterContextMach_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); +int RegisterContextMach_i386::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h index ad0f69d1c05..8ac693a5558 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h @@ -16,34 +16,25 @@ // Project includes #include "RegisterContextDarwin_i386.h" -class RegisterContextMach_i386 : public RegisterContextDarwin_i386 -{ +class RegisterContextMach_i386 : public RegisterContextDarwin_i386 { public: - - RegisterContextMach_i386(lldb_private::Thread &thread, uint32_t concrete_frame_idx); - - virtual - ~RegisterContextMach_i386(); - + RegisterContextMach_i386(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + virtual ~RegisterContextMach_i386(); + protected: - - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); }; -#endif // liblldb_RegisterContextMach_i386_h_ +#endif // liblldb_RegisterContextMach_i386_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp index f03685e1313..522b73a2888 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp @@ -20,53 +20,43 @@ using namespace lldb; using namespace lldb_private; +RegisterContextMach_x86_64::RegisterContextMach_x86_64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextDarwin_x86_64(thread, concrete_frame_idx) {} -RegisterContextMach_x86_64::RegisterContextMach_x86_64(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContextDarwin_x86_64 (thread, concrete_frame_idx) -{ -} - -RegisterContextMach_x86_64::~RegisterContextMach_x86_64() -{ -} +RegisterContextMach_x86_64::~RegisterContextMach_x86_64() {} -int -RegisterContextMach_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) -{ - mach_msg_type_number_t count = GPRWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); +int RegisterContextMach_x86_64::DoReadGPR(lldb::tid_t tid, int flavor, + GPR &gpr) { + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } -int -RegisterContextMach_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) -{ - mach_msg_type_number_t count = FPUWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); +int RegisterContextMach_x86_64::DoReadFPU(lldb::tid_t tid, int flavor, + FPU &fpu) { + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } -int -RegisterContextMach_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) -{ - mach_msg_type_number_t count = EXCWordCount; - return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); +int RegisterContextMach_x86_64::DoReadEXC(lldb::tid_t tid, int flavor, + EXC &exc) { + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } -int -RegisterContextMach_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); +int RegisterContextMach_x86_64::DoWriteGPR(lldb::tid_t tid, int flavor, + const GPR &gpr) { + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } -int -RegisterContextMach_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); +int RegisterContextMach_x86_64::DoWriteFPU(lldb::tid_t tid, int flavor, + const FPU &fpu) { + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } -int -RegisterContextMach_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) -{ - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); +int RegisterContextMach_x86_64::DoWriteEXC(lldb::tid_t tid, int flavor, + const EXC &exc) { + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h index 9e6dfa39550..cd425046b08 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h @@ -1,4 +1,5 @@ -//===-- RegisterContextMach_x86_64.h ------------------------------*- C++ -*-===// +//===-- RegisterContextMach_x86_64.h ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,34 +17,25 @@ // Project includes #include "RegisterContextDarwin_x86_64.h" -class RegisterContextMach_x86_64 : public RegisterContextDarwin_x86_64 -{ +class RegisterContextMach_x86_64 : public RegisterContextDarwin_x86_64 { public: - - RegisterContextMach_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx); - - virtual - ~RegisterContextMach_x86_64(); - + RegisterContextMach_x86_64(lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + virtual ~RegisterContextMach_x86_64(); + protected: - - virtual int - DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); - - int - DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); - - int - DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); - - int - DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); - - int - DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); - - int - DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); + virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); + + int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); + + int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); + + int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); + + int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); + + int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); }; -#endif // liblldb_RegisterContextMach_x86_64_h_ +#endif // liblldb_RegisterContextMach_x86_64_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp index 40d00b1eed8..57966e1729a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp @@ -26,149 +26,123 @@ using namespace lldb_private; //---------------------------------------------------------------------- // RegisterContextMemory constructor //---------------------------------------------------------------------- -RegisterContextMemory::RegisterContextMemory -( - Thread &thread, - uint32_t concrete_frame_idx, - DynamicRegisterInfo ®_infos, - addr_t reg_data_addr -) : - RegisterContext (thread, concrete_frame_idx), - m_reg_infos (reg_infos), - m_reg_valid (), - m_reg_data (), - m_reg_data_addr (reg_data_addr) -{ - // Resize our vector of bools to contain one bool for every register. - // We will use these boolean values to know when a register value - // is valid in m_reg_data. - const size_t num_regs = reg_infos.GetNumRegisters(); - assert (num_regs > 0); - m_reg_valid.resize (num_regs); - - // Make a heap based buffer that is big enough to store all registers - DataBufferSP reg_data_sp(new DataBufferHeap (reg_infos.GetRegisterDataByteSize(), 0)); - m_reg_data.SetData (reg_data_sp); +RegisterContextMemory::RegisterContextMemory(Thread &thread, + uint32_t concrete_frame_idx, + DynamicRegisterInfo ®_infos, + addr_t reg_data_addr) + : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos), + m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) { + // Resize our vector of bools to contain one bool for every register. + // We will use these boolean values to know when a register value + // is valid in m_reg_data. + const size_t num_regs = reg_infos.GetNumRegisters(); + assert(num_regs > 0); + m_reg_valid.resize(num_regs); + + // Make a heap based buffer that is big enough to store all registers + DataBufferSP reg_data_sp( + new DataBufferHeap(reg_infos.GetRegisterDataByteSize(), 0)); + m_reg_data.SetData(reg_data_sp); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -RegisterContextMemory::~RegisterContextMemory() -{ -} +RegisterContextMemory::~RegisterContextMemory() {} -void -RegisterContextMemory::InvalidateAllRegisters () -{ - if (m_reg_data_addr != LLDB_INVALID_ADDRESS) - SetAllRegisterValid (false); +void RegisterContextMemory::InvalidateAllRegisters() { + if (m_reg_data_addr != LLDB_INVALID_ADDRESS) + SetAllRegisterValid(false); } -void -RegisterContextMemory::SetAllRegisterValid (bool b) -{ - std::vector<bool>::iterator pos, end = m_reg_valid.end(); - for (pos = m_reg_valid.begin(); pos != end; ++pos) - *pos = b; +void RegisterContextMemory::SetAllRegisterValid(bool b) { + std::vector<bool>::iterator pos, end = m_reg_valid.end(); + for (pos = m_reg_valid.begin(); pos != end; ++pos) + *pos = b; } -size_t -RegisterContextMemory::GetRegisterCount () -{ - return m_reg_infos.GetNumRegisters (); +size_t RegisterContextMemory::GetRegisterCount() { + return m_reg_infos.GetNumRegisters(); } -const RegisterInfo * -RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg) -{ - return m_reg_infos.GetRegisterInfoAtIndex (reg); +const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) { + return m_reg_infos.GetRegisterInfoAtIndex(reg); } -size_t -RegisterContextMemory::GetRegisterSetCount () -{ - return m_reg_infos.GetNumRegisterSets (); +size_t RegisterContextMemory::GetRegisterSetCount() { + return m_reg_infos.GetNumRegisterSets(); } -const RegisterSet * -RegisterContextMemory::GetRegisterSet (size_t reg_set) -{ - return m_reg_infos.GetRegisterSet (reg_set); +const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) { + return m_reg_infos.GetRegisterSet(reg_set); } -uint32_t -RegisterContextMemory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num); +uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num); } -bool -RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; - if (!m_reg_valid[reg_num]) - { - if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ())) - return false; - } - const bool partial_data_ok = false; - return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success(); +bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; + if (!m_reg_valid[reg_num]) { + if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer())) + return false; + } + const bool partial_data_ok = false; + return reg_value + .SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, + partial_data_ok) + .Success(); } -bool -RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (m_reg_data_addr != LLDB_INVALID_ADDRESS) - { - const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; - addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset; - Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value)); - m_reg_valid[reg_num] = false; - return error.Success(); - } - return false; +bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) { + if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { + const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; + addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset; + Error error(WriteRegisterValueToMemory(reg_info, reg_addr, + reg_info->byte_size, reg_value)); + m_reg_valid[reg_num] = false; + return error.Success(); + } + return false; } -bool -RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp) -{ - if (m_reg_data_addr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize()) - { - SetAllRegisterValid (true); - return true; - } - } +bool RegisterContextMemory::ReadAllRegisterValues(DataBufferSP &data_sp) { + if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), + data_sp->GetByteSize(), + error) == data_sp->GetByteSize()) { + SetAllRegisterValid(true); + return true; + } } - return false; + } + return false; } -bool -RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp) -{ - if (m_reg_data_addr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (CalculateProcess()); - if (process_sp) - { - Error error; - SetAllRegisterValid (false); - if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize()) - return true; - } +bool RegisterContextMemory::WriteAllRegisterValues( + const DataBufferSP &data_sp) { + if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(CalculateProcess()); + if (process_sp) { + Error error; + SetAllRegisterValid(false); + if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), + data_sp->GetByteSize(), + error) == data_sp->GetByteSize()) + return true; } - return false; + } + return false; } -void -RegisterContextMemory::SetAllRegisterData (const lldb::DataBufferSP &data_sp) -{ - m_reg_data.SetData(data_sp); - SetAllRegisterValid (true); +void RegisterContextMemory::SetAllRegisterData( + const lldb::DataBufferSP &data_sp) { + m_reg_data.SetData(data_sp); + SetAllRegisterValid(true); } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h index d61aba9543d..55de0412b09 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h @@ -16,76 +16,65 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" class DynamicRegisterInfo; -class RegisterContextMemory : public lldb_private::RegisterContext -{ +class RegisterContextMemory : public lldb_private::RegisterContext { public: - RegisterContextMemory (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - DynamicRegisterInfo ®_info, - lldb::addr_t reg_data_addr); - - ~RegisterContextMemory() override; - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const lldb_private::RegisterSet * - GetRegisterSet(size_t reg_set) override; - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - //------------------------------------------------------------------ - // If all of the thread register are in a contiguous buffer in - // memory, then the default ReadRegister/WriteRegister and - // ReadAllRegisterValues/WriteAllRegisterValues will work. If thread - // registers are not contiguous, clients will want to subclass this - // class and modify the read/write functions as needed. - //------------------------------------------------------------------ - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue ®_value) override; - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue ®_value) override; - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - void - SetAllRegisterData (const lldb::DataBufferSP &data_sp); + RegisterContextMemory(lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + DynamicRegisterInfo ®_info, + lldb::addr_t reg_data_addr); + + ~RegisterContextMemory() override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + //------------------------------------------------------------------ + // If all of the thread register are in a contiguous buffer in + // memory, then the default ReadRegister/WriteRegister and + // ReadAllRegisterValues/WriteAllRegisterValues will work. If thread + // registers are not contiguous, clients will want to subclass this + // class and modify the read/write functions as needed. + //------------------------------------------------------------------ + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value) override; + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + void SetAllRegisterData(const lldb::DataBufferSP &data_sp); protected: - void - SetAllRegisterValid (bool b); + void SetAllRegisterValid(bool b); - DynamicRegisterInfo &m_reg_infos; - std::vector<bool> m_reg_valid; - lldb_private::DataExtractor m_reg_data; - lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory + DynamicRegisterInfo &m_reg_infos; + std::vector<bool> m_reg_valid; + lldb_private::DataExtractor m_reg_data; + lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register + // context that is stored in memmory private: - DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory); + DISALLOW_COPY_AND_ASSIGN(RegisterContextMemory); }; #endif // lldb_RegisterContextMemory_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp index 71ece160d4d..8ad00a6b769 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp @@ -12,41 +12,40 @@ #include "llvm/Support/Compiler.h" -#include "RegisterContextPOSIX_x86.h" #include "RegisterContextNetBSD_x86_64.h" +#include "RegisterContextPOSIX_x86.h" using namespace lldb_private; using namespace lldb; // src/sys/arch/amd64/include/frame_regs.h -typedef struct _GPR -{ - uint64_t rdi; /* 0 */ - uint64_t rsi; /* 1 */ - uint64_t rdx; /* 2 */ - uint64_t rcx; /* 3 */ - uint64_t r8; /* 4 */ - uint64_t r9; /* 5 */ - uint64_t r10; /* 6 */ - uint64_t r11; /* 7 */ - uint64_t r12; /* 8 */ - uint64_t r13; /* 9 */ - uint64_t r14; /* 10 */ - uint64_t r15; /* 11 */ - uint64_t rbp; /* 12 */ - uint64_t rbx; /* 13 */ - uint64_t rax; /* 14 */ - uint64_t gs; /* 15 */ - uint64_t fs; /* 16 */ - uint64_t es; /* 17 */ - uint64_t ds; /* 18 */ - uint64_t trapno; /* 19 */ - uint64_t err; /* 20 */ - uint64_t rip; /* 21 */ - uint64_t cs; /* 22 */ - uint64_t rflags; /* 23 */ - uint64_t rsp; /* 24 */ - uint64_t ss; /* 25 */ +typedef struct _GPR { + uint64_t rdi; /* 0 */ + uint64_t rsi; /* 1 */ + uint64_t rdx; /* 2 */ + uint64_t rcx; /* 3 */ + uint64_t r8; /* 4 */ + uint64_t r9; /* 5 */ + uint64_t r10; /* 6 */ + uint64_t r11; /* 7 */ + uint64_t r12; /* 8 */ + uint64_t r13; /* 9 */ + uint64_t r14; /* 10 */ + uint64_t r15; /* 11 */ + uint64_t rbp; /* 12 */ + uint64_t rbx; /* 13 */ + uint64_t rax; /* 14 */ + uint64_t gs; /* 15 */ + uint64_t fs; /* 16 */ + uint64_t es; /* 17 */ + uint64_t ds; /* 18 */ + uint64_t trapno; /* 19 */ + uint64_t err; /* 20 */ + uint64_t rip; /* 21 */ + uint64_t cs; /* 22 */ + uint64_t rflags; /* 23 */ + uint64_t rsp; /* 24 */ + uint64_t ss; /* 25 */ } GPR; /* @@ -65,38 +64,35 @@ typedef struct _GPR */ struct UserArea { - GPR gpr; - uint64_t mc_tlsbase; - FPR fpr; + GPR gpr; + uint64_t mc_tlsbase; + FPR fpr; }; - //--------------------------------------------------------------------------- // Cherry-pick parts of RegisterInfos_x86_64.h, without debug registers //--------------------------------------------------------------------------- // Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(GPR, regname)) +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) // Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(FXSAVE, regname)) +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, regname)) // Computes the offset of the YMM register assembled from register halves. // Based on DNBArchImplX86_64.cpp from debugserver -#define YMM_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + \ - (32 * reg_index)) +#define YMM_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) // Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) +#define FPR_SIZE(reg) sizeof(((FXSAVE *)NULL)->reg) // Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) +#define FP_SIZE sizeof(((MMSReg *)NULL)->bytes) // Number of bytes needed to represent an XMM register. #define XMM_SIZE sizeof(XMMReg) @@ -107,197 +103,229 @@ struct UserArea { // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB // Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, NULL, NULL } - -#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ - { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_x86_64 }, NULL, NULL } - -#define DEFINE_FP_ST(reg, i) \ - { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ - NULL, NULL } - -#define DEFINE_FP_MM(reg, i) \ - { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingUint, eFormatHex, \ - { dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_x86_64 }, \ - NULL, NULL } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64}, \ - NULL, NULL } - -#define DEFINE_YMM(reg, i) \ - { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64 }, \ - NULL, NULL } - -#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ - { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ - { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ - { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ - { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } - -static RegisterInfo -g_register_infos_x86_64[] = -{ - // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin - DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), - DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), - DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - DEFINE_GPR_PSEUDO_32(eax, rax), - DEFINE_GPR_PSEUDO_32(ebx, rbx), - DEFINE_GPR_PSEUDO_32(ecx, rcx), - DEFINE_GPR_PSEUDO_32(edx, rdx), - DEFINE_GPR_PSEUDO_32(edi, rdi), - DEFINE_GPR_PSEUDO_32(esi, rsi), - DEFINE_GPR_PSEUDO_32(ebp, rbp), - DEFINE_GPR_PSEUDO_32(esp, rsp), - DEFINE_GPR_PSEUDO_32(r8d, r8), - DEFINE_GPR_PSEUDO_32(r9d, r9), - DEFINE_GPR_PSEUDO_32(r10d, r10), - DEFINE_GPR_PSEUDO_32(r11d, r11), - DEFINE_GPR_PSEUDO_32(r12d, r12), - DEFINE_GPR_PSEUDO_32(r13d, r13), - DEFINE_GPR_PSEUDO_32(r14d, r14), - DEFINE_GPR_PSEUDO_32(r15d, r15), - DEFINE_GPR_PSEUDO_16(ax, rax), - DEFINE_GPR_PSEUDO_16(bx, rbx), - DEFINE_GPR_PSEUDO_16(cx, rcx), - DEFINE_GPR_PSEUDO_16(dx, rdx), - DEFINE_GPR_PSEUDO_16(di, rdi), - DEFINE_GPR_PSEUDO_16(si, rsi), - DEFINE_GPR_PSEUDO_16(bp, rbp), - DEFINE_GPR_PSEUDO_16(sp, rsp), - DEFINE_GPR_PSEUDO_16(r8w, r8), - DEFINE_GPR_PSEUDO_16(r9w, r9), - DEFINE_GPR_PSEUDO_16(r10w, r10), - DEFINE_GPR_PSEUDO_16(r11w, r11), - DEFINE_GPR_PSEUDO_16(r12w, r12), - DEFINE_GPR_PSEUDO_16(r13w, r13), - DEFINE_GPR_PSEUDO_16(r14w, r14), - DEFINE_GPR_PSEUDO_16(r15w, r15), - DEFINE_GPR_PSEUDO_8H(ah, rax), - DEFINE_GPR_PSEUDO_8H(bh, rbx), - DEFINE_GPR_PSEUDO_8H(ch, rcx), - DEFINE_GPR_PSEUDO_8H(dh, rdx), - DEFINE_GPR_PSEUDO_8L(al, rax), - DEFINE_GPR_PSEUDO_8L(bl, rbx), - DEFINE_GPR_PSEUDO_8L(cl, rcx), - DEFINE_GPR_PSEUDO_8L(dl, rdx), - DEFINE_GPR_PSEUDO_8L(dil, rdi), - DEFINE_GPR_PSEUDO_8L(sil, rsi), - DEFINE_GPR_PSEUDO_8L(bpl, rbp), - DEFINE_GPR_PSEUDO_8L(spl, rsp), - DEFINE_GPR_PSEUDO_8L(r8l, r8), - DEFINE_GPR_PSEUDO_8L(r9l, r9), - DEFINE_GPR_PSEUDO_8L(r10l, r10), - DEFINE_GPR_PSEUDO_8L(r11l, r11), - DEFINE_GPR_PSEUDO_8L(r12l, r12), - DEFINE_GPR_PSEUDO_8L(r13l, r13), - DEFINE_GPR_PSEUDO_8L(r14l, r14), - DEFINE_GPR_PSEUDO_8L(r15l, r15), - - // i387 Floating point registers. EH_frame, DWARF, Generic, Process Plugin - DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR *) NULL)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##reg##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { \ + #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##name##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_FP_ST(reg, i) \ + { \ + #reg #i, NULL, FP_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_FP_MM(reg, i) \ + { \ + #reg #i, NULL, sizeof(uint64_t), \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingUint, eFormatHex, \ + {dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_mm##i##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_XMM(reg, i) \ + { \ + #reg #i, NULL, XMM_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg##i##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_YMM(reg, i) \ + { \ + #reg #i, NULL, YMM_SIZE, \ + LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_##reg##i##h_x86_64, \ + dwarf_##reg##i##h_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg##i##_x86_64 }, \ + NULL, NULL \ + } + +#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ + { \ + #reg32, NULL, 4, \ + GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg32##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ + { \ + #reg16, NULL, 2, \ + GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg16##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ + { \ + #reg8, NULL, 1, GPR_OFFSET(reg64) + 1, eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ + { \ + #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64 \ + } + +static RegisterInfo g_register_infos_x86_64[] = { + // General purpose registers. EH_Frame, DWARF, + // Generic, Process Plugin + DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, + LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, + LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, + LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, + LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, + LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, + LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, + LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + DEFINE_GPR_PSEUDO_32(eax, rax), DEFINE_GPR_PSEUDO_32(ebx, rbx), + DEFINE_GPR_PSEUDO_32(ecx, rcx), DEFINE_GPR_PSEUDO_32(edx, rdx), + DEFINE_GPR_PSEUDO_32(edi, rdi), DEFINE_GPR_PSEUDO_32(esi, rsi), + DEFINE_GPR_PSEUDO_32(ebp, rbp), DEFINE_GPR_PSEUDO_32(esp, rsp), + DEFINE_GPR_PSEUDO_32(r8d, r8), DEFINE_GPR_PSEUDO_32(r9d, r9), + DEFINE_GPR_PSEUDO_32(r10d, r10), DEFINE_GPR_PSEUDO_32(r11d, r11), + DEFINE_GPR_PSEUDO_32(r12d, r12), DEFINE_GPR_PSEUDO_32(r13d, r13), + DEFINE_GPR_PSEUDO_32(r14d, r14), DEFINE_GPR_PSEUDO_32(r15d, r15), + DEFINE_GPR_PSEUDO_16(ax, rax), DEFINE_GPR_PSEUDO_16(bx, rbx), + DEFINE_GPR_PSEUDO_16(cx, rcx), DEFINE_GPR_PSEUDO_16(dx, rdx), + DEFINE_GPR_PSEUDO_16(di, rdi), DEFINE_GPR_PSEUDO_16(si, rsi), + DEFINE_GPR_PSEUDO_16(bp, rbp), DEFINE_GPR_PSEUDO_16(sp, rsp), + DEFINE_GPR_PSEUDO_16(r8w, r8), DEFINE_GPR_PSEUDO_16(r9w, r9), + DEFINE_GPR_PSEUDO_16(r10w, r10), DEFINE_GPR_PSEUDO_16(r11w, r11), + DEFINE_GPR_PSEUDO_16(r12w, r12), DEFINE_GPR_PSEUDO_16(r13w, r13), + DEFINE_GPR_PSEUDO_16(r14w, r14), DEFINE_GPR_PSEUDO_16(r15w, r15), + DEFINE_GPR_PSEUDO_8H(ah, rax), DEFINE_GPR_PSEUDO_8H(bh, rbx), + DEFINE_GPR_PSEUDO_8H(ch, rcx), DEFINE_GPR_PSEUDO_8H(dh, rdx), + DEFINE_GPR_PSEUDO_8L(al, rax), DEFINE_GPR_PSEUDO_8L(bl, rbx), + DEFINE_GPR_PSEUDO_8L(cl, rcx), DEFINE_GPR_PSEUDO_8L(dl, rdx), + DEFINE_GPR_PSEUDO_8L(dil, rdi), DEFINE_GPR_PSEUDO_8L(sil, rsi), + DEFINE_GPR_PSEUDO_8L(bpl, rbp), DEFINE_GPR_PSEUDO_8L(spl, rsp), + DEFINE_GPR_PSEUDO_8L(r8l, r8), DEFINE_GPR_PSEUDO_8L(r9l, r9), + DEFINE_GPR_PSEUDO_8L(r10l, r10), DEFINE_GPR_PSEUDO_8L(r11l, r11), + DEFINE_GPR_PSEUDO_8L(r12l, r12), DEFINE_GPR_PSEUDO_8L(r13l, r13), + DEFINE_GPR_PSEUDO_8L(r14l, r14), DEFINE_GPR_PSEUDO_8L(r15l, r15), + + // i387 Floating point registers. EH_frame, + // DWARF, Generic, Process Plugin + DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), // FP registers. - DEFINE_FP_ST(st, 0), - DEFINE_FP_ST(st, 1), - DEFINE_FP_ST(st, 2), - DEFINE_FP_ST(st, 3), - DEFINE_FP_ST(st, 4), - DEFINE_FP_ST(st, 5), - DEFINE_FP_ST(st, 6), - DEFINE_FP_ST(st, 7), - DEFINE_FP_MM(mm, 0), - DEFINE_FP_MM(mm, 1), - DEFINE_FP_MM(mm, 2), - DEFINE_FP_MM(mm, 3), - DEFINE_FP_MM(mm, 4), - DEFINE_FP_MM(mm, 5), - DEFINE_FP_MM(mm, 6), + DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7), DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), DEFINE_FP_MM(mm, 2), DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), DEFINE_FP_MM(mm, 5), DEFINE_FP_MM(mm, 6), DEFINE_FP_MM(mm, 7), // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), DEFINE_XMM(xmm, 10), DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), DEFINE_XMM(xmm, 13), DEFINE_XMM(xmm, 14), DEFINE_XMM(xmm, 15), // Copy of YMM registers assembled from xmm and ymmh - DEFINE_YMM(ymm, 0), - DEFINE_YMM(ymm, 1), - DEFINE_YMM(ymm, 2), - DEFINE_YMM(ymm, 3), - DEFINE_YMM(ymm, 4), - DEFINE_YMM(ymm, 5), - DEFINE_YMM(ymm, 6), - DEFINE_YMM(ymm, 7), - DEFINE_YMM(ymm, 8), - DEFINE_YMM(ymm, 9), - DEFINE_YMM(ymm, 10), - DEFINE_YMM(ymm, 11), - DEFINE_YMM(ymm, 12), - DEFINE_YMM(ymm, 13), - DEFINE_YMM(ymm, 14), + DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), DEFINE_YMM(ymm, 8), + DEFINE_YMM(ymm, 9), DEFINE_YMM(ymm, 10), DEFINE_YMM(ymm, 11), + DEFINE_YMM(ymm, 12), DEFINE_YMM(ymm, 13), DEFINE_YMM(ymm, 14), DEFINE_YMM(ymm, 15), }; @@ -306,52 +334,40 @@ g_register_infos_x86_64[] = //--------------------------------------------------------------------------- static const RegisterInfo * -PrivateGetRegisterInfoPtr (const lldb_private::ArchSpec& target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86_64: - return g_register_infos_x86_64; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } } static uint32_t -PrivateGetRegisterCount (const lldb_private::ArchSpec& target_arch) -{ - switch (target_arch.GetMachine()) - { - case llvm::Triple::x86_64: - return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } +PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86_64: + return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / + sizeof(g_register_infos_x86_64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } } -RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64(const ArchSpec &target_arch) : - lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p (PrivateGetRegisterInfoPtr (target_arch)), - m_register_count (PrivateGetRegisterCount (target_arch)) -{ -} +RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)), + m_register_count(PrivateGetRegisterCount(target_arch)) {} -size_t -RegisterContextNetBSD_x86_64::GetGPRSize() const -{ - return sizeof(GPR); -} +size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } -const RegisterInfo * -RegisterContextNetBSD_x86_64::GetRegisterInfo() const -{ - return m_register_info_p; +const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const { + return m_register_info_p; } -uint32_t -RegisterContextNetBSD_x86_64::GetRegisterCount () const -{ - return m_register_count; +uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { + return m_register_count; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h index c267278c418..6b1998148d6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -12,24 +12,20 @@ #include "RegisterInfoInterface.h" -class RegisterContextNetBSD_x86_64: - public lldb_private::RegisterInfoInterface -{ +class RegisterContextNetBSD_x86_64 + : public lldb_private::RegisterInfoInterface { public: - RegisterContextNetBSD_x86_64(const lldb_private::ArchSpec &target_arch); + RegisterContextNetBSD_x86_64(const lldb_private::ArchSpec &target_arch); - size_t - GetGPRSize() const override; + size_t GetGPRSize() const override; - const lldb_private::RegisterInfo * - GetRegisterInfo() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; - uint32_t - GetRegisterCount () const override; + uint32_t GetRegisterCount() const override; private: - const lldb_private::RegisterInfo *m_register_info_p; - const uint32_t m_register_count; + const lldb_private::RegisterInfo *m_register_info_p; + const uint32_t m_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index 029a0e7352e..15d155e315f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -15,321 +15,204 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" #include "llvm/Support/Compiler.h" -#include "RegisterContextPOSIX_arm.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_arm.h" using namespace lldb; using namespace lldb_private; // arm general purpose registers. -const uint32_t g_gpr_regnums_arm[] = -{ - gpr_r0_arm, - gpr_r1_arm, - gpr_r2_arm, - gpr_r3_arm, - gpr_r4_arm, - gpr_r5_arm, - gpr_r6_arm, - gpr_r7_arm, - gpr_r8_arm, - gpr_r9_arm, - gpr_r10_arm, - gpr_r11_arm, - gpr_r12_arm, - gpr_sp_arm, - gpr_lr_arm, - gpr_pc_arm, - gpr_cpsr_arm, +const uint32_t g_gpr_regnums_arm[] = { + gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm, + gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm, + gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm, + gpr_pc_arm, gpr_cpsr_arm, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \ +static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == + k_num_gpr_registers_arm, "g_gpr_regnums_arm has wrong number of register infos"); // arm floating point registers. -static const uint32_t g_fpu_regnums_arm[] = -{ - fpu_s0_arm, - fpu_s1_arm, - fpu_s2_arm, - fpu_s3_arm, - fpu_s4_arm, - fpu_s5_arm, - fpu_s6_arm, - fpu_s7_arm, - fpu_s8_arm, - fpu_s9_arm, - fpu_s10_arm, - fpu_s11_arm, - fpu_s12_arm, - fpu_s13_arm, - fpu_s14_arm, - fpu_s15_arm, - fpu_s16_arm, - fpu_s17_arm, - fpu_s18_arm, - fpu_s19_arm, - fpu_s20_arm, - fpu_s21_arm, - fpu_s22_arm, - fpu_s23_arm, - fpu_s24_arm, - fpu_s25_arm, - fpu_s26_arm, - fpu_s27_arm, - fpu_s28_arm, - fpu_s29_arm, - fpu_s30_arm, - fpu_s31_arm, - fpu_fpscr_arm, - fpu_d0_arm, - fpu_d1_arm, - fpu_d2_arm, - fpu_d3_arm, - fpu_d4_arm, - fpu_d5_arm, - fpu_d6_arm, - fpu_d7_arm, - fpu_d8_arm, - fpu_d9_arm, - fpu_d10_arm, - fpu_d11_arm, - fpu_d12_arm, - fpu_d13_arm, - fpu_d14_arm, - fpu_d15_arm, - fpu_d16_arm, - fpu_d17_arm, - fpu_d18_arm, - fpu_d19_arm, - fpu_d20_arm, - fpu_d21_arm, - fpu_d22_arm, - fpu_d23_arm, - fpu_d24_arm, - fpu_d25_arm, - fpu_d26_arm, - fpu_d27_arm, - fpu_d28_arm, - fpu_d29_arm, - fpu_d30_arm, - fpu_d31_arm, - fpu_q0_arm, - fpu_q1_arm, - fpu_q2_arm, - fpu_q3_arm, - fpu_q4_arm, - fpu_q5_arm, - fpu_q6_arm, - fpu_q7_arm, - fpu_q8_arm, - fpu_q9_arm, - fpu_q10_arm, - fpu_q11_arm, - fpu_q12_arm, - fpu_q13_arm, - fpu_q14_arm, +static const uint32_t g_fpu_regnums_arm[] = { + fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm, + fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm, + fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm, + fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm, + fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm, + fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm, + fpu_s30_arm, fpu_s31_arm, fpu_fpscr_arm, fpu_d0_arm, fpu_d1_arm, + fpu_d2_arm, fpu_d3_arm, fpu_d4_arm, fpu_d5_arm, fpu_d6_arm, + fpu_d7_arm, fpu_d8_arm, fpu_d9_arm, fpu_d10_arm, fpu_d11_arm, + fpu_d12_arm, fpu_d13_arm, fpu_d14_arm, fpu_d15_arm, fpu_d16_arm, + fpu_d17_arm, fpu_d18_arm, fpu_d19_arm, fpu_d20_arm, fpu_d21_arm, + fpu_d22_arm, fpu_d23_arm, fpu_d24_arm, fpu_d25_arm, fpu_d26_arm, + fpu_d27_arm, fpu_d28_arm, fpu_d29_arm, fpu_d30_arm, fpu_d31_arm, + fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm, + fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm, + fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm, fpu_q15_arm, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \ +static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == + k_num_fpr_registers_arm, "g_fpu_regnums_arm has wrong number of register infos"); // Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; +enum { k_num_register_sets = 2 }; // Register sets for arm. -static const lldb_private::RegisterSet -g_reg_sets_arm[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm } -}; +static const lldb_private::RegisterSet g_reg_sets_arm[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_arm, + g_gpr_regnums_arm}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_arm, + g_fpu_regnums_arm}}; -bool RegisterContextPOSIX_arm::IsGPR(unsigned reg) -{ - return reg <= m_reg_info.last_gpr; // GPR's come first. +bool RegisterContextPOSIX_arm::IsGPR(unsigned reg) { + return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool RegisterContextPOSIX_arm::IsFPR(unsigned reg) -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool RegisterContextPOSIX_arm::IsFPR(unsigned reg) { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : lldb_private::RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); - - switch (register_info->m_target_arch.GetMachine()) - { - case llvm::Triple::arm: - m_reg_info.num_registers = k_num_registers_arm; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; - m_reg_info.last_gpr = k_last_gpr_arm; - m_reg_info.first_fpr = k_first_fpr_arm; - m_reg_info.last_fpr = k_last_fpr_arm; - m_reg_info.first_fpr_v = fpu_s0_arm; - m_reg_info.last_fpr_v = fpu_s31_arm; - m_reg_info.gpr_flags = gpr_cpsr_arm; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } +RegisterContextPOSIX_arm::RegisterContextPOSIX_arm( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : lldb_private::RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); - ::memset(&m_fpr, 0, sizeof m_fpr); + switch (register_info->m_target_arch.GetMachine()) { + case llvm::Triple::arm: + m_reg_info.num_registers = k_num_registers_arm; + m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; + m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; + m_reg_info.last_gpr = k_last_gpr_arm; + m_reg_info.first_fpr = k_first_fpr_arm; + m_reg_info.last_fpr = k_last_fpr_arm; + m_reg_info.first_fpr_v = fpu_s0_arm; + m_reg_info.last_fpr_v = fpu_s31_arm; + m_reg_info.gpr_flags = gpr_cpsr_arm; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } - // elf-core yet to support ReadFPR() - lldb::ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; -} + ::memset(&m_fpr, 0, sizeof m_fpr); -RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() -{ + // elf-core yet to support ReadFPR() + lldb::ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; } -void -RegisterContextPOSIX_arm::Invalidate() -{ -} +RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {} -void -RegisterContextPOSIX_arm::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_arm::Invalidate() {} + +void RegisterContextPOSIX_arm::InvalidateAllRegisters() {} -unsigned -RegisterContextPOSIX_arm::GetRegisterOffset(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +unsigned RegisterContextPOSIX_arm::GetRegisterOffset(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_arm::GetRegisterSize(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_arm::GetRegisterSize(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -size_t -RegisterContextPOSIX_arm::GetRegisterCount() -{ - size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; - return num_registers; +size_t RegisterContextPOSIX_arm::GetRegisterCount() { + size_t num_registers = + m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; + return num_registers; } -size_t -RegisterContextPOSIX_arm::GetGPRSize() -{ - return m_register_info_ap->GetGPRSize (); +size_t RegisterContextPOSIX_arm::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); } -const lldb_private::RegisterInfo * -RegisterContextPOSIX_arm::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return m_register_info_ap->GetRegisterInfo (); +const lldb_private::RegisterInfo *RegisterContextPOSIX_arm::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); } const lldb_private::RegisterInfo * -RegisterContextPOSIX_arm::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < m_reg_info.num_registers) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_arm::GetRegisterInfoAtIndex(size_t reg) { + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_arm::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } +size_t RegisterContextPOSIX_arm::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } - return sets; + return sets; } const lldb_private::RegisterSet * -RegisterContextPOSIX_arm::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - { - switch (m_register_info_ap->m_target_arch.GetMachine()) - { - case llvm::Triple::arm: - return &g_reg_sets_arm[set]; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +RegisterContextPOSIX_arm::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) { + switch (m_register_info_ap->m_target_arch.GetMachine()) { + case llvm::Triple::arm: + return &g_reg_sets_arm[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return NULL; + } + return NULL; } -const char * -RegisterContextPOSIX_arm::GetRegisterName(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_arm::GetRegisterName(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -lldb::ByteOrder -RegisterContextPOSIX_arm::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - lldb_private::Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_arm::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; + lldb_private::Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } -bool -RegisterContextPOSIX_arm::IsRegisterSetAvailable(size_t set_index) -{ - return set_index < k_num_register_sets; +bool RegisterContextPOSIX_arm::IsRegisterSetAvailable(size_t set_index) { + return set_index < k_num_register_sets; } - // Used when parsing DWARF and EH frame information and any other -// object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_arm::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); - - assert (kind < lldb::kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } +// object file sections that contain register numbers in them. +uint32_t RegisterContextPOSIX_arm::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); - return LLDB_INVALID_REGNUM; -} + assert(kind < lldb::kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const lldb_private::RegisterInfo *reg_info = + GetRegisterInfoAtIndex(reg_idx); + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h index fbbcb940291..817649e7c49 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h @@ -14,112 +14,98 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" -#include "lldb/Target/RegisterContext.h" #include "RegisterInfoInterface.h" #include "lldb-arm-register-enums.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" class ProcessMonitor; -class RegisterContextPOSIX_arm - : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_arm : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_arm (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIX_arm(lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); - ~RegisterContextPOSIX_arm() override; + ~RegisterContextPOSIX_arm() override; - void - Invalidate(); + void Invalidate(); - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - virtual size_t - GetGPRSize(); + virtual size_t GetGPRSize(); - virtual unsigned - GetRegisterSize(unsigned reg); + virtual unsigned GetRegisterSize(unsigned reg); - virtual unsigned - GetRegisterOffset(unsigned reg); + virtual unsigned GetRegisterOffset(unsigned reg); - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - - uint32_t first_fpr_v; - uint32_t last_fpr_v; - - uint32_t gpr_flags; - }; - - struct QReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; - - uint32_t m_gpr_arm[lldb_private::k_num_gpr_registers_arm]; // 32-bit general purpose registers. - RegInfo m_reg_info; - struct RegisterContextPOSIX_arm::FPU m_fpr; // floating-point registers including extended register sets. - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) - - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); - - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); - - bool - IsGPR(unsigned reg); - - bool - IsFPR(unsigned reg); - - lldb::ByteOrder GetByteOrder(); - - virtual bool ReadGPR() = 0; - virtual bool ReadFPR() = 0; - virtual bool WriteGPR() = 0; - virtual bool WriteFPR() = 0; + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + + uint32_t first_fpr_v; + uint32_t last_fpr_v; + + uint32_t gpr_flags; + }; + + struct QReg { + uint8_t bytes[16]; + }; + + struct FPU { + union { + uint32_t s[32]; + uint64_t d[32]; + QReg q[16]; // the 128-bit NEON registers + } floats; + uint32_t fpscr; + }; + + uint32_t m_gpr_arm[lldb_private::k_num_gpr_registers_arm]; // 32-bit general + // purpose + // registers. + RegInfo m_reg_info; + struct RegisterContextPOSIX_arm::FPU + m_fpr; // floating-point registers including extended register sets. + std::unique_ptr<lldb_private::RegisterInfoInterface> + m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; }; #endif // liblldb_RegisterContextPOSIX_arm_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 96508eafcce..06569cfca59 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -15,288 +15,200 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" #include "llvm/Support/Compiler.h" -#include "RegisterContextPOSIX_arm64.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_arm64.h" using namespace lldb; using namespace lldb_private; // ARM64 general purpose registers. -const uint32_t g_gpr_regnums_arm64[] = -{ - gpr_x0_arm64, - gpr_x1_arm64, - gpr_x2_arm64, - gpr_x3_arm64, - gpr_x4_arm64, - gpr_x5_arm64, - gpr_x6_arm64, - gpr_x7_arm64, - gpr_x8_arm64, - gpr_x9_arm64, - gpr_x10_arm64, - gpr_x11_arm64, - gpr_x12_arm64, - gpr_x13_arm64, - gpr_x14_arm64, - gpr_x15_arm64, - gpr_x16_arm64, - gpr_x17_arm64, - gpr_x18_arm64, - gpr_x19_arm64, - gpr_x20_arm64, - gpr_x21_arm64, - gpr_x22_arm64, - gpr_x23_arm64, - gpr_x24_arm64, - gpr_x25_arm64, - gpr_x26_arm64, - gpr_x27_arm64, - gpr_x28_arm64, - gpr_fp_arm64, - gpr_lr_arm64, - gpr_sp_arm64, - gpr_pc_arm64, - gpr_cpsr_arm64, +const uint32_t g_gpr_regnums_arm64[] = { + gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64, + gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64, + gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64, + gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64, + gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64, + gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64, + gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64, + gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64, + gpr_pc_arm64, gpr_cpsr_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ +static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - + 1) == k_num_gpr_registers_arm64, "g_gpr_regnums_arm64 has wrong number of register infos"); // ARM64 floating point registers. -static const uint32_t g_fpu_regnums_arm64[] = -{ - fpu_v0_arm64, - fpu_v1_arm64, - fpu_v2_arm64, - fpu_v3_arm64, - fpu_v4_arm64, - fpu_v5_arm64, - fpu_v6_arm64, - fpu_v7_arm64, - fpu_v8_arm64, - fpu_v9_arm64, - fpu_v10_arm64, - fpu_v11_arm64, - fpu_v12_arm64, - fpu_v13_arm64, - fpu_v14_arm64, - fpu_v15_arm64, - fpu_v16_arm64, - fpu_v17_arm64, - fpu_v18_arm64, - fpu_v19_arm64, - fpu_v20_arm64, - fpu_v21_arm64, - fpu_v22_arm64, - fpu_v23_arm64, - fpu_v24_arm64, - fpu_v25_arm64, - fpu_v26_arm64, - fpu_v27_arm64, - fpu_v28_arm64, - fpu_v29_arm64, - fpu_v30_arm64, - fpu_v31_arm64, - fpu_fpsr_arm64, - fpu_fpcr_arm64, +static const uint32_t g_fpu_regnums_arm64[] = { + fpu_v0_arm64, fpu_v1_arm64, fpu_v2_arm64, fpu_v3_arm64, + fpu_v4_arm64, fpu_v5_arm64, fpu_v6_arm64, fpu_v7_arm64, + fpu_v8_arm64, fpu_v9_arm64, fpu_v10_arm64, fpu_v11_arm64, + fpu_v12_arm64, fpu_v13_arm64, fpu_v14_arm64, fpu_v15_arm64, + fpu_v16_arm64, fpu_v17_arm64, fpu_v18_arm64, fpu_v19_arm64, + fpu_v20_arm64, fpu_v21_arm64, fpu_v22_arm64, fpu_v23_arm64, + fpu_v24_arm64, fpu_v25_arm64, fpu_v26_arm64, fpu_v27_arm64, + fpu_v28_arm64, fpu_v29_arm64, fpu_v30_arm64, fpu_v31_arm64, + fpu_fpsr_arm64, fpu_fpcr_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ +static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - + 1) == k_num_fpr_registers_arm64, "g_fpu_regnums_arm64 has wrong number of register infos"); // Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; +enum { k_num_register_sets = 2 }; // Register sets for ARM64. -static const lldb_private::RegisterSet -g_reg_sets_arm64[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } -}; +static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64, + g_gpr_regnums_arm64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, + g_fpu_regnums_arm64}}; -bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg) -{ - return reg <= m_reg_info.last_gpr; // GPR's come first. +bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg) { + return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : lldb_private::RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); - - switch (register_info->m_target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - m_reg_info.num_registers = k_num_registers_arm64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; - m_reg_info.last_gpr = k_last_gpr_arm64; - m_reg_info.first_fpr = k_first_fpr_arm64; - m_reg_info.last_fpr = k_last_fpr_arm64; - m_reg_info.first_fpr_v = fpu_v0_arm64; - m_reg_info.last_fpr_v = fpu_v31_arm64; - m_reg_info.gpr_flags = gpr_cpsr_arm64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } +RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info) + : lldb_private::RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); - ::memset(&m_fpr, 0, sizeof m_fpr); + switch (register_info->m_target_arch.GetMachine()) { + case llvm::Triple::aarch64: + m_reg_info.num_registers = k_num_registers_arm64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; + m_reg_info.last_gpr = k_last_gpr_arm64; + m_reg_info.first_fpr = k_first_fpr_arm64; + m_reg_info.last_fpr = k_last_fpr_arm64; + m_reg_info.first_fpr_v = fpu_v0_arm64; + m_reg_info.last_fpr_v = fpu_v31_arm64; + m_reg_info.gpr_flags = gpr_cpsr_arm64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } - // elf-core yet to support ReadFPR() - lldb::ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; -} + ::memset(&m_fpr, 0, sizeof m_fpr); -RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() -{ + // elf-core yet to support ReadFPR() + lldb::ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; } -void -RegisterContextPOSIX_arm64::Invalidate() -{ -} +RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {} -void -RegisterContextPOSIX_arm64::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_arm64::Invalidate() {} -unsigned -RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +void RegisterContextPOSIX_arm64::InvalidateAllRegisters() {} + +unsigned RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -size_t -RegisterContextPOSIX_arm64::GetRegisterCount() -{ - size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; - return num_registers; +size_t RegisterContextPOSIX_arm64::GetRegisterCount() { + size_t num_registers = + m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; + return num_registers; } -size_t -RegisterContextPOSIX_arm64::GetGPRSize() -{ - return m_register_info_ap->GetGPRSize (); +size_t RegisterContextPOSIX_arm64::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); } const lldb_private::RegisterInfo * -RegisterContextPOSIX_arm64::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return m_register_info_ap->GetRegisterInfo (); +RegisterContextPOSIX_arm64::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); } const lldb_private::RegisterInfo * -RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < m_reg_info.num_registers) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_arm64::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } +size_t RegisterContextPOSIX_arm64::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } - return sets; + return sets; } const lldb_private::RegisterSet * -RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - { - switch (m_register_info_ap->m_target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - return &g_reg_sets_arm64[set]; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) { + switch (m_register_info_ap->m_target_arch.GetMachine()) { + case llvm::Triple::aarch64: + return &g_reg_sets_arm64[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return NULL; + } + return NULL; } -const char * -RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -lldb::ByteOrder -RegisterContextPOSIX_arm64::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - lldb_private::Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_arm64::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; + lldb_private::Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } -bool -RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) -{ - return set_index < k_num_register_sets; +bool RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) { + return set_index < k_num_register_sets; } - // Used when parsing DWARF and EH frame information and any other -// object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); - - assert (kind < lldb::kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } +// object file sections that contain register numbers in them. +uint32_t RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < lldb::kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const lldb_private::RegisterInfo *reg_info = + GetRegisterInfoAtIndex(reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index 225d4f25168..923e786dd04 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -14,111 +14,98 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" -#include "lldb/Target/RegisterContext.h" #include "RegisterInfoInterface.h" #include "lldb-arm64-register-enums.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" class ProcessMonitor; -class RegisterContextPOSIX_arm64 - : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_arm64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIX_arm64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); - ~RegisterContextPOSIX_arm64() override; + ~RegisterContextPOSIX_arm64() override; - void - Invalidate(); + void Invalidate(); - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - virtual size_t - GetGPRSize(); + virtual size_t GetGPRSize(); - virtual unsigned - GetRegisterSize(unsigned reg); + virtual unsigned GetRegisterSize(unsigned reg); - virtual unsigned - GetRegisterOffset(unsigned reg); + virtual unsigned GetRegisterOffset(unsigned reg); - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - - uint32_t first_fpr_v; - uint32_t last_fpr_v; - - uint32_t gpr_flags; - }; - - // based on RegisterContextDarwin_arm64.h - struct VReg - { - uint8_t bytes[16]; - }; - - // based on RegisterContextDarwin_arm64.h - struct FPU - { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; - - uint64_t m_gpr_arm64[lldb_private::k_num_gpr_registers_arm64]; // 64-bit general purpose registers. - RegInfo m_reg_info; - struct RegisterContextPOSIX_arm64::FPU m_fpr; // floating-point registers including extended register sets. - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) - - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); - - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); - - bool - IsGPR(unsigned reg); - - bool - IsFPR(unsigned reg); - - lldb::ByteOrder GetByteOrder(); - - virtual bool ReadGPR() = 0; - virtual bool ReadFPR() = 0; - virtual bool WriteGPR() = 0; - virtual bool WriteFPR() = 0; + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + + uint32_t first_fpr_v; + uint32_t last_fpr_v; + + uint32_t gpr_flags; + }; + + // based on RegisterContextDarwin_arm64.h + struct VReg { + uint8_t bytes[16]; + }; + + // based on RegisterContextDarwin_arm64.h + struct FPU { + VReg v[32]; + uint32_t fpsr; + uint32_t fpcr; + }; + + uint64_t m_gpr_arm64[lldb_private::k_num_gpr_registers_arm64]; // 64-bit + // general + // purpose + // registers. + RegInfo m_reg_info; + struct RegisterContextPOSIX_arm64::FPU + m_fpr; // floating-point registers including extended register sets. + std::unique_ptr<lldb_private::RegisterInfoInterface> + m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; }; #endif // liblldb_RegisterContextPOSIX_arm64_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp index cefedaec63c..8c67fb89d08 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp @@ -15,223 +15,150 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" #include "llvm/Support/Compiler.h" -#include "RegisterContextPOSIX_mips64.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_mips64.h" using namespace lldb_private; using namespace lldb; -static const -uint32_t g_gpr_regnums[] = -{ - gpr_zero_mips64, - gpr_r1_mips64, - gpr_r2_mips64, - gpr_r3_mips64, - gpr_r4_mips64, - gpr_r5_mips64, - gpr_r6_mips64, - gpr_r7_mips64, - gpr_r8_mips64, - gpr_r9_mips64, - gpr_r10_mips64, - gpr_r11_mips64, - gpr_r12_mips64, - gpr_r13_mips64, - gpr_r14_mips64, - gpr_r15_mips64, - gpr_r16_mips64, - gpr_r17_mips64, - gpr_r18_mips64, - gpr_r19_mips64, - gpr_r20_mips64, - gpr_r21_mips64, - gpr_r22_mips64, - gpr_r23_mips64, - gpr_r24_mips64, - gpr_r25_mips64, - gpr_r26_mips64, - gpr_r27_mips64, - gpr_gp_mips64, - gpr_sp_mips64, - gpr_r30_mips64, - gpr_ra_mips64, - gpr_sr_mips64, - gpr_mullo_mips64, - gpr_mulhi_mips64, - gpr_badvaddr_mips64, - gpr_cause_mips64, - gpr_pc_mips64, - gpr_ic_mips64, - gpr_dummy_mips64 -}; +static const uint32_t g_gpr_regnums[] = { + gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, gpr_r3_mips64, + gpr_r4_mips64, gpr_r5_mips64, gpr_r6_mips64, gpr_r7_mips64, + gpr_r8_mips64, gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, + gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, gpr_r15_mips64, + gpr_r16_mips64, gpr_r17_mips64, gpr_r18_mips64, gpr_r19_mips64, + gpr_r20_mips64, gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, + gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, gpr_r27_mips64, + gpr_gp_mips64, gpr_sp_mips64, gpr_r30_mips64, gpr_ra_mips64, + gpr_sr_mips64, gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, + gpr_cause_mips64, gpr_pc_mips64, gpr_ic_mips64, gpr_dummy_mips64}; // Number of register sets provided by this context. -enum -{ - k_num_register_sets = 1 -}; +enum { k_num_register_sets = 1 }; -static const RegisterSet -g_reg_sets_mips64[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_mips64, g_gpr_regnums }, +static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, + g_gpr_regnums}, }; -bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg) -{ - return reg <= k_num_gpr_registers_mips64; // GPR's come first. +bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg) { + return reg <= k_num_gpr_registers_mips64; // GPR's come first. } -bool -RegisterContextPOSIX_mips64::IsFPR(unsigned reg) -{ - // XXX - return false; +bool RegisterContextPOSIX_mips64::IsFPR(unsigned reg) { + // XXX + return false; } -RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(Thread &thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info) - : RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); - - // elf-core yet to support ReadFPR() - ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; -} +RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); -RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() -{ + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; } -void -RegisterContextPOSIX_mips64::Invalidate() -{ -} +RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {} -void -RegisterContextPOSIX_mips64::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_mips64::Invalidate() {} -unsigned -RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg) -{ - assert(reg < k_num_registers_mips64 && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +void RegisterContextPOSIX_mips64::InvalidateAllRegisters() {} + +unsigned RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg) { + assert(reg < k_num_registers_mips64 && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg) -{ - assert(reg < k_num_registers_mips64 && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg) { + assert(reg < k_num_registers_mips64 && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -size_t -RegisterContextPOSIX_mips64::GetRegisterCount() -{ - size_t num_registers = k_num_registers_mips64; - return num_registers; +size_t RegisterContextPOSIX_mips64::GetRegisterCount() { + size_t num_registers = k_num_registers_mips64; + return num_registers; } -size_t -RegisterContextPOSIX_mips64::GetGPRSize() -{ - return m_register_info_ap->GetGPRSize(); +size_t RegisterContextPOSIX_mips64::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); } -const RegisterInfo * -RegisterContextPOSIX_mips64::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return m_register_info_ap->GetRegisterInfo (); +const RegisterInfo *RegisterContextPOSIX_mips64::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); } const RegisterInfo * -RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_registers_mips64) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_registers_mips64) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_mips64::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } - - return sets; +size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; } -const RegisterSet * -RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - return &g_reg_sets_mips64[set]; - else - return NULL; +const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_mips64[set]; + else + return NULL; } -const char * -RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers_mips64 && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) { + assert(reg < k_num_registers_mips64 && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -lldb::ByteOrder -RegisterContextPOSIX_mips64::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = eByteOrderInvalid; - Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_mips64::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } -bool -RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) -{ - size_t num_sets = k_num_register_sets; +bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) { + size_t num_sets = k_num_register_sets; - return (set_index < num_sets); + return (set_index < num_sets); } // Used when parsing DWARF and EH frame information and any other // object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); - - assert (kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } - - return LLDB_INVALID_REGNUM; -} +uint32_t RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h index 07552d8d681..90ff9d65949 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h @@ -14,82 +14,69 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" -#include "lldb/Target/RegisterContext.h" -#include "RegisterInfoInterface.h" #include "RegisterContext_mips.h" +#include "RegisterInfoInterface.h" #include "lldb-mips-freebsd-register-enums.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" using namespace lldb_private; class ProcessMonitor; -class RegisterContextPOSIX_mips64 - : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_mips64 : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_mips64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIX_mips64( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); - ~RegisterContextPOSIX_mips64() override; + ~RegisterContextPOSIX_mips64() override; - void - Invalidate(); + void Invalidate(); - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - virtual size_t - GetGPRSize(); + virtual size_t GetGPRSize(); - virtual unsigned - GetRegisterSize(unsigned reg); + virtual unsigned GetRegisterSize(unsigned reg); - virtual unsigned - GetRegisterOffset(unsigned reg); + virtual unsigned GetRegisterOffset(unsigned reg); - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers. - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + uint64_t + m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers. + std::unique_ptr<lldb_private::RegisterInfoInterface> + m_register_info_ap; // Register Info Interface (FreeBSD or Linux) - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); - bool - IsGPR(unsigned reg); + bool IsGPR(unsigned reg); - bool - IsFPR(unsigned reg); + bool IsFPR(unsigned reg); - lldb::ByteOrder GetByteOrder(); + lldb::ByteOrder GetByteOrder(); - virtual bool ReadGPR() = 0; - virtual bool ReadFPR() = 0; - virtual bool WriteGPR() = 0; - virtual bool WriteFPR() = 0; + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; }; #endif // liblldb_RegisterContextPOSIX_mips64_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index e353e811476..6a9838a6fd0 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -15,305 +16,184 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" #include "llvm/Support/Compiler.h" -#include "RegisterContextPOSIX_powerpc.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_powerpc.h" using namespace lldb_private; using namespace lldb; -static const -uint32_t g_gpr_regnums[] = -{ - gpr_r0_powerpc, - gpr_r1_powerpc, - gpr_r2_powerpc, - gpr_r3_powerpc, - gpr_r4_powerpc, - gpr_r5_powerpc, - gpr_r6_powerpc, - gpr_r7_powerpc, - gpr_r8_powerpc, - gpr_r9_powerpc, - gpr_r10_powerpc, - gpr_r11_powerpc, - gpr_r12_powerpc, - gpr_r13_powerpc, - gpr_r14_powerpc, - gpr_r15_powerpc, - gpr_r16_powerpc, - gpr_r17_powerpc, - gpr_r18_powerpc, - gpr_r19_powerpc, - gpr_r20_powerpc, - gpr_r21_powerpc, - gpr_r22_powerpc, - gpr_r23_powerpc, - gpr_r24_powerpc, - gpr_r25_powerpc, - gpr_r26_powerpc, - gpr_r27_powerpc, - gpr_r28_powerpc, - gpr_r29_powerpc, - gpr_r30_powerpc, - gpr_r31_powerpc, - gpr_lr_powerpc, - gpr_cr_powerpc, - gpr_xer_powerpc, - gpr_ctr_powerpc, +static const uint32_t g_gpr_regnums[] = { + gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc, + gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc, + gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc, + gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc, + gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc, + gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc, + gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc, + gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc, + gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc, gpr_pc_powerpc, }; -static const -uint32_t g_fpr_regnums[] = -{ - fpr_f0_powerpc, - fpr_f1_powerpc, - fpr_f2_powerpc, - fpr_f3_powerpc, - fpr_f4_powerpc, - fpr_f5_powerpc, - fpr_f6_powerpc, - fpr_f7_powerpc, - fpr_f8_powerpc, - fpr_f9_powerpc, - fpr_f10_powerpc, - fpr_f11_powerpc, - fpr_f12_powerpc, - fpr_f13_powerpc, - fpr_f14_powerpc, - fpr_f15_powerpc, - fpr_f16_powerpc, - fpr_f17_powerpc, - fpr_f18_powerpc, - fpr_f19_powerpc, - fpr_f20_powerpc, - fpr_f21_powerpc, - fpr_f22_powerpc, - fpr_f23_powerpc, - fpr_f24_powerpc, - fpr_f25_powerpc, - fpr_f26_powerpc, - fpr_f27_powerpc, - fpr_f28_powerpc, - fpr_f29_powerpc, - fpr_f30_powerpc, - fpr_f31_powerpc, +static const uint32_t g_fpr_regnums[] = { + fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc, + fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc, + fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc, + fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc, + fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc, + fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc, + fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc, + fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc, fpr_fpscr_powerpc, }; -static const -uint32_t g_vmx_regnums[] = -{ - vmx_v0_powerpc, - vmx_v1_powerpc, - vmx_v2_powerpc, - vmx_v3_powerpc, - vmx_v4_powerpc, - vmx_v5_powerpc, - vmx_v6_powerpc, - vmx_v7_powerpc, - vmx_v8_powerpc, - vmx_v9_powerpc, - vmx_v10_powerpc, - vmx_v11_powerpc, - vmx_v12_powerpc, - vmx_v13_powerpc, - vmx_v14_powerpc, - vmx_v15_powerpc, - vmx_v16_powerpc, - vmx_v17_powerpc, - vmx_v18_powerpc, - vmx_v19_powerpc, - vmx_v20_powerpc, - vmx_v21_powerpc, - vmx_v22_powerpc, - vmx_v23_powerpc, - vmx_v24_powerpc, - vmx_v25_powerpc, - vmx_v26_powerpc, - vmx_v27_powerpc, - vmx_v28_powerpc, - vmx_v29_powerpc, - vmx_v30_powerpc, - vmx_v31_powerpc, - vmx_vrsave_powerpc, - vmx_vscr_powerpc, +static const uint32_t g_vmx_regnums[] = { + vmx_v0_powerpc, vmx_v1_powerpc, vmx_v2_powerpc, vmx_v3_powerpc, + vmx_v4_powerpc, vmx_v5_powerpc, vmx_v6_powerpc, vmx_v7_powerpc, + vmx_v8_powerpc, vmx_v9_powerpc, vmx_v10_powerpc, vmx_v11_powerpc, + vmx_v12_powerpc, vmx_v13_powerpc, vmx_v14_powerpc, vmx_v15_powerpc, + vmx_v16_powerpc, vmx_v17_powerpc, vmx_v18_powerpc, vmx_v19_powerpc, + vmx_v20_powerpc, vmx_v21_powerpc, vmx_v22_powerpc, vmx_v23_powerpc, + vmx_v24_powerpc, vmx_v25_powerpc, vmx_v26_powerpc, vmx_v27_powerpc, + vmx_v28_powerpc, vmx_v29_powerpc, vmx_v30_powerpc, vmx_v31_powerpc, + vmx_vrsave_powerpc, vmx_vscr_powerpc, }; // Number of register sets provided by this context. -enum -{ - k_num_register_sets = 3 +enum { k_num_register_sets = 3 }; + +static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, + g_gpr_regnums}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, + g_fpr_regnums}, + {"Altivec/VMX Registers", "vmx", k_num_vmx_registers_powerpc, + g_vmx_regnums}, }; -static const RegisterSet -g_reg_sets_powerpc[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums }, - { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums }, - { "Altivec/VMX Registers", "vmx", k_num_vmx_registers_powerpc, g_vmx_regnums }, -}; - -static_assert(k_first_gpr_powerpc == 0, "GPRs must index starting at 0, or fix IsGPR()"); -bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) -{ - return (reg <= k_last_gpr_powerpc); // GPR's come first. +static_assert(k_first_gpr_powerpc == 0, + "GPRs must index starting at 0, or fix IsGPR()"); +bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) { + return (reg <= k_last_gpr_powerpc); // GPR's come first. } -bool -RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) -{ - return (reg >= k_first_fpr) && (reg <= k_last_fpr); +bool RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) { + return (reg >= k_first_fpr) && (reg <= k_last_fpr); } -bool -RegisterContextPOSIX_powerpc::IsVMX(unsigned reg) -{ - return (reg >= k_first_vmx) && (reg <= k_last_vmx); +bool RegisterContextPOSIX_powerpc::IsVMX(unsigned reg) { + return (reg >= k_first_vmx) && (reg <= k_last_vmx); } -RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info) - : RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); - - // elf-core yet to support ReadFPR() - ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; -} +RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); -RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() -{ + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; } -void -RegisterContextPOSIX_powerpc::Invalidate() -{ -} +RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {} -void -RegisterContextPOSIX_powerpc::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_powerpc::Invalidate() {} -unsigned -RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg) -{ - assert(reg < k_num_registers_powerpc && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +void RegisterContextPOSIX_powerpc::InvalidateAllRegisters() {} + +unsigned RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg) { + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg) -{ - assert(reg < k_num_registers_powerpc && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg) { + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -size_t -RegisterContextPOSIX_powerpc::GetRegisterCount() -{ - size_t num_registers = k_num_registers_powerpc; - return num_registers; +size_t RegisterContextPOSIX_powerpc::GetRegisterCount() { + size_t num_registers = k_num_registers_powerpc; + return num_registers; } -size_t -RegisterContextPOSIX_powerpc::GetGPRSize() -{ - return m_register_info_ap->GetGPRSize(); +size_t RegisterContextPOSIX_powerpc::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); } -const RegisterInfo * -RegisterContextPOSIX_powerpc::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return m_register_info_ap->GetRegisterInfo (); +const RegisterInfo *RegisterContextPOSIX_powerpc::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); } const RegisterInfo * -RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_registers_powerpc) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_registers_powerpc) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_powerpc::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } - - return sets; +size_t RegisterContextPOSIX_powerpc::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; } -const RegisterSet * -RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - return &g_reg_sets_powerpc[set]; - else - return NULL; +const RegisterSet *RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_powerpc[set]; + else + return NULL; } -const char * -RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers_powerpc && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) { + assert(reg < k_num_registers_powerpc && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -lldb::ByteOrder -RegisterContextPOSIX_powerpc::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = eByteOrderInvalid; - Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_powerpc::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } -bool -RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) -{ - size_t num_sets = k_num_register_sets; +bool RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) { + size_t num_sets = k_num_register_sets; - return (set_index < num_sets); + return (set_index < num_sets); } // Used when parsing DWARF and EH frame information and any other // object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); - - assert (kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } - - return LLDB_INVALID_REGNUM; -} +uint32_t RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 4168e46ebd9..79bb01f6740 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -14,210 +14,196 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "RegisterContext_powerpc.h" +#include "RegisterInfoInterface.h" #include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" -#include "RegisterInfoInterface.h" -#include "RegisterContext_powerpc.h" class ProcessMonitor; // --------------------------------------------------------------------------- // Internal codes for all powerpc registers. // --------------------------------------------------------------------------- -enum -{ - k_first_gpr_powerpc, - gpr_r0_powerpc = k_first_gpr_powerpc, - gpr_r1_powerpc, - gpr_r2_powerpc, - gpr_r3_powerpc, - gpr_r4_powerpc, - gpr_r5_powerpc, - gpr_r6_powerpc, - gpr_r7_powerpc, - gpr_r8_powerpc, - gpr_r9_powerpc, - gpr_r10_powerpc, - gpr_r11_powerpc, - gpr_r12_powerpc, - gpr_r13_powerpc, - gpr_r14_powerpc, - gpr_r15_powerpc, - gpr_r16_powerpc, - gpr_r17_powerpc, - gpr_r18_powerpc, - gpr_r19_powerpc, - gpr_r20_powerpc, - gpr_r21_powerpc, - gpr_r22_powerpc, - gpr_r23_powerpc, - gpr_r24_powerpc, - gpr_r25_powerpc, - gpr_r26_powerpc, - gpr_r27_powerpc, - gpr_r28_powerpc, - gpr_r29_powerpc, - gpr_r30_powerpc, - gpr_r31_powerpc, - gpr_lr_powerpc, - gpr_cr_powerpc, - gpr_xer_powerpc, - gpr_ctr_powerpc, - gpr_pc_powerpc, - k_last_gpr_powerpc = gpr_pc_powerpc, - - k_first_fpr, - fpr_f0_powerpc = k_first_fpr, - fpr_f1_powerpc, - fpr_f2_powerpc, - fpr_f3_powerpc, - fpr_f4_powerpc, - fpr_f5_powerpc, - fpr_f6_powerpc, - fpr_f7_powerpc, - fpr_f8_powerpc, - fpr_f9_powerpc, - fpr_f10_powerpc, - fpr_f11_powerpc, - fpr_f12_powerpc, - fpr_f13_powerpc, - fpr_f14_powerpc, - fpr_f15_powerpc, - fpr_f16_powerpc, - fpr_f17_powerpc, - fpr_f18_powerpc, - fpr_f19_powerpc, - fpr_f20_powerpc, - fpr_f21_powerpc, - fpr_f22_powerpc, - fpr_f23_powerpc, - fpr_f24_powerpc, - fpr_f25_powerpc, - fpr_f26_powerpc, - fpr_f27_powerpc, - fpr_f28_powerpc, - fpr_f29_powerpc, - fpr_f30_powerpc, - fpr_f31_powerpc, - fpr_fpscr_powerpc, - k_last_fpr = fpr_fpscr_powerpc, - - k_first_vmx, - vmx_v0_powerpc = k_first_vmx, - vmx_v1_powerpc, - vmx_v2_powerpc, - vmx_v3_powerpc, - vmx_v4_powerpc, - vmx_v5_powerpc, - vmx_v6_powerpc, - vmx_v7_powerpc, - vmx_v8_powerpc, - vmx_v9_powerpc, - vmx_v10_powerpc, - vmx_v11_powerpc, - vmx_v12_powerpc, - vmx_v13_powerpc, - vmx_v14_powerpc, - vmx_v15_powerpc, - vmx_v16_powerpc, - vmx_v17_powerpc, - vmx_v18_powerpc, - vmx_v19_powerpc, - vmx_v20_powerpc, - vmx_v21_powerpc, - vmx_v22_powerpc, - vmx_v23_powerpc, - vmx_v24_powerpc, - vmx_v25_powerpc, - vmx_v26_powerpc, - vmx_v27_powerpc, - vmx_v28_powerpc, - vmx_v29_powerpc, - vmx_v30_powerpc, - vmx_v31_powerpc, - vmx_vrsave_powerpc, - vmx_vscr_powerpc, - k_last_vmx = vmx_vscr_powerpc, - - k_num_registers_powerpc, - k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, - k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, - k_num_vmx_registers_powerpc = k_last_vmx - k_first_vmx + 1, +enum { + k_first_gpr_powerpc, + gpr_r0_powerpc = k_first_gpr_powerpc, + gpr_r1_powerpc, + gpr_r2_powerpc, + gpr_r3_powerpc, + gpr_r4_powerpc, + gpr_r5_powerpc, + gpr_r6_powerpc, + gpr_r7_powerpc, + gpr_r8_powerpc, + gpr_r9_powerpc, + gpr_r10_powerpc, + gpr_r11_powerpc, + gpr_r12_powerpc, + gpr_r13_powerpc, + gpr_r14_powerpc, + gpr_r15_powerpc, + gpr_r16_powerpc, + gpr_r17_powerpc, + gpr_r18_powerpc, + gpr_r19_powerpc, + gpr_r20_powerpc, + gpr_r21_powerpc, + gpr_r22_powerpc, + gpr_r23_powerpc, + gpr_r24_powerpc, + gpr_r25_powerpc, + gpr_r26_powerpc, + gpr_r27_powerpc, + gpr_r28_powerpc, + gpr_r29_powerpc, + gpr_r30_powerpc, + gpr_r31_powerpc, + gpr_lr_powerpc, + gpr_cr_powerpc, + gpr_xer_powerpc, + gpr_ctr_powerpc, + gpr_pc_powerpc, + k_last_gpr_powerpc = gpr_pc_powerpc, + + k_first_fpr, + fpr_f0_powerpc = k_first_fpr, + fpr_f1_powerpc, + fpr_f2_powerpc, + fpr_f3_powerpc, + fpr_f4_powerpc, + fpr_f5_powerpc, + fpr_f6_powerpc, + fpr_f7_powerpc, + fpr_f8_powerpc, + fpr_f9_powerpc, + fpr_f10_powerpc, + fpr_f11_powerpc, + fpr_f12_powerpc, + fpr_f13_powerpc, + fpr_f14_powerpc, + fpr_f15_powerpc, + fpr_f16_powerpc, + fpr_f17_powerpc, + fpr_f18_powerpc, + fpr_f19_powerpc, + fpr_f20_powerpc, + fpr_f21_powerpc, + fpr_f22_powerpc, + fpr_f23_powerpc, + fpr_f24_powerpc, + fpr_f25_powerpc, + fpr_f26_powerpc, + fpr_f27_powerpc, + fpr_f28_powerpc, + fpr_f29_powerpc, + fpr_f30_powerpc, + fpr_f31_powerpc, + fpr_fpscr_powerpc, + k_last_fpr = fpr_fpscr_powerpc, + + k_first_vmx, + vmx_v0_powerpc = k_first_vmx, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, + k_last_vmx = vmx_vscr_powerpc, + + k_num_registers_powerpc, + k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, + k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, + k_num_vmx_registers_powerpc = k_last_vmx - k_first_vmx + 1, }; -class RegisterContextPOSIX_powerpc - : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_powerpc : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_powerpc (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIX_powerpc( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); - ~RegisterContextPOSIX_powerpc() override; + ~RegisterContextPOSIX_powerpc() override; - void - Invalidate(); + void Invalidate(); - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - virtual size_t - GetGPRSize(); + virtual size_t GetGPRSize(); - virtual unsigned - GetRegisterSize(unsigned reg); + virtual unsigned GetRegisterSize(unsigned reg); - virtual unsigned - GetRegisterOffset(unsigned reg); + virtual unsigned GetRegisterOffset(unsigned reg); - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. - uint64_t m_fpr_powerpc[k_num_fpr_registers_powerpc]; // floating point registers. - uint32_t m_vmx_powerpc[k_num_vmx_registers_powerpc][4]; - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + uint64_t + m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. + uint64_t + m_fpr_powerpc[k_num_fpr_registers_powerpc]; // floating point registers. + uint32_t m_vmx_powerpc[k_num_vmx_registers_powerpc][4]; + std::unique_ptr<lldb_private::RegisterInfoInterface> + m_register_info_ap; // Register Info Interface (FreeBSD or Linux) - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); - bool - IsGPR(unsigned reg); + bool IsGPR(unsigned reg); - bool - IsFPR(unsigned reg); + bool IsFPR(unsigned reg); - bool - IsVMX(unsigned reg); + bool IsVMX(unsigned reg); - lldb::ByteOrder GetByteOrder(); + lldb::ByteOrder GetByteOrder(); - virtual bool ReadGPR() = 0; - virtual bool ReadFPR() = 0; - virtual bool ReadVMX() = 0; - virtual bool WriteGPR() = 0; - virtual bool WriteFPR() = 0; - virtual bool WriteVMX() = 0; + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool ReadVMX() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; + virtual bool WriteVMX() = 0; }; #endif // liblldb_RegisterContextPOSIX_powerpc_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index 960be50c7be..66664c99bda 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -21,245 +21,172 @@ #include "lldb/Target/Thread.h" #include "llvm/Support/Compiler.h" -#include "RegisterContext_s390x.h" #include "RegisterContextPOSIX_s390x.h" +#include "RegisterContext_s390x.h" using namespace lldb_private; using namespace lldb; // s390x 64-bit general purpose registers. -static const uint32_t g_gpr_regnums_s390x[] = -{ - lldb_r0_s390x, - lldb_r1_s390x, - lldb_r2_s390x, - lldb_r3_s390x, - lldb_r4_s390x, - lldb_r5_s390x, - lldb_r6_s390x, - lldb_r7_s390x, - lldb_r8_s390x, - lldb_r9_s390x, - lldb_r10_s390x, - lldb_r11_s390x, - lldb_r12_s390x, - lldb_r13_s390x, - lldb_r14_s390x, - lldb_r15_s390x, - lldb_acr0_s390x, - lldb_acr1_s390x, - lldb_acr2_s390x, - lldb_acr3_s390x, - lldb_acr4_s390x, - lldb_acr5_s390x, - lldb_acr6_s390x, - lldb_acr7_s390x, - lldb_acr8_s390x, - lldb_acr9_s390x, - lldb_acr10_s390x, - lldb_acr11_s390x, - lldb_acr12_s390x, - lldb_acr13_s390x, - lldb_acr14_s390x, - lldb_acr15_s390x, - lldb_pswm_s390x, - lldb_pswa_s390x, +static const uint32_t g_gpr_regnums_s390x[] = { + lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x, + lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x, + lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x, + lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x, + lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x, + lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x, + lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x, + lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x, + lldb_pswm_s390x, lldb_pswa_s390x, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x, +static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - + 1 == + k_num_gpr_registers_s390x, "g_gpr_regnums_s390x has wrong number of register infos"); // s390x 64-bit floating point registers. -static const uint32_t g_fpu_regnums_s390x[] = -{ - lldb_f0_s390x, - lldb_f1_s390x, - lldb_f2_s390x, - lldb_f3_s390x, - lldb_f4_s390x, - lldb_f5_s390x, - lldb_f6_s390x, - lldb_f7_s390x, - lldb_f8_s390x, - lldb_f9_s390x, - lldb_f10_s390x, - lldb_f11_s390x, - lldb_f12_s390x, - lldb_f13_s390x, - lldb_f14_s390x, - lldb_f15_s390x, +static const uint32_t g_fpu_regnums_s390x[] = { + lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x, + lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x, + lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x, + lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x, lldb_fpc_s390x, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x, +static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - + 1 == + k_num_fpr_registers_s390x, "g_fpu_regnums_s390x has wrong number of register infos"); // Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; +enum { k_num_register_sets = 2 }; // Register sets for s390x 64-bit. -static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x }, - { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x }, +static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x, + g_gpr_regnums_s390x}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x, + g_fpu_regnums_s390x}, }; -bool -RegisterContextPOSIX_s390x::IsGPR(unsigned reg) -{ - return reg <= m_reg_info.last_gpr; // GPRs come first. +bool RegisterContextPOSIX_s390x::IsGPR(unsigned reg) { + return reg <= m_reg_info.last_gpr; // GPRs come first. } -bool -RegisterContextPOSIX_s390x::IsFPR(unsigned reg) -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool RegisterContextPOSIX_s390x::IsFPR(unsigned reg) { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(Thread &thread, uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info) - : RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); +RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); - switch (register_info->m_target_arch.GetMachine()) - { - case llvm::Triple::systemz: - m_reg_info.num_registers = k_num_registers_s390x; - m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; - m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; - m_reg_info.last_gpr = k_last_gpr_s390x; - m_reg_info.first_fpr = k_first_fpr_s390x; - m_reg_info.last_fpr = k_last_fpr_s390x; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } + switch (register_info->m_target_arch.GetMachine()) { + case llvm::Triple::systemz: + m_reg_info.num_registers = k_num_registers_s390x; + m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; + m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; + m_reg_info.last_gpr = k_last_gpr_s390x; + m_reg_info.first_fpr = k_first_fpr_s390x; + m_reg_info.last_fpr = k_last_fpr_s390x; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } } -RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() -{ -} +RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() {} -void -RegisterContextPOSIX_s390x::Invalidate() -{ -} +void RegisterContextPOSIX_s390x::Invalidate() {} -void -RegisterContextPOSIX_s390x::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_s390x::InvalidateAllRegisters() {} -const RegisterInfo * -RegisterContextPOSIX_s390x::GetRegisterInfo() -{ - return m_register_info_ap->GetRegisterInfo(); +const RegisterInfo *RegisterContextPOSIX_s390x::GetRegisterInfo() { + return m_register_info_ap->GetRegisterInfo(); } const RegisterInfo * -RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < m_reg_info.num_registers) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg) { + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_s390x::GetRegisterCount() -{ - return m_reg_info.num_registers; +size_t RegisterContextPOSIX_s390x::GetRegisterCount() { + return m_reg_info.num_registers; } -unsigned -RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +unsigned RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -const char * -RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -bool -RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index) -{ - return set_index < k_num_register_sets; +bool RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index) { + return set_index < k_num_register_sets; } -size_t -RegisterContextPOSIX_s390x::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } +size_t RegisterContextPOSIX_s390x::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } - return sets; + return sets; } -const RegisterSet * -RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - { - switch (m_register_info_ap->m_target_arch.GetMachine()) - { - case llvm::Triple::systemz: - return &g_reg_sets_s390x[set]; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +const RegisterSet *RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) { + switch (m_register_info_ap->m_target_arch.GetMachine()) { + case llvm::Triple::systemz: + return &g_reg_sets_s390x[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return NULL; + } + return NULL; } -lldb::ByteOrder -RegisterContextPOSIX_s390x::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = eByteOrderInvalid; - Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_s390x::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } // Used when parsing DWARF and EH frame information and any other // object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); +uint32_t RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); - assert(kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); - if (reg_info->kinds[kind] == num) - return reg_idx; - } + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h index 4904b2857c4..1ffc45c2d4b 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h @@ -14,90 +14,71 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" -#include "lldb/Target/RegisterContext.h" -#include "RegisterInfoInterface.h" #include "RegisterContext_s390x.h" +#include "RegisterInfoInterface.h" #include "lldb-s390x-register-enums.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" class ProcessMonitor; -class RegisterContextPOSIX_s390x : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_s390x : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_s390x(lldb_private::Thread &thread, uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + RegisterContextPOSIX_s390x( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); - ~RegisterContextPOSIX_s390x() override; + ~RegisterContextPOSIX_s390x() override; - void - Invalidate(); + void Invalidate(); - void - InvalidateAllRegisters() override; + void InvalidateAllRegisters() override; - size_t - GetRegisterCount() override; + size_t GetRegisterCount() override; - virtual unsigned - GetRegisterSize(unsigned reg); + virtual unsigned GetRegisterSize(unsigned reg); - virtual unsigned - GetRegisterOffset(unsigned reg); + virtual unsigned GetRegisterOffset(unsigned reg); - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t - GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; - const char * - GetRegisterName(unsigned reg); + const char *GetRegisterName(unsigned reg); - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - }; - - RegInfo m_reg_info; - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; - - virtual bool - IsRegisterSetAvailable(size_t set_index); - - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); - - bool - IsGPR(unsigned reg); - - bool - IsFPR(unsigned reg); - - lldb::ByteOrder - GetByteOrder(); - - virtual bool - ReadGPR() = 0; - virtual bool - ReadFPR() = 0; - virtual bool - WriteGPR() = 0; - virtual bool - WriteFPR() = 0; + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + }; + + RegInfo m_reg_info; + std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; + + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; }; #endif // liblldb_RegisterContextPOSIX_s390x_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 77b6385da8b..77f3fcb0e9c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -15,187 +15,94 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" #include "llvm/Support/Compiler.h" -#include "RegisterContext_x86.h" -#include "RegisterContextPOSIX_x86.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContext_x86.h" using namespace lldb_private; using namespace lldb; -const uint32_t -g_gpr_regnums_i386[] = -{ - lldb_eax_i386, - lldb_ebx_i386, - lldb_ecx_i386, - lldb_edx_i386, - lldb_edi_i386, - lldb_esi_i386, - lldb_ebp_i386, - lldb_esp_i386, - lldb_eip_i386, - lldb_eflags_i386, - lldb_cs_i386, - lldb_fs_i386, - lldb_gs_i386, - lldb_ss_i386, - lldb_ds_i386, - lldb_es_i386, - lldb_ax_i386, - lldb_bx_i386, - lldb_cx_i386, - lldb_dx_i386, - lldb_di_i386, - lldb_si_i386, - lldb_bp_i386, - lldb_sp_i386, - lldb_ah_i386, - lldb_bh_i386, - lldb_ch_i386, - lldb_dh_i386, - lldb_al_i386, - lldb_bl_i386, - lldb_cl_i386, - lldb_dl_i386, - LLDB_INVALID_REGNUM, // Register sets must be terminated with LLDB_INVALID_REGNUM. +const uint32_t g_gpr_regnums_i386[] = { + lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, + lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, + lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, + lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386, + lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386, + lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386, + lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386, + lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386, + LLDB_INVALID_REGNUM, // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386, - "g_gpr_regnums_i386 has wrong number of register infos"); - -const uint32_t -g_lldb_regnums_i386[] = -{ - lldb_fctrl_i386, - lldb_fstat_i386, - lldb_ftag_i386, - lldb_fop_i386, - lldb_fiseg_i386, - lldb_fioff_i386, - lldb_foseg_i386, - lldb_fooff_i386, - lldb_mxcsr_i386, - lldb_mxcsrmask_i386, - lldb_st0_i386, - lldb_st1_i386, - lldb_st2_i386, - lldb_st3_i386, - lldb_st4_i386, - lldb_st5_i386, - lldb_st6_i386, - lldb_st7_i386, - lldb_mm0_i386, - lldb_mm1_i386, - lldb_mm2_i386, - lldb_mm3_i386, - lldb_mm4_i386, - lldb_mm5_i386, - lldb_mm6_i386, - lldb_mm7_i386, - lldb_xmm0_i386, - lldb_xmm1_i386, - lldb_xmm2_i386, - lldb_xmm3_i386, - lldb_xmm4_i386, - lldb_xmm5_i386, - lldb_xmm6_i386, - lldb_xmm7_i386, - LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. +static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - + 1 == + k_num_gpr_registers_i386, + "g_gpr_regnums_i386 has wrong number of register infos"); + +const uint32_t g_lldb_regnums_i386[] = { + lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, + lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, + lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, + lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386, + lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386, + lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386, + lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, + lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, + lldb_xmm6_i386, lldb_xmm7_i386, + LLDB_INVALID_REGNUM // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) - 1 == k_num_fpr_registers_i386, - "g_lldb_regnums_i386 has wrong number of register infos"); - -const uint32_t -g_avx_regnums_i386[] = -{ - lldb_ymm0_i386, - lldb_ymm1_i386, - lldb_ymm2_i386, - lldb_ymm3_i386, - lldb_ymm4_i386, - lldb_ymm5_i386, - lldb_ymm6_i386, - lldb_ymm7_i386, - LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. +static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) - + 1 == + k_num_fpr_registers_i386, + "g_lldb_regnums_i386 has wrong number of register infos"); + +const uint32_t g_avx_regnums_i386[] = { + lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, + lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, + LLDB_INVALID_REGNUM // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386, - " g_avx_regnums_i386 has wrong number of register infos"); - -static const -uint32_t g_gpr_regnums_x86_64[] = -{ - lldb_rax_x86_64, - lldb_rbx_x86_64, - lldb_rcx_x86_64, - lldb_rdx_x86_64, - lldb_rdi_x86_64, - lldb_rsi_x86_64, - lldb_rbp_x86_64, - lldb_rsp_x86_64, - lldb_r8_x86_64, - lldb_r9_x86_64, - lldb_r10_x86_64, - lldb_r11_x86_64, - lldb_r12_x86_64, - lldb_r13_x86_64, - lldb_r14_x86_64, - lldb_r15_x86_64, - lldb_rip_x86_64, - lldb_rflags_x86_64, - lldb_cs_x86_64, - lldb_fs_x86_64, - lldb_gs_x86_64, - lldb_ss_x86_64, - lldb_ds_x86_64, - lldb_es_x86_64, - lldb_eax_x86_64, - lldb_ebx_x86_64, - lldb_ecx_x86_64, - lldb_edx_x86_64, - lldb_edi_x86_64, - lldb_esi_x86_64, - lldb_ebp_x86_64, - lldb_esp_x86_64, - lldb_r8d_x86_64, // Low 32 bits or r8 - lldb_r9d_x86_64, // Low 32 bits or r9 - lldb_r10d_x86_64, // Low 32 bits or r10 - lldb_r11d_x86_64, // Low 32 bits or r11 - lldb_r12d_x86_64, // Low 32 bits or r12 - lldb_r13d_x86_64, // Low 32 bits or r13 - lldb_r14d_x86_64, // Low 32 bits or r14 - lldb_r15d_x86_64, // Low 32 bits or r15 - lldb_ax_x86_64, - lldb_bx_x86_64, - lldb_cx_x86_64, - lldb_dx_x86_64, - lldb_di_x86_64, - lldb_si_x86_64, - lldb_bp_x86_64, - lldb_sp_x86_64, - lldb_r8w_x86_64, // Low 16 bits or r8 - lldb_r9w_x86_64, // Low 16 bits or r9 - lldb_r10w_x86_64, // Low 16 bits or r10 - lldb_r11w_x86_64, // Low 16 bits or r11 - lldb_r12w_x86_64, // Low 16 bits or r12 - lldb_r13w_x86_64, // Low 16 bits or r13 - lldb_r14w_x86_64, // Low 16 bits or r14 - lldb_r15w_x86_64, // Low 16 bits or r15 - lldb_ah_x86_64, - lldb_bh_x86_64, - lldb_ch_x86_64, - lldb_dh_x86_64, - lldb_al_x86_64, - lldb_bl_x86_64, - lldb_cl_x86_64, - lldb_dl_x86_64, - lldb_dil_x86_64, - lldb_sil_x86_64, - lldb_bpl_x86_64, - lldb_spl_x86_64, +static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - + 1 == + k_num_avx_registers_i386, + " g_avx_regnums_i386 has wrong number of register infos"); + +static const uint32_t g_gpr_regnums_x86_64[] = { + lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, + lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, + lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, + lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, + lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, + lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, + lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, + lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits or r8 + lldb_r9d_x86_64, // Low 32 bits or r9 + lldb_r10d_x86_64, // Low 32 bits or r10 + lldb_r11d_x86_64, // Low 32 bits or r11 + lldb_r12d_x86_64, // Low 32 bits or r12 + lldb_r13d_x86_64, // Low 32 bits or r13 + lldb_r14d_x86_64, // Low 32 bits or r14 + lldb_r15d_x86_64, // Low 32 bits or r15 + lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, + lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits or r8 + lldb_r9w_x86_64, // Low 16 bits or r9 + lldb_r10w_x86_64, // Low 16 bits or r10 + lldb_r11w_x86_64, // Low 16 bits or r11 + lldb_r12w_x86_64, // Low 16 bits or r12 + lldb_r13w_x86_64, // Low 16 bits or r13 + lldb_r14w_x86_64, // Low 16 bits or r14 + lldb_r15w_x86_64, // Low 16 bits or r15 + lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, + lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, + lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, lldb_r8l_x86_64, // Low 8 bits or r8 lldb_r9l_x86_64, // Low 8 bits or r9 lldb_r10l_x86_64, // Low 8 bits or r10 @@ -204,464 +111,446 @@ uint32_t g_gpr_regnums_x86_64[] = lldb_r13l_x86_64, // Low 8 bits or r13 lldb_r14l_x86_64, // Low 8 bits or r14 lldb_r15l_x86_64, // Low 8 bits or r15 - LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. + LLDB_INVALID_REGNUM // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64, - "g_gpr_regnums_x86_64 has wrong number of register infos"); - -static const uint32_t -g_lldb_regnums_x86_64[] = -{ - lldb_fctrl_x86_64, - lldb_fstat_x86_64, - lldb_ftag_x86_64, - lldb_fop_x86_64, - lldb_fiseg_x86_64, - lldb_fioff_x86_64, - lldb_foseg_x86_64, - lldb_fooff_x86_64, - lldb_mxcsr_x86_64, - lldb_mxcsrmask_x86_64, - lldb_st0_x86_64, - lldb_st1_x86_64, - lldb_st2_x86_64, - lldb_st3_x86_64, - lldb_st4_x86_64, - lldb_st5_x86_64, - lldb_st6_x86_64, - lldb_st7_x86_64, - lldb_mm0_x86_64, - lldb_mm1_x86_64, - lldb_mm2_x86_64, - lldb_mm3_x86_64, - lldb_mm4_x86_64, - lldb_mm5_x86_64, - lldb_mm6_x86_64, - lldb_mm7_x86_64, - lldb_xmm0_x86_64, - lldb_xmm1_x86_64, - lldb_xmm2_x86_64, - lldb_xmm3_x86_64, - lldb_xmm4_x86_64, - lldb_xmm5_x86_64, - lldb_xmm6_x86_64, - lldb_xmm7_x86_64, - lldb_xmm8_x86_64, - lldb_xmm9_x86_64, - lldb_xmm10_x86_64, - lldb_xmm11_x86_64, - lldb_xmm12_x86_64, - lldb_xmm13_x86_64, - lldb_xmm14_x86_64, - lldb_xmm15_x86_64, - LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. +static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - + 1 == + k_num_gpr_registers_x86_64, + "g_gpr_regnums_x86_64 has wrong number of register infos"); + +static const uint32_t g_lldb_regnums_x86_64[] = { + lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, + lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, + lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64, + lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64, + lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64, + lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64, + lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64, + lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64, + lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64, + lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64, + lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64, + lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64, + lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64, + lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64, + LLDB_INVALID_REGNUM // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_lldb_regnums_x86_64) / sizeof(g_lldb_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64, - "g_lldb_regnums_x86_64 has wrong number of register infos"); - -static const uint32_t -g_avx_regnums_x86_64[] = -{ - lldb_ymm0_x86_64, - lldb_ymm1_x86_64, - lldb_ymm2_x86_64, - lldb_ymm3_x86_64, - lldb_ymm4_x86_64, - lldb_ymm5_x86_64, - lldb_ymm6_x86_64, - lldb_ymm7_x86_64, - lldb_ymm8_x86_64, - lldb_ymm9_x86_64, - lldb_ymm10_x86_64, - lldb_ymm11_x86_64, - lldb_ymm12_x86_64, - lldb_ymm13_x86_64, - lldb_ymm14_x86_64, - lldb_ymm15_x86_64, - LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. +static_assert((sizeof(g_lldb_regnums_x86_64) / + sizeof(g_lldb_regnums_x86_64[0])) - + 1 == + k_num_fpr_registers_x86_64, + "g_lldb_regnums_x86_64 has wrong number of register infos"); + +static const uint32_t g_avx_regnums_x86_64[] = { + lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, + lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, + lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, + lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, + LLDB_INVALID_REGNUM // Register sets must be terminated with + // LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64, - "g_avx_regnums_x86_64 has wrong number of register infos"); - -uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { lldb_eax_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { lldb_ebx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { lldb_ecx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { lldb_edx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { lldb_edi_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { lldb_esi_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { lldb_ebp_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { lldb_esp_i386, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { lldb_eax_i386, lldb_ax_i386, lldb_ah_i386, lldb_al_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { lldb_ebx_i386, lldb_bx_i386, lldb_bh_i386, lldb_bl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { lldb_ecx_i386, lldb_cx_i386, lldb_ch_i386, lldb_cl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { lldb_edx_i386, lldb_dx_i386, lldb_dh_i386, lldb_dl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { lldb_edi_i386, lldb_di_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { lldb_esi_i386, lldb_si_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { lldb_ebp_i386, lldb_bp_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { lldb_esp_i386, lldb_sp_i386, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { lldb_rax_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { lldb_rbx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { lldb_rcx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { lldb_rdx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { lldb_rdi_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { lldb_rsi_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { lldb_rbp_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { lldb_rsp_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { lldb_r8_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { lldb_r9_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { lldb_r10_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { lldb_r11_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { lldb_r12_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { lldb_r13_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { lldb_r14_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { lldb_r15_x86_64, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { lldb_rax_x86_64, lldb_eax_x86_64, lldb_ax_x86_64, lldb_ah_x86_64, lldb_al_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { lldb_rbx_x86_64, lldb_ebx_x86_64, lldb_bx_x86_64, lldb_bh_x86_64, lldb_bl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { lldb_rcx_x86_64, lldb_ecx_x86_64, lldb_cx_x86_64, lldb_ch_x86_64, lldb_cl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { lldb_rdx_x86_64, lldb_edx_x86_64, lldb_dx_x86_64, lldb_dh_x86_64, lldb_dl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { lldb_rdi_x86_64, lldb_edi_x86_64, lldb_di_x86_64, lldb_dil_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { lldb_rsi_x86_64, lldb_esi_x86_64, lldb_si_x86_64, lldb_sil_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { lldb_rbp_x86_64, lldb_ebp_x86_64, lldb_bp_x86_64, lldb_bpl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { lldb_rsp_x86_64, lldb_esp_x86_64, lldb_sp_x86_64, lldb_spl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { lldb_r8_x86_64, lldb_r8d_x86_64, lldb_r8w_x86_64, lldb_r8l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { lldb_r9_x86_64, lldb_r9d_x86_64, lldb_r9w_x86_64, lldb_r9l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { lldb_r10_x86_64, lldb_r10d_x86_64, lldb_r10w_x86_64, lldb_r10l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { lldb_r11_x86_64, lldb_r11d_x86_64, lldb_r11w_x86_64, lldb_r11l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { lldb_r12_x86_64, lldb_r12d_x86_64, lldb_r12w_x86_64, lldb_r12l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { lldb_r13_x86_64, lldb_r13d_x86_64, lldb_r13w_x86_64, lldb_r13l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { lldb_r14_x86_64, lldb_r14d_x86_64, lldb_r14w_x86_64, lldb_r14l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { lldb_r15_x86_64, lldb_r15d_x86_64, lldb_r15w_x86_64, lldb_r15l_x86_64, LLDB_INVALID_REGNUM }; +static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - + 1 == + k_num_avx_registers_x86_64, + "g_avx_regnums_x86_64 has wrong number of register infos"); + +uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = {lldb_eax_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = {lldb_ebx_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = {lldb_ecx_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = {lldb_edx_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = {lldb_edi_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = {lldb_esi_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = {lldb_ebp_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = {lldb_esp_i386, + LLDB_INVALID_REGNUM}; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { + lldb_eax_i386, lldb_ax_i386, lldb_ah_i386, lldb_al_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { + lldb_ebx_i386, lldb_bx_i386, lldb_bh_i386, lldb_bl_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { + lldb_ecx_i386, lldb_cx_i386, lldb_ch_i386, lldb_cl_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { + lldb_edx_i386, lldb_dx_i386, lldb_dh_i386, lldb_dl_i386, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { + lldb_edi_i386, lldb_di_i386, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { + lldb_esi_i386, lldb_si_i386, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { + lldb_ebp_i386, lldb_bp_i386, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { + lldb_esp_i386, lldb_sp_i386, LLDB_INVALID_REGNUM}; + +uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = {lldb_rax_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = {lldb_rbx_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = {lldb_rcx_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = {lldb_rdx_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = {lldb_rdi_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = {lldb_rsi_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = {lldb_rbp_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = {lldb_rsp_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = {lldb_r8_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = {lldb_r9_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = {lldb_r10_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = {lldb_r11_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = {lldb_r12_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = {lldb_r13_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = {lldb_r14_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = {lldb_r15_x86_64, + LLDB_INVALID_REGNUM}; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { + lldb_rax_x86_64, lldb_eax_x86_64, lldb_ax_x86_64, + lldb_ah_x86_64, lldb_al_x86_64, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { + lldb_rbx_x86_64, lldb_ebx_x86_64, lldb_bx_x86_64, + lldb_bh_x86_64, lldb_bl_x86_64, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { + lldb_rcx_x86_64, lldb_ecx_x86_64, lldb_cx_x86_64, + lldb_ch_x86_64, lldb_cl_x86_64, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { + lldb_rdx_x86_64, lldb_edx_x86_64, lldb_dx_x86_64, + lldb_dh_x86_64, lldb_dl_x86_64, LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { + lldb_rdi_x86_64, lldb_edi_x86_64, lldb_di_x86_64, lldb_dil_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { + lldb_rsi_x86_64, lldb_esi_x86_64, lldb_si_x86_64, lldb_sil_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { + lldb_rbp_x86_64, lldb_ebp_x86_64, lldb_bp_x86_64, lldb_bpl_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { + lldb_rsp_x86_64, lldb_esp_x86_64, lldb_sp_x86_64, lldb_spl_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { + lldb_r8_x86_64, lldb_r8d_x86_64, lldb_r8w_x86_64, lldb_r8l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { + lldb_r9_x86_64, lldb_r9d_x86_64, lldb_r9w_x86_64, lldb_r9l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { + lldb_r10_x86_64, lldb_r10d_x86_64, lldb_r10w_x86_64, lldb_r10l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { + lldb_r11_x86_64, lldb_r11d_x86_64, lldb_r11w_x86_64, lldb_r11l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { + lldb_r12_x86_64, lldb_r12d_x86_64, lldb_r12w_x86_64, lldb_r12l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { + lldb_r13_x86_64, lldb_r13d_x86_64, lldb_r13w_x86_64, lldb_r13l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { + lldb_r14_x86_64, lldb_r14d_x86_64, lldb_r14w_x86_64, lldb_r14l_x86_64, + LLDB_INVALID_REGNUM}; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { + lldb_r15_x86_64, lldb_r15d_x86_64, lldb_r15w_x86_64, lldb_r15l_x86_64, + LLDB_INVALID_REGNUM}; // Number of register sets provided by this context. -enum -{ - k_num_extended_register_sets = 1, - k_num_register_sets = 3 -}; - -static const RegisterSet -g_reg_sets_i386[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_lldb_regnums_i386 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 } -}; - -static const RegisterSet -g_reg_sets_x86_64[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_lldb_regnums_x86_64 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 } -}; - -bool RegisterContextPOSIX_x86::IsGPR(unsigned reg) -{ - return reg <= m_reg_info.last_gpr; // GPR's come first. +enum { k_num_extended_register_sets = 1, k_num_register_sets = 3 }; + +static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, + g_gpr_regnums_i386}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, + g_lldb_regnums_i386}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, + g_avx_regnums_i386}}; + +static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, + g_gpr_regnums_x86_64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, + g_lldb_regnums_x86_64}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, + g_avx_regnums_x86_64}}; + +bool RegisterContextPOSIX_x86::IsGPR(unsigned reg) { + return reg <= m_reg_info.last_gpr; // GPR's come first. } -bool RegisterContextPOSIX_x86::IsFPR(unsigned reg) -{ - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +bool RegisterContextPOSIX_x86::IsFPR(unsigned reg) { + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -bool RegisterContextPOSIX_x86::IsAVX(unsigned reg) -{ - return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm); +bool RegisterContextPOSIX_x86::IsAVX(unsigned reg) { + return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm); } -bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type) -{ - bool generic_fpr = IsFPR(reg); +bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type) { + bool generic_fpr = IsFPR(reg); - if (fpr_type == eXSAVE) - return generic_fpr || IsAVX(reg); - return generic_fpr; + if (fpr_type == eXSAVE) + return generic_fpr || IsAVX(reg); + return generic_fpr; } -RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *register_info) - : RegisterContext(thread, concrete_frame_idx) -{ - m_register_info_ap.reset(register_info); - - switch (register_info->m_target_arch.GetMachine()) - { - case llvm::Triple::x86: - m_reg_info.num_registers = k_num_registers_i386; - m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; - m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; - m_reg_info.num_avx_registers = k_num_avx_registers_i386; - m_reg_info.last_gpr = k_last_gpr_i386; - m_reg_info.first_fpr = k_first_fpr_i386; - m_reg_info.last_fpr = k_last_fpr_i386; - m_reg_info.first_st = lldb_st0_i386; - m_reg_info.last_st = lldb_st7_i386; - m_reg_info.first_mm = lldb_mm0_i386; - m_reg_info.last_mm = lldb_mm7_i386; - m_reg_info.first_xmm = lldb_xmm0_i386; - m_reg_info.last_xmm = lldb_xmm7_i386; - m_reg_info.first_ymm = lldb_ymm0_i386; - m_reg_info.last_ymm = lldb_ymm7_i386; - m_reg_info.first_dr = lldb_dr0_i386; - m_reg_info.gpr_flags = lldb_eflags_i386; - break; - case llvm::Triple::x86_64: - m_reg_info.num_registers = k_num_registers_x86_64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; - m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; - m_reg_info.last_gpr = k_last_gpr_x86_64; - m_reg_info.first_fpr = k_first_fpr_x86_64; - m_reg_info.last_fpr = k_last_fpr_x86_64; - m_reg_info.first_st = lldb_st0_x86_64; - m_reg_info.last_st = lldb_st7_x86_64; - m_reg_info.first_mm = lldb_mm0_x86_64; - m_reg_info.last_mm = lldb_mm7_x86_64; - m_reg_info.first_xmm = lldb_xmm0_x86_64; - m_reg_info.last_xmm = lldb_xmm15_x86_64; - m_reg_info.first_ymm = lldb_ymm0_x86_64; - m_reg_info.last_ymm = lldb_ymm15_x86_64; - m_reg_info.first_dr = lldb_dr0_x86_64; - m_reg_info.gpr_flags = lldb_rflags_x86_64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Initialize m_iovec to point to the buffer and buffer size - // using the conventions of Berkeley style UIO structures, as required - // by PTRACE extensions. - m_iovec.iov_base = &m_fpr.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); - - ::memset(&m_fpr, 0, sizeof(FPR)); - - // elf-core yet to support ReadFPR() - ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; - - m_fpr_type = eNotValid; +RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); + + switch (register_info->m_target_arch.GetMachine()) { + case llvm::Triple::x86: + m_reg_info.num_registers = k_num_registers_i386; + m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; + m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; + m_reg_info.num_avx_registers = k_num_avx_registers_i386; + m_reg_info.last_gpr = k_last_gpr_i386; + m_reg_info.first_fpr = k_first_fpr_i386; + m_reg_info.last_fpr = k_last_fpr_i386; + m_reg_info.first_st = lldb_st0_i386; + m_reg_info.last_st = lldb_st7_i386; + m_reg_info.first_mm = lldb_mm0_i386; + m_reg_info.last_mm = lldb_mm7_i386; + m_reg_info.first_xmm = lldb_xmm0_i386; + m_reg_info.last_xmm = lldb_xmm7_i386; + m_reg_info.first_ymm = lldb_ymm0_i386; + m_reg_info.last_ymm = lldb_ymm7_i386; + m_reg_info.first_dr = lldb_dr0_i386; + m_reg_info.gpr_flags = lldb_eflags_i386; + break; + case llvm::Triple::x86_64: + m_reg_info.num_registers = k_num_registers_x86_64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; + m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; + m_reg_info.last_gpr = k_last_gpr_x86_64; + m_reg_info.first_fpr = k_first_fpr_x86_64; + m_reg_info.last_fpr = k_last_fpr_x86_64; + m_reg_info.first_st = lldb_st0_x86_64; + m_reg_info.last_st = lldb_st7_x86_64; + m_reg_info.first_mm = lldb_mm0_x86_64; + m_reg_info.last_mm = lldb_mm7_x86_64; + m_reg_info.first_xmm = lldb_xmm0_x86_64; + m_reg_info.last_xmm = lldb_xmm15_x86_64; + m_reg_info.first_ymm = lldb_ymm0_x86_64; + m_reg_info.last_ymm = lldb_ymm15_x86_64; + m_reg_info.first_dr = lldb_dr0_x86_64; + m_reg_info.gpr_flags = lldb_rflags_x86_64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Initialize m_iovec to point to the buffer and buffer size + // using the conventions of Berkeley style UIO structures, as required + // by PTRACE extensions. + m_iovec.iov_base = &m_fpr.xstate.xsave; + m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); + + ::memset(&m_fpr, 0, sizeof(FPR)); + + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; + + m_fpr_type = eNotValid; } -RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() -{ -} +RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() {} -RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() -{ - if (m_fpr_type == eNotValid) - { - // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx - m_fpr_type = eXSAVE; // extended floating-point registers, if available - if (false == ReadFPR()) - m_fpr_type = eFXSAVE; // assume generic floating-point registers - } - return m_fpr_type; +RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() { + if (m_fpr_type == eNotValid) { + // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx + m_fpr_type = eXSAVE; // extended floating-point registers, if available + if (false == ReadFPR()) + m_fpr_type = eFXSAVE; // assume generic floating-point registers + } + return m_fpr_type; } -void -RegisterContextPOSIX_x86::Invalidate() -{ -} +void RegisterContextPOSIX_x86::Invalidate() {} -void -RegisterContextPOSIX_x86::InvalidateAllRegisters() -{ -} +void RegisterContextPOSIX_x86::InvalidateAllRegisters() {} -unsigned -RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; +unsigned RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; } -unsigned -RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; +unsigned RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; } -size_t -RegisterContextPOSIX_x86::GetRegisterCount() -{ - size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; - if (GetFPRType() == eXSAVE) - return num_registers + m_reg_info.num_avx_registers; - return num_registers; +size_t RegisterContextPOSIX_x86::GetRegisterCount() { + size_t num_registers = + m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; + if (GetFPRType() == eXSAVE) + return num_registers + m_reg_info.num_avx_registers; + return num_registers; } -size_t -RegisterContextPOSIX_x86::GetGPRSize() -{ - return m_register_info_ap->GetGPRSize (); +size_t RegisterContextPOSIX_x86::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); } -const RegisterInfo * -RegisterContextPOSIX_x86::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return m_register_info_ap->GetRegisterInfo (); +const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); } const RegisterInfo * -RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < m_reg_info.num_registers) - return &GetRegisterInfo()[reg]; - else - return NULL; +RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg) { + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; } -size_t -RegisterContextPOSIX_x86::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - { - if (IsRegisterSetAvailable(set)) - ++sets; - } +size_t RegisterContextPOSIX_x86::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } - return sets; + return sets; } -const RegisterSet * -RegisterContextPOSIX_x86::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - { - switch (m_register_info_ap->m_target_arch.GetMachine()) - { - case llvm::Triple::x86: - return &g_reg_sets_i386[set]; - case llvm::Triple::x86_64: - return &g_reg_sets_x86_64[set]; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } +const RegisterSet *RegisterContextPOSIX_x86::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) { + switch (m_register_info_ap->m_target_arch.GetMachine()) { + case llvm::Triple::x86: + return &g_reg_sets_i386[set]; + case llvm::Triple::x86_64: + return &g_reg_sets_x86_64[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return NULL; + } + return NULL; } -const char * -RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) -{ - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return GetRegisterInfo()[reg].name; +const char *RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) { + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; } -lldb::ByteOrder -RegisterContextPOSIX_x86::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = eByteOrderInvalid; - Process *process = CalculateProcess().get(); +lldb::ByteOrder RegisterContextPOSIX_x86::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); - if (process) - byte_order = process->GetByteOrder(); - return byte_order; + if (process) + byte_order = process->GetByteOrder(); + return byte_order; } // Parse ymm registers and into xmm.bytes and ymmh.bytes. -bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order) -{ - if (!IsAVX(reg)) - return false; - - if (byte_order == eByteOrderLittle) - { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(YMMHReg)); - return true; - } - - if (byte_order == eByteOrderBig) - { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order +bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, + lldb::ByteOrder byte_order) { + if (!IsAVX(reg)) + return false; + + if (byte_order == eByteOrderLittle) { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(YMMHReg)); + return true; + } + + if (byte_order == eByteOrderBig) { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order } // Concatenate xmm.bytes with ymmh.bytes -bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order) -{ - if (!IsAVX(reg)) - return false; - - if (byte_order == eByteOrderLittle) - { - ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - - if (byte_order == eByteOrderBig) - { - ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order +bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, + lldb::ByteOrder byte_order) { + if (!IsAVX(reg)) + return false; + + if (byte_order == eByteOrderLittle) { + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + + if (byte_order == eByteOrderBig) { + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order } -bool -RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index) -{ - // Note: Extended register sets are assumed to be at the end of g_reg_sets... - size_t num_sets = k_num_register_sets - k_num_extended_register_sets; +bool RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index) { + // Note: Extended register sets are assumed to be at the end of g_reg_sets... + size_t num_sets = k_num_register_sets - k_num_extended_register_sets; - if (GetFPRType() == eXSAVE) // ...and to start with AVX registers. - ++num_sets; - return (set_index < num_sets); + if (GetFPRType() == eXSAVE) // ...and to start with AVX registers. + ++num_sets; + return (set_index < num_sets); } - // Used when parsing DWARF and EH frame information and any other -// object file sections that contain register numbers in them. -uint32_t -RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); - - assert (kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } +// object file sections that contain register numbers in them. +uint32_t RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); - return LLDB_INVALID_REGNUM; -} + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index b4708255a56..22f3493b4ee 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -14,181 +14,168 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" -#include "lldb/Target/RegisterContext.h" -#include "RegisterInfoInterface.h" #include "RegisterContext_x86.h" +#include "RegisterInfoInterface.h" #include "lldb-x86-register-enums.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" class ProcessMonitor; -class RegisterContextPOSIX_x86 - : public lldb_private::RegisterContext -{ +class RegisterContextPOSIX_x86 : public lldb_private::RegisterContext { public: - RegisterContextPOSIX_x86 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - - ~RegisterContextPOSIX_x86() override; - - void - Invalidate(); - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - virtual size_t - GetGPRSize(); - - virtual unsigned - GetRegisterSize(unsigned reg); - - virtual unsigned - GetRegisterOffset(unsigned reg); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set) override; - - const char * - GetRegisterName(unsigned reg); - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - //--------------------------------------------------------------------------- - // Note: prefer kernel definitions over user-land - //--------------------------------------------------------------------------- - enum FPRType - { - eNotValid = 0, - eFSAVE, // TODO - eFXSAVE, - eSOFT, // TODO - eXSAVE - }; - - static uint32_t g_contained_eax[]; - static uint32_t g_contained_ebx[]; - static uint32_t g_contained_ecx[]; - static uint32_t g_contained_edx[]; - static uint32_t g_contained_edi[]; - static uint32_t g_contained_esi[]; - static uint32_t g_contained_ebp[]; - static uint32_t g_contained_esp[]; - - static uint32_t g_invalidate_eax[]; - static uint32_t g_invalidate_ebx[]; - static uint32_t g_invalidate_ecx[]; - static uint32_t g_invalidate_edx[]; - static uint32_t g_invalidate_edi[]; - static uint32_t g_invalidate_esi[]; - static uint32_t g_invalidate_ebp[]; - static uint32_t g_invalidate_esp[]; - - static uint32_t g_contained_rax[]; - static uint32_t g_contained_rbx[]; - static uint32_t g_contained_rcx[]; - static uint32_t g_contained_rdx[]; - static uint32_t g_contained_rdi[]; - static uint32_t g_contained_rsi[]; - static uint32_t g_contained_rbp[]; - static uint32_t g_contained_rsp[]; - static uint32_t g_contained_r8[]; - static uint32_t g_contained_r9[]; - static uint32_t g_contained_r10[]; - static uint32_t g_contained_r11[]; - static uint32_t g_contained_r12[]; - static uint32_t g_contained_r13[]; - static uint32_t g_contained_r14[]; - static uint32_t g_contained_r15[]; - - static uint32_t g_invalidate_rax[]; - static uint32_t g_invalidate_rbx[]; - static uint32_t g_invalidate_rcx[]; - static uint32_t g_invalidate_rdx[]; - static uint32_t g_invalidate_rdi[]; - static uint32_t g_invalidate_rsi[]; - static uint32_t g_invalidate_rbp[]; - static uint32_t g_invalidate_rsp[]; - static uint32_t g_invalidate_r8[]; - static uint32_t g_invalidate_r9[]; - static uint32_t g_invalidate_r10[]; - static uint32_t g_invalidate_r11[]; - static uint32_t g_invalidate_r12[]; - static uint32_t g_invalidate_r13[]; - static uint32_t g_invalidate_r14[]; - static uint32_t g_invalidate_r15[]; + RegisterContextPOSIX_x86(lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); + + ~RegisterContextPOSIX_x86() override; + + void Invalidate(); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + const char *GetRegisterName(unsigned reg); + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + //--------------------------------------------------------------------------- + // Note: prefer kernel definitions over user-land + //--------------------------------------------------------------------------- + enum FPRType { + eNotValid = 0, + eFSAVE, // TODO + eFXSAVE, + eSOFT, // TODO + eXSAVE + }; + + static uint32_t g_contained_eax[]; + static uint32_t g_contained_ebx[]; + static uint32_t g_contained_ecx[]; + static uint32_t g_contained_edx[]; + static uint32_t g_contained_edi[]; + static uint32_t g_contained_esi[]; + static uint32_t g_contained_ebp[]; + static uint32_t g_contained_esp[]; + + static uint32_t g_invalidate_eax[]; + static uint32_t g_invalidate_ebx[]; + static uint32_t g_invalidate_ecx[]; + static uint32_t g_invalidate_edx[]; + static uint32_t g_invalidate_edi[]; + static uint32_t g_invalidate_esi[]; + static uint32_t g_invalidate_ebp[]; + static uint32_t g_invalidate_esp[]; + + static uint32_t g_contained_rax[]; + static uint32_t g_contained_rbx[]; + static uint32_t g_contained_rcx[]; + static uint32_t g_contained_rdx[]; + static uint32_t g_contained_rdi[]; + static uint32_t g_contained_rsi[]; + static uint32_t g_contained_rbp[]; + static uint32_t g_contained_rsp[]; + static uint32_t g_contained_r8[]; + static uint32_t g_contained_r9[]; + static uint32_t g_contained_r10[]; + static uint32_t g_contained_r11[]; + static uint32_t g_contained_r12[]; + static uint32_t g_contained_r13[]; + static uint32_t g_contained_r14[]; + static uint32_t g_contained_r15[]; + + static uint32_t g_invalidate_rax[]; + static uint32_t g_invalidate_rbx[]; + static uint32_t g_invalidate_rcx[]; + static uint32_t g_invalidate_rdx[]; + static uint32_t g_invalidate_rdi[]; + static uint32_t g_invalidate_rsi[]; + static uint32_t g_invalidate_rbp[]; + static uint32_t g_invalidate_rsp[]; + static uint32_t g_invalidate_r8[]; + static uint32_t g_invalidate_r9[]; + static uint32_t g_invalidate_r10[]; + static uint32_t g_invalidate_r11[]; + static uint32_t g_invalidate_r12[]; + static uint32_t g_invalidate_r13[]; + static uint32_t g_invalidate_r14[]; + static uint32_t g_invalidate_r15[]; protected: - struct RegInfo - { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - uint32_t num_avx_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - - uint32_t first_st; - uint32_t last_st; - uint32_t first_mm; - uint32_t last_mm; - uint32_t first_xmm; - uint32_t last_xmm; - uint32_t first_ymm; - uint32_t last_ymm; - - uint32_t first_dr; - uint32_t gpr_flags; - }; - - uint64_t m_gpr_x86_64[lldb_private::k_num_gpr_registers_x86_64]; // 64-bit general purpose registers. - RegInfo m_reg_info; - FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. - FPR m_fpr; // floating-point registers including extended register sets. - IOVEC m_iovec; // wrapper for xsave. - YMM m_ymm_set; // copy of ymmh and xmm register halves. - std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) - - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); - - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); - - bool - IsGPR(unsigned reg); - - bool - IsFPR(unsigned reg); - - bool - IsAVX(unsigned reg); - - lldb::ByteOrder GetByteOrder(); - - bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order); - bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); - bool IsFPR(unsigned reg, FPRType fpr_type); - FPRType GetFPRType(); - - virtual bool ReadGPR() = 0; - virtual bool ReadFPR() = 0; - virtual bool WriteGPR() = 0; - virtual bool WriteFPR() = 0; + struct RegInfo { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + uint32_t num_avx_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + + uint32_t first_st; + uint32_t last_st; + uint32_t first_mm; + uint32_t last_mm; + uint32_t first_xmm; + uint32_t last_xmm; + uint32_t first_ymm; + uint32_t last_ymm; + + uint32_t first_dr; + uint32_t gpr_flags; + }; + + uint64_t m_gpr_x86_64[lldb_private::k_num_gpr_registers_x86_64]; // 64-bit + // general + // purpose + // registers. + RegInfo m_reg_info; + FPRType + m_fpr_type; // determines the type of data stored by union FPR, if any. + FPR m_fpr; // floating-point registers including extended register sets. + IOVEC m_iovec; // wrapper for xsave. + YMM m_ymm_set; // copy of ymmh and xmm register halves. + std::unique_ptr<lldb_private::RegisterInfoInterface> + m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + bool IsAVX(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order); + bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); + bool IsFPR(unsigned reg, FPRType fpr_type); + FPRType GetFPRType(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; }; #endif // liblldb_RegisterContextPOSIX_x86_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index 200ef4d3d65..2b5cb00fa96 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -7,255 +7,213 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private.h" #include "lldb/Core/Error.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" #include "RegisterContextThreadMemory.h" using namespace lldb; using namespace lldb_private; -RegisterContextThreadMemory::RegisterContextThreadMemory (Thread &thread, - lldb::addr_t register_data_addr) : - RegisterContext (thread, 0), - m_thread_wp (thread.shared_from_this()), - m_reg_ctx_sp (), - m_register_data_addr (register_data_addr), - m_stop_id(0) -{ -} +RegisterContextThreadMemory::RegisterContextThreadMemory( + Thread &thread, lldb::addr_t register_data_addr) + : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()), + m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {} -RegisterContextThreadMemory::~RegisterContextThreadMemory() -{ -} +RegisterContextThreadMemory::~RegisterContextThreadMemory() {} -void -RegisterContextThreadMemory::UpdateRegisterContext () -{ - ThreadSP thread_sp (m_thread_wp.lock()); - if (thread_sp) - { - ProcessSP process_sp (thread_sp->GetProcess()); +void RegisterContextThreadMemory::UpdateRegisterContext() { + ThreadSP thread_sp(m_thread_wp.lock()); + if (thread_sp) { + ProcessSP process_sp(thread_sp->GetProcess()); - if (process_sp) - { - const uint32_t stop_id = process_sp->GetModID().GetStopID(); - if (m_stop_id != stop_id) - { - m_stop_id = stop_id; - m_reg_ctx_sp.reset(); - } - if (!m_reg_ctx_sp) - { - ThreadSP backing_thread_sp (thread_sp->GetBackingThread()); - if (backing_thread_sp) - { - m_reg_ctx_sp = backing_thread_sp->GetRegisterContext(); - } - else - { - OperatingSystem *os = process_sp->GetOperatingSystem (); - if (os->IsOperatingSystemPluginThread (thread_sp)) - m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), m_register_data_addr); - } - } - } - else - { - m_reg_ctx_sp.reset(); - } - } - else - { + if (process_sp) { + const uint32_t stop_id = process_sp->GetModID().GetStopID(); + if (m_stop_id != stop_id) { + m_stop_id = stop_id; m_reg_ctx_sp.reset(); + } + if (!m_reg_ctx_sp) { + ThreadSP backing_thread_sp(thread_sp->GetBackingThread()); + if (backing_thread_sp) { + m_reg_ctx_sp = backing_thread_sp->GetRegisterContext(); + } else { + OperatingSystem *os = process_sp->GetOperatingSystem(); + if (os->IsOperatingSystemPluginThread(thread_sp)) + m_reg_ctx_sp = os->CreateRegisterContextForThread( + thread_sp.get(), m_register_data_addr); + } + } + } else { + m_reg_ctx_sp.reset(); } + } else { + m_reg_ctx_sp.reset(); + } } //------------------------------------------------------------------ // Subclasses must override these functions //------------------------------------------------------------------ -void -RegisterContextThreadMemory::InvalidateAllRegisters () -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - m_reg_ctx_sp->InvalidateAllRegisters(); +void RegisterContextThreadMemory::InvalidateAllRegisters() { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + m_reg_ctx_sp->InvalidateAllRegisters(); } -size_t -RegisterContextThreadMemory::GetRegisterCount () -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->GetRegisterCount(); - return 0; +size_t RegisterContextThreadMemory::GetRegisterCount() { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterCount(); + return 0; } const RegisterInfo * -RegisterContextThreadMemory::GetRegisterInfoAtIndex (size_t reg) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg); - return NULL; -} - -size_t -RegisterContextThreadMemory::GetRegisterSetCount () -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->GetRegisterSetCount(); - return 0; -} - -const RegisterSet * -RegisterContextThreadMemory::GetRegisterSet (size_t reg_set) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->GetRegisterSet(reg_set); - return NULL; -} - -bool -RegisterContextThreadMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ReadRegister(reg_info, reg_value); - return false; -} - -bool -RegisterContextThreadMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->WriteRegister (reg_info, reg_value); - return false; -} - -bool -RegisterContextThreadMemory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ReadAllRegisterValues(data_sp); - return false; -} - -bool -RegisterContextThreadMemory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->WriteAllRegisterValues (data_sp); - return false; -} - -bool -RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP reg_ctx_sp) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp); - return false; -} - -uint32_t -RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num); - return false; -} - -uint32_t -RegisterContextThreadMemory::NumSupportedHardwareBreakpoints () -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->NumSupportedHardwareBreakpoints(); - return false; -} - -uint32_t -RegisterContextThreadMemory::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size); - return 0; -} - -bool -RegisterContextThreadMemory::ClearHardwareBreakpoint (uint32_t hw_idx) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ClearHardwareBreakpoint (hw_idx); - return false; -} - -uint32_t -RegisterContextThreadMemory::NumSupportedHardwareWatchpoints () -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->NumSupportedHardwareWatchpoints(); - return 0; +RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg); + return NULL; } -uint32_t -RegisterContextThreadMemory::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write); - return 0; +size_t RegisterContextThreadMemory::GetRegisterSetCount() { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterSetCount(); + return 0; } -bool -RegisterContextThreadMemory::ClearHardwareWatchpoint (uint32_t hw_index) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index); - return false; +const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->GetRegisterSet(reg_set); + return NULL; } -bool -RegisterContextThreadMemory::HardwareSingleStep (bool enable) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->HardwareSingleStep(enable); - return false; +bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegister(reg_info, reg_value); + return false; } -Error -RegisterContextThreadMemory::ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->ReadRegisterValueFromMemory (reg_info, src_addr, src_len, reg_value); - Error error; - error.SetErrorString("invalid register context"); - return error; +bool RegisterContextThreadMemory::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegister(reg_info, reg_value); + return false; } -Error -RegisterContextThreadMemory::WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value) -{ - UpdateRegisterContext (); - if (m_reg_ctx_sp) - return m_reg_ctx_sp->WriteRegisterValueToMemory (reg_info, dst_addr, dst_len, reg_value); - Error error; - error.SetErrorString("invalid register context"); - return error; +bool RegisterContextThreadMemory::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadAllRegisterValues(data_sp); + return false; +} + +bool RegisterContextThreadMemory::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteAllRegisterValues(data_sp); + return false; +} + +bool RegisterContextThreadMemory::CopyFromRegisterContext( + lldb::RegisterContextSP reg_ctx_sp) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp); + return false; +} + +uint32_t RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num); + return false; +} + +uint32_t RegisterContextThreadMemory::NumSupportedHardwareBreakpoints() { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareBreakpoints(); + return false; +} + +uint32_t RegisterContextThreadMemory::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size); + return 0; +} + +bool RegisterContextThreadMemory::ClearHardwareBreakpoint(uint32_t hw_idx) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareBreakpoint(hw_idx); + return false; +} + +uint32_t RegisterContextThreadMemory::NumSupportedHardwareWatchpoints() { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t RegisterContextThreadMemory::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, + bool read, + bool write) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write); + return 0; +} + +bool RegisterContextThreadMemory::ClearHardwareWatchpoint(uint32_t hw_index) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index); + return false; +} + +bool RegisterContextThreadMemory::HardwareSingleStep(bool enable) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->HardwareSingleStep(enable); + return false; +} + +Error RegisterContextThreadMemory::ReadRegisterValueFromMemory( + const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, + uint32_t src_len, RegisterValue ®_value) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->ReadRegisterValueFromMemory(reg_info, src_addr, + src_len, reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; +} + +Error RegisterContextThreadMemory::WriteRegisterValueToMemory( + const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, + uint32_t dst_len, const RegisterValue ®_value) { + UpdateRegisterContext(); + if (m_reg_ctx_sp) + return m_reg_ctx_sp->WriteRegisterValueToMemory(reg_info, dst_addr, dst_len, + reg_value); + Error error; + error.SetErrorString("invalid register context"); + return error; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h index b4680de7951..7e0a2a9f7f1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h @@ -16,103 +16,88 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" namespace lldb_private { - -class RegisterContextThreadMemory : public lldb_private::RegisterContext -{ + +class RegisterContextThreadMemory : public lldb_private::RegisterContext { public: - RegisterContextThreadMemory (Thread &thread, - lldb::addr_t register_data_addr); - - ~RegisterContextThreadMemory() override; - - void - InvalidateAllRegisters() override; - - size_t - GetRegisterCount() override; - - const RegisterInfo * - GetRegisterInfoAtIndex(size_t reg) override; - - size_t - GetRegisterSetCount() override; - - const RegisterSet * - GetRegisterSet(size_t reg_set) override; - - bool - ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; - - bool - WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; - - // These two functions are used to implement "push" and "pop" of register states. They are used primarily - // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then - // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues. - // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which - // may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation, - // so these API's should only be used when this behavior is needed. - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - bool - CopyFromRegisterContext (lldb::RegisterContextSP context); - - uint32_t - ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - - uint32_t - NumSupportedHardwareBreakpoints() override; - - uint32_t - SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - - bool - ClearHardwareBreakpoint(uint32_t hw_idx) override; - - uint32_t - NumSupportedHardwareWatchpoints() override; - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; - - bool - ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool - HardwareSingleStep(bool enable) override; - - Error - ReadRegisterValueFromMemory(const lldb_private::RegisterInfo *reg_info, - lldb::addr_t src_addr, - uint32_t src_len, - RegisterValue ®_value) override; - - Error - WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info, - lldb::addr_t dst_addr, uint32_t dst_len, - const RegisterValue ®_value) override; + RegisterContextThreadMemory(Thread &thread, lldb::addr_t register_data_addr); + + ~RegisterContextThreadMemory() override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const RegisterSet *GetRegisterSet(size_t reg_set) override; + + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + // These two functions are used to implement "push" and "pop" of register + // states. They are used primarily + // for expression evaluation, where we need to push a new state (storing the + // old one in data_sp) and then + // restoring the original state by passing the data_sp we got from + // ReadAllRegisters to WriteAllRegisterValues. + // ReadAllRegisters will do what is necessary to return a coherent set of + // register values for this thread, which + // may mean e.g. interrupting a thread that is sitting in a kernel trap. That + // is a somewhat disruptive operation, + // so these API's should only be used when this behavior is needed. + + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + bool CopyFromRegisterContext(lldb::RegisterContextSP context); + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + uint32_t NumSupportedHardwareBreakpoints() override; + + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + + uint32_t NumSupportedHardwareWatchpoints() override; + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write) override; + + bool ClearHardwareWatchpoint(uint32_t hw_index) override; + + bool HardwareSingleStep(bool enable) override; + + Error ReadRegisterValueFromMemory(const lldb_private::RegisterInfo *reg_info, + lldb::addr_t src_addr, uint32_t src_len, + RegisterValue ®_value) override; + + Error WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info, + lldb::addr_t dst_addr, uint32_t dst_len, + const RegisterValue ®_value) override; protected: - void - UpdateRegisterContext (); - - lldb::ThreadWP m_thread_wp; - lldb::RegisterContextSP m_reg_ctx_sp; - lldb::addr_t m_register_data_addr; - uint32_t m_stop_id; + void UpdateRegisterContext(); + + lldb::ThreadWP m_thread_wp; + lldb::RegisterContextSP m_reg_ctx_sp; + lldb::addr_t m_register_data_addr; + uint32_t m_stop_id; private: - DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory); + DISALLOW_COPY_AND_ASSIGN(RegisterContextThreadMemory); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h b/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h index de628238018..565747cb4bd 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h @@ -13,375 +13,368 @@ #include <cstddef> #include <cstdint> -// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF) +// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & +// eRegisterKindDWARF) -enum -{ - // GP Registers - dwarf_zero_mips = 0, - dwarf_r1_mips, - dwarf_r2_mips, - dwarf_r3_mips, - dwarf_r4_mips, - dwarf_r5_mips, - dwarf_r6_mips, - dwarf_r7_mips, - dwarf_r8_mips, - dwarf_r9_mips, - dwarf_r10_mips, - dwarf_r11_mips, - dwarf_r12_mips, - dwarf_r13_mips, - dwarf_r14_mips, - dwarf_r15_mips, - dwarf_r16_mips, - dwarf_r17_mips, - dwarf_r18_mips, - dwarf_r19_mips, - dwarf_r20_mips, - dwarf_r21_mips, - dwarf_r22_mips, - dwarf_r23_mips, - dwarf_r24_mips, - dwarf_r25_mips, - dwarf_r26_mips, - dwarf_r27_mips, - dwarf_gp_mips, - dwarf_sp_mips, - dwarf_r30_mips, - dwarf_ra_mips, - dwarf_sr_mips, - dwarf_lo_mips, - dwarf_hi_mips, - dwarf_bad_mips, - dwarf_cause_mips, - dwarf_pc_mips, - dwarf_f0_mips, - dwarf_f1_mips, - dwarf_f2_mips, - dwarf_f3_mips, - dwarf_f4_mips, - dwarf_f5_mips, - dwarf_f6_mips, - dwarf_f7_mips, - dwarf_f8_mips, - dwarf_f9_mips, - dwarf_f10_mips, - dwarf_f11_mips, - dwarf_f12_mips, - dwarf_f13_mips, - dwarf_f14_mips, - dwarf_f15_mips, - dwarf_f16_mips, - dwarf_f17_mips, - dwarf_f18_mips, - dwarf_f19_mips, - dwarf_f20_mips, - dwarf_f21_mips, - dwarf_f22_mips, - dwarf_f23_mips, - dwarf_f24_mips, - dwarf_f25_mips, - dwarf_f26_mips, - dwarf_f27_mips, - dwarf_f28_mips, - dwarf_f29_mips, - dwarf_f30_mips, - dwarf_f31_mips, - dwarf_fcsr_mips, - dwarf_fir_mips, - dwarf_w0_mips, - dwarf_w1_mips, - dwarf_w2_mips, - dwarf_w3_mips, - dwarf_w4_mips, - dwarf_w5_mips, - dwarf_w6_mips, - dwarf_w7_mips, - dwarf_w8_mips, - dwarf_w9_mips, - dwarf_w10_mips, - dwarf_w11_mips, - dwarf_w12_mips, - dwarf_w13_mips, - dwarf_w14_mips, - dwarf_w15_mips, - dwarf_w16_mips, - dwarf_w17_mips, - dwarf_w18_mips, - dwarf_w19_mips, - dwarf_w20_mips, - dwarf_w21_mips, - dwarf_w22_mips, - dwarf_w23_mips, - dwarf_w24_mips, - dwarf_w25_mips, - dwarf_w26_mips, - dwarf_w27_mips, - dwarf_w28_mips, - dwarf_w29_mips, - dwarf_w30_mips, - dwarf_w31_mips, - dwarf_mcsr_mips, - dwarf_mir_mips, - dwarf_config5_mips, - dwarf_ic_mips, - dwarf_dummy_mips +enum { + // GP Registers + dwarf_zero_mips = 0, + dwarf_r1_mips, + dwarf_r2_mips, + dwarf_r3_mips, + dwarf_r4_mips, + dwarf_r5_mips, + dwarf_r6_mips, + dwarf_r7_mips, + dwarf_r8_mips, + dwarf_r9_mips, + dwarf_r10_mips, + dwarf_r11_mips, + dwarf_r12_mips, + dwarf_r13_mips, + dwarf_r14_mips, + dwarf_r15_mips, + dwarf_r16_mips, + dwarf_r17_mips, + dwarf_r18_mips, + dwarf_r19_mips, + dwarf_r20_mips, + dwarf_r21_mips, + dwarf_r22_mips, + dwarf_r23_mips, + dwarf_r24_mips, + dwarf_r25_mips, + dwarf_r26_mips, + dwarf_r27_mips, + dwarf_gp_mips, + dwarf_sp_mips, + dwarf_r30_mips, + dwarf_ra_mips, + dwarf_sr_mips, + dwarf_lo_mips, + dwarf_hi_mips, + dwarf_bad_mips, + dwarf_cause_mips, + dwarf_pc_mips, + dwarf_f0_mips, + dwarf_f1_mips, + dwarf_f2_mips, + dwarf_f3_mips, + dwarf_f4_mips, + dwarf_f5_mips, + dwarf_f6_mips, + dwarf_f7_mips, + dwarf_f8_mips, + dwarf_f9_mips, + dwarf_f10_mips, + dwarf_f11_mips, + dwarf_f12_mips, + dwarf_f13_mips, + dwarf_f14_mips, + dwarf_f15_mips, + dwarf_f16_mips, + dwarf_f17_mips, + dwarf_f18_mips, + dwarf_f19_mips, + dwarf_f20_mips, + dwarf_f21_mips, + dwarf_f22_mips, + dwarf_f23_mips, + dwarf_f24_mips, + dwarf_f25_mips, + dwarf_f26_mips, + dwarf_f27_mips, + dwarf_f28_mips, + dwarf_f29_mips, + dwarf_f30_mips, + dwarf_f31_mips, + dwarf_fcsr_mips, + dwarf_fir_mips, + dwarf_w0_mips, + dwarf_w1_mips, + dwarf_w2_mips, + dwarf_w3_mips, + dwarf_w4_mips, + dwarf_w5_mips, + dwarf_w6_mips, + dwarf_w7_mips, + dwarf_w8_mips, + dwarf_w9_mips, + dwarf_w10_mips, + dwarf_w11_mips, + dwarf_w12_mips, + dwarf_w13_mips, + dwarf_w14_mips, + dwarf_w15_mips, + dwarf_w16_mips, + dwarf_w17_mips, + dwarf_w18_mips, + dwarf_w19_mips, + dwarf_w20_mips, + dwarf_w21_mips, + dwarf_w22_mips, + dwarf_w23_mips, + dwarf_w24_mips, + dwarf_w25_mips, + dwarf_w26_mips, + dwarf_w27_mips, + dwarf_w28_mips, + dwarf_w29_mips, + dwarf_w30_mips, + dwarf_w31_mips, + dwarf_mcsr_mips, + dwarf_mir_mips, + dwarf_config5_mips, + dwarf_ic_mips, + dwarf_dummy_mips }; -enum -{ - dwarf_zero_mips64 = 0, - dwarf_r1_mips64, - dwarf_r2_mips64, - dwarf_r3_mips64, - dwarf_r4_mips64, - dwarf_r5_mips64, - dwarf_r6_mips64, - dwarf_r7_mips64, - dwarf_r8_mips64, - dwarf_r9_mips64, - dwarf_r10_mips64, - dwarf_r11_mips64, - dwarf_r12_mips64, - dwarf_r13_mips64, - dwarf_r14_mips64, - dwarf_r15_mips64, - dwarf_r16_mips64, - dwarf_r17_mips64, - dwarf_r18_mips64, - dwarf_r19_mips64, - dwarf_r20_mips64, - dwarf_r21_mips64, - dwarf_r22_mips64, - dwarf_r23_mips64, - dwarf_r24_mips64, - dwarf_r25_mips64, - dwarf_r26_mips64, - dwarf_r27_mips64, - dwarf_gp_mips64, - dwarf_sp_mips64, - dwarf_r30_mips64, - dwarf_ra_mips64, - dwarf_sr_mips64, - dwarf_lo_mips64, - dwarf_hi_mips64, - dwarf_bad_mips64, - dwarf_cause_mips64, - dwarf_pc_mips64, - dwarf_f0_mips64, - dwarf_f1_mips64, - dwarf_f2_mips64, - dwarf_f3_mips64, - dwarf_f4_mips64, - dwarf_f5_mips64, - dwarf_f6_mips64, - dwarf_f7_mips64, - dwarf_f8_mips64, - dwarf_f9_mips64, - dwarf_f10_mips64, - dwarf_f11_mips64, - dwarf_f12_mips64, - dwarf_f13_mips64, - dwarf_f14_mips64, - dwarf_f15_mips64, - dwarf_f16_mips64, - dwarf_f17_mips64, - dwarf_f18_mips64, - dwarf_f19_mips64, - dwarf_f20_mips64, - dwarf_f21_mips64, - dwarf_f22_mips64, - dwarf_f23_mips64, - dwarf_f24_mips64, - dwarf_f25_mips64, - dwarf_f26_mips64, - dwarf_f27_mips64, - dwarf_f28_mips64, - dwarf_f29_mips64, - dwarf_f30_mips64, - dwarf_f31_mips64, - dwarf_fcsr_mips64, - dwarf_fir_mips64, - dwarf_ic_mips64, - dwarf_dummy_mips64, - dwarf_w0_mips64, - dwarf_w1_mips64, - dwarf_w2_mips64, - dwarf_w3_mips64, - dwarf_w4_mips64, - dwarf_w5_mips64, - dwarf_w6_mips64, - dwarf_w7_mips64, - dwarf_w8_mips64, - dwarf_w9_mips64, - dwarf_w10_mips64, - dwarf_w11_mips64, - dwarf_w12_mips64, - dwarf_w13_mips64, - dwarf_w14_mips64, - dwarf_w15_mips64, - dwarf_w16_mips64, - dwarf_w17_mips64, - dwarf_w18_mips64, - dwarf_w19_mips64, - dwarf_w20_mips64, - dwarf_w21_mips64, - dwarf_w22_mips64, - dwarf_w23_mips64, - dwarf_w24_mips64, - dwarf_w25_mips64, - dwarf_w26_mips64, - dwarf_w27_mips64, - dwarf_w28_mips64, - dwarf_w29_mips64, - dwarf_w30_mips64, - dwarf_w31_mips64, - dwarf_mcsr_mips64, - dwarf_mir_mips64, - dwarf_config5_mips64, +enum { + dwarf_zero_mips64 = 0, + dwarf_r1_mips64, + dwarf_r2_mips64, + dwarf_r3_mips64, + dwarf_r4_mips64, + dwarf_r5_mips64, + dwarf_r6_mips64, + dwarf_r7_mips64, + dwarf_r8_mips64, + dwarf_r9_mips64, + dwarf_r10_mips64, + dwarf_r11_mips64, + dwarf_r12_mips64, + dwarf_r13_mips64, + dwarf_r14_mips64, + dwarf_r15_mips64, + dwarf_r16_mips64, + dwarf_r17_mips64, + dwarf_r18_mips64, + dwarf_r19_mips64, + dwarf_r20_mips64, + dwarf_r21_mips64, + dwarf_r22_mips64, + dwarf_r23_mips64, + dwarf_r24_mips64, + dwarf_r25_mips64, + dwarf_r26_mips64, + dwarf_r27_mips64, + dwarf_gp_mips64, + dwarf_sp_mips64, + dwarf_r30_mips64, + dwarf_ra_mips64, + dwarf_sr_mips64, + dwarf_lo_mips64, + dwarf_hi_mips64, + dwarf_bad_mips64, + dwarf_cause_mips64, + dwarf_pc_mips64, + dwarf_f0_mips64, + dwarf_f1_mips64, + dwarf_f2_mips64, + dwarf_f3_mips64, + dwarf_f4_mips64, + dwarf_f5_mips64, + dwarf_f6_mips64, + dwarf_f7_mips64, + dwarf_f8_mips64, + dwarf_f9_mips64, + dwarf_f10_mips64, + dwarf_f11_mips64, + dwarf_f12_mips64, + dwarf_f13_mips64, + dwarf_f14_mips64, + dwarf_f15_mips64, + dwarf_f16_mips64, + dwarf_f17_mips64, + dwarf_f18_mips64, + dwarf_f19_mips64, + dwarf_f20_mips64, + dwarf_f21_mips64, + dwarf_f22_mips64, + dwarf_f23_mips64, + dwarf_f24_mips64, + dwarf_f25_mips64, + dwarf_f26_mips64, + dwarf_f27_mips64, + dwarf_f28_mips64, + dwarf_f29_mips64, + dwarf_f30_mips64, + dwarf_f31_mips64, + dwarf_fcsr_mips64, + dwarf_fir_mips64, + dwarf_ic_mips64, + dwarf_dummy_mips64, + dwarf_w0_mips64, + dwarf_w1_mips64, + dwarf_w2_mips64, + dwarf_w3_mips64, + dwarf_w4_mips64, + dwarf_w5_mips64, + dwarf_w6_mips64, + dwarf_w7_mips64, + dwarf_w8_mips64, + dwarf_w9_mips64, + dwarf_w10_mips64, + dwarf_w11_mips64, + dwarf_w12_mips64, + dwarf_w13_mips64, + dwarf_w14_mips64, + dwarf_w15_mips64, + dwarf_w16_mips64, + dwarf_w17_mips64, + dwarf_w18_mips64, + dwarf_w19_mips64, + dwarf_w20_mips64, + dwarf_w21_mips64, + dwarf_w22_mips64, + dwarf_w23_mips64, + dwarf_w24_mips64, + dwarf_w25_mips64, + dwarf_w26_mips64, + dwarf_w27_mips64, + dwarf_w28_mips64, + dwarf_w29_mips64, + dwarf_w30_mips64, + dwarf_w31_mips64, + dwarf_mcsr_mips64, + dwarf_mir_mips64, + dwarf_config5_mips64, }; -struct IOVEC_mips -{ - void *iov_base; - size_t iov_len; +struct IOVEC_mips { + void *iov_base; + size_t iov_len; }; // GP registers -struct GPR_linux_mips -{ - uint64_t zero; - uint64_t r1; - uint64_t r2; - uint64_t r3; - uint64_t r4; - uint64_t r5; - uint64_t r6; - uint64_t r7; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t r16; - uint64_t r17; - uint64_t r18; - uint64_t r19; - uint64_t r20; - uint64_t r21; - uint64_t r22; - uint64_t r23; - uint64_t r24; - uint64_t r25; - uint64_t r26; - uint64_t r27; - uint64_t gp; - uint64_t sp; - uint64_t r30; - uint64_t ra; - uint64_t mullo; - uint64_t mulhi; - uint64_t pc; - uint64_t badvaddr; - uint64_t sr; - uint64_t cause; - uint64_t config5; +struct GPR_linux_mips { + uint64_t zero; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t gp; + uint64_t sp; + uint64_t r30; + uint64_t ra; + uint64_t mullo; + uint64_t mulhi; + uint64_t pc; + uint64_t badvaddr; + uint64_t sr; + uint64_t cause; + uint64_t config5; }; -struct FPR_linux_mips -{ - uint64_t f0; - uint64_t f1; - uint64_t f2; - uint64_t f3; - uint64_t f4; - uint64_t f5; - uint64_t f6; - uint64_t f7; - uint64_t f8; - uint64_t f9; - uint64_t f10; - uint64_t f11; - uint64_t f12; - uint64_t f13; - uint64_t f14; - uint64_t f15; - uint64_t f16; - uint64_t f17; - uint64_t f18; - uint64_t f19; - uint64_t f20; - uint64_t f21; - uint64_t f22; - uint64_t f23; - uint64_t f24; - uint64_t f25; - uint64_t f26; - uint64_t f27; - uint64_t f28; - uint64_t f29; - uint64_t f30; - uint64_t f31; - uint32_t fcsr; - uint32_t fir; - uint32_t config5; +struct FPR_linux_mips { + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; + uint64_t f6; + uint64_t f7; + uint64_t f8; + uint64_t f9; + uint64_t f10; + uint64_t f11; + uint64_t f12; + uint64_t f13; + uint64_t f14; + uint64_t f15; + uint64_t f16; + uint64_t f17; + uint64_t f18; + uint64_t f19; + uint64_t f20; + uint64_t f21; + uint64_t f22; + uint64_t f23; + uint64_t f24; + uint64_t f25; + uint64_t f26; + uint64_t f27; + uint64_t f28; + uint64_t f29; + uint64_t f30; + uint64_t f31; + uint32_t fcsr; + uint32_t fir; + uint32_t config5; }; -struct MSAReg -{ - uint8_t byte[16]; +struct MSAReg { + uint8_t byte[16]; }; -struct MSA_linux_mips -{ - MSAReg w0; - MSAReg w1; - MSAReg w2; - MSAReg w3; - MSAReg w4; - MSAReg w5; - MSAReg w6; - MSAReg w7; - MSAReg w8; - MSAReg w9; - MSAReg w10; - MSAReg w11; - MSAReg w12; - MSAReg w13; - MSAReg w14; - MSAReg w15; - MSAReg w16; - MSAReg w17; - MSAReg w18; - MSAReg w19; - MSAReg w20; - MSAReg w21; - MSAReg w22; - MSAReg w23; - MSAReg w24; - MSAReg w25; - MSAReg w26; - MSAReg w27; - MSAReg w28; - MSAReg w29; - MSAReg w30; - MSAReg w31; - uint32_t fcsr; /* FPU control status register */ - uint32_t fir; /* FPU implementaion revision */ - uint32_t mcsr; /* MSA control status register */ - uint32_t mir; /* MSA implementation revision */ - uint32_t config5; /* Config5 register */ +struct MSA_linux_mips { + MSAReg w0; + MSAReg w1; + MSAReg w2; + MSAReg w3; + MSAReg w4; + MSAReg w5; + MSAReg w6; + MSAReg w7; + MSAReg w8; + MSAReg w9; + MSAReg w10; + MSAReg w11; + MSAReg w12; + MSAReg w13; + MSAReg w14; + MSAReg w15; + MSAReg w16; + MSAReg w17; + MSAReg w18; + MSAReg w19; + MSAReg w20; + MSAReg w21; + MSAReg w22; + MSAReg w23; + MSAReg w24; + MSAReg w25; + MSAReg w26; + MSAReg w27; + MSAReg w28; + MSAReg w29; + MSAReg w30; + MSAReg w31; + uint32_t fcsr; /* FPU control status register */ + uint32_t fir; /* FPU implementaion revision */ + uint32_t mcsr; /* MSA control status register */ + uint32_t mir; /* MSA implementation revision */ + uint32_t config5; /* Config5 register */ }; -struct UserArea -{ - GPR_linux_mips gpr; // General purpose registers. - FPR_linux_mips fpr; // Floating point registers. - MSA_linux_mips msa; // MSA registers. +struct UserArea { + GPR_linux_mips gpr; // General purpose registers. + FPR_linux_mips fpr; // Floating point registers. + MSA_linux_mips msa; // MSA registers. }; #endif // liblldb_RegisterContext_mips64_H_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h index 2e3053cf37b..73242952c6d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -1,4 +1,5 @@ -//===-- RegisterContext_powerpc.h --------------------------------*- C++ -*-===// +//===-- RegisterContext_powerpc.h --------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,114 +11,114 @@ #ifndef liblldb_RegisterContext_powerpc_H_ #define liblldb_RegisterContext_powerpc_H_ -// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF) -enum -{ - dwarf_r0_powerpc = 0, - dwarf_r1_powerpc, - dwarf_r2_powerpc, - dwarf_r3_powerpc, - dwarf_r4_powerpc, - dwarf_r5_powerpc, - dwarf_r6_powerpc, - dwarf_r7_powerpc, - dwarf_r8_powerpc, - dwarf_r9_powerpc, - dwarf_r10_powerpc, - dwarf_r11_powerpc, - dwarf_r12_powerpc, - dwarf_r13_powerpc, - dwarf_r14_powerpc, - dwarf_r15_powerpc, - dwarf_r16_powerpc, - dwarf_r17_powerpc, - dwarf_r18_powerpc, - dwarf_r19_powerpc, - dwarf_r20_powerpc, - dwarf_r21_powerpc, - dwarf_r22_powerpc, - dwarf_r23_powerpc, - dwarf_r24_powerpc, - dwarf_r25_powerpc, - dwarf_r26_powerpc, - dwarf_r27_powerpc, - dwarf_r28_powerpc, - dwarf_r29_powerpc, - dwarf_r30_powerpc, - dwarf_r31_powerpc, - dwarf_f0_powerpc, - dwarf_f1_powerpc, - dwarf_f2_powerpc, - dwarf_f3_powerpc, - dwarf_f4_powerpc, - dwarf_f5_powerpc, - dwarf_f6_powerpc, - dwarf_f7_powerpc, - dwarf_f8_powerpc, - dwarf_f9_powerpc, - dwarf_f10_powerpc, - dwarf_f11_powerpc, - dwarf_f12_powerpc, - dwarf_f13_powerpc, - dwarf_f14_powerpc, - dwarf_f15_powerpc, - dwarf_f16_powerpc, - dwarf_f17_powerpc, - dwarf_f18_powerpc, - dwarf_f19_powerpc, - dwarf_f20_powerpc, - dwarf_f21_powerpc, - dwarf_f22_powerpc, - dwarf_f23_powerpc, - dwarf_f24_powerpc, - dwarf_f25_powerpc, - dwarf_f26_powerpc, - dwarf_f27_powerpc, - dwarf_f28_powerpc, - dwarf_f29_powerpc, - dwarf_f30_powerpc, - dwarf_f31_powerpc, - dwarf_cr_powerpc, - dwarf_fpscr_powerpc, - dwarf_msr_powerpc, - dwarf_vscr_powerpc, - dwarf_xer_powerpc = 101, - dwarf_lr_powerpc = 108, - dwarf_ctr_powerpc, - dwarf_pc_powerpc, - dwarf_vrsave_powerpc = 356, - dwarf_v0_powerpc = 1124, - dwarf_v1_powerpc, - dwarf_v2_powerpc, - dwarf_v3_powerpc, - dwarf_v4_powerpc, - dwarf_v5_powerpc, - dwarf_v6_powerpc, - dwarf_v7_powerpc, - dwarf_v8_powerpc, - dwarf_v9_powerpc, - dwarf_v10_powerpc, - dwarf_v11_powerpc, - dwarf_v12_powerpc, - dwarf_v13_powerpc, - dwarf_v14_powerpc, - dwarf_v15_powerpc, - dwarf_v16_powerpc, - dwarf_v17_powerpc, - dwarf_v18_powerpc, - dwarf_v19_powerpc, - dwarf_v20_powerpc, - dwarf_v21_powerpc, - dwarf_v22_powerpc, - dwarf_v23_powerpc, - dwarf_v24_powerpc, - dwarf_v25_powerpc, - dwarf_v26_powerpc, - dwarf_v27_powerpc, - dwarf_v28_powerpc, - dwarf_v29_powerpc, - dwarf_v30_powerpc, - dwarf_v31_powerpc, +// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & +// eRegisterKindDWARF) +enum { + dwarf_r0_powerpc = 0, + dwarf_r1_powerpc, + dwarf_r2_powerpc, + dwarf_r3_powerpc, + dwarf_r4_powerpc, + dwarf_r5_powerpc, + dwarf_r6_powerpc, + dwarf_r7_powerpc, + dwarf_r8_powerpc, + dwarf_r9_powerpc, + dwarf_r10_powerpc, + dwarf_r11_powerpc, + dwarf_r12_powerpc, + dwarf_r13_powerpc, + dwarf_r14_powerpc, + dwarf_r15_powerpc, + dwarf_r16_powerpc, + dwarf_r17_powerpc, + dwarf_r18_powerpc, + dwarf_r19_powerpc, + dwarf_r20_powerpc, + dwarf_r21_powerpc, + dwarf_r22_powerpc, + dwarf_r23_powerpc, + dwarf_r24_powerpc, + dwarf_r25_powerpc, + dwarf_r26_powerpc, + dwarf_r27_powerpc, + dwarf_r28_powerpc, + dwarf_r29_powerpc, + dwarf_r30_powerpc, + dwarf_r31_powerpc, + dwarf_f0_powerpc, + dwarf_f1_powerpc, + dwarf_f2_powerpc, + dwarf_f3_powerpc, + dwarf_f4_powerpc, + dwarf_f5_powerpc, + dwarf_f6_powerpc, + dwarf_f7_powerpc, + dwarf_f8_powerpc, + dwarf_f9_powerpc, + dwarf_f10_powerpc, + dwarf_f11_powerpc, + dwarf_f12_powerpc, + dwarf_f13_powerpc, + dwarf_f14_powerpc, + dwarf_f15_powerpc, + dwarf_f16_powerpc, + dwarf_f17_powerpc, + dwarf_f18_powerpc, + dwarf_f19_powerpc, + dwarf_f20_powerpc, + dwarf_f21_powerpc, + dwarf_f22_powerpc, + dwarf_f23_powerpc, + dwarf_f24_powerpc, + dwarf_f25_powerpc, + dwarf_f26_powerpc, + dwarf_f27_powerpc, + dwarf_f28_powerpc, + dwarf_f29_powerpc, + dwarf_f30_powerpc, + dwarf_f31_powerpc, + dwarf_cr_powerpc, + dwarf_fpscr_powerpc, + dwarf_msr_powerpc, + dwarf_vscr_powerpc, + dwarf_xer_powerpc = 101, + dwarf_lr_powerpc = 108, + dwarf_ctr_powerpc, + dwarf_pc_powerpc, + dwarf_vrsave_powerpc = 356, + dwarf_v0_powerpc = 1124, + dwarf_v1_powerpc, + dwarf_v2_powerpc, + dwarf_v3_powerpc, + dwarf_v4_powerpc, + dwarf_v5_powerpc, + dwarf_v6_powerpc, + dwarf_v7_powerpc, + dwarf_v8_powerpc, + dwarf_v9_powerpc, + dwarf_v10_powerpc, + dwarf_v11_powerpc, + dwarf_v12_powerpc, + dwarf_v13_powerpc, + dwarf_v14_powerpc, + dwarf_v15_powerpc, + dwarf_v16_powerpc, + dwarf_v17_powerpc, + dwarf_v18_powerpc, + dwarf_v19_powerpc, + dwarf_v20_powerpc, + dwarf_v21_powerpc, + dwarf_v22_powerpc, + dwarf_v23_powerpc, + dwarf_v24_powerpc, + dwarf_v25_powerpc, + dwarf_v26_powerpc, + dwarf_v27_powerpc, + dwarf_v28_powerpc, + dwarf_v29_powerpc, + dwarf_v30_powerpc, + dwarf_v31_powerpc, }; #endif // liblldb_RegisterContext_powerpc_H_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h index 9777c774440..90803dc1678 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h @@ -14,80 +14,80 @@ // SystemZ ehframe, dwarf regnums //--------------------------------------------------------------------------- -// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF) -enum -{ - // General Purpose Registers - dwarf_r0_s390x = 0, - dwarf_r1_s390x, - dwarf_r2_s390x, - dwarf_r3_s390x, - dwarf_r4_s390x, - dwarf_r5_s390x, - dwarf_r6_s390x, - dwarf_r7_s390x, - dwarf_r8_s390x, - dwarf_r9_s390x, - dwarf_r10_s390x, - dwarf_r11_s390x, - dwarf_r12_s390x, - dwarf_r13_s390x, - dwarf_r14_s390x, - dwarf_r15_s390x, - // Floating Point Registers / Vector Registers 0-15 - dwarf_f0_s390x = 16, - dwarf_f2_s390x, - dwarf_f4_s390x, - dwarf_f6_s390x, - dwarf_f1_s390x, - dwarf_f3_s390x, - dwarf_f5_s390x, - dwarf_f7_s390x, - dwarf_f8_s390x, - dwarf_f10_s390x, - dwarf_f12_s390x, - dwarf_f14_s390x, - dwarf_f9_s390x, - dwarf_f11_s390x, - dwarf_f13_s390x, - dwarf_f15_s390x, - // Access Registers - dwarf_acr0_s390x = 48, - dwarf_acr1_s390x, - dwarf_acr2_s390x, - dwarf_acr3_s390x, - dwarf_acr4_s390x, - dwarf_acr5_s390x, - dwarf_acr6_s390x, - dwarf_acr7_s390x, - dwarf_acr8_s390x, - dwarf_acr9_s390x, - dwarf_acr10_s390x, - dwarf_acr11_s390x, - dwarf_acr12_s390x, - dwarf_acr13_s390x, - dwarf_acr14_s390x, - dwarf_acr15_s390x, - // Program Status Word - dwarf_pswm_s390x = 64, - dwarf_pswa_s390x, - // Vector Registers 16-31 - dwarf_v16_s390x = 68, - dwarf_v18_s390x, - dwarf_v20_s390x, - dwarf_v22_s390x, - dwarf_v17_s390x, - dwarf_v19_s390x, - dwarf_v21_s390x, - dwarf_v23_s390x, - dwarf_v24_s390x, - dwarf_v26_s390x, - dwarf_v28_s390x, - dwarf_v30_s390x, - dwarf_v25_s390x, - dwarf_v27_s390x, - dwarf_v29_s390x, - dwarf_v31_s390x, +// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & +// eRegisterKindDWARF) +enum { + // General Purpose Registers + dwarf_r0_s390x = 0, + dwarf_r1_s390x, + dwarf_r2_s390x, + dwarf_r3_s390x, + dwarf_r4_s390x, + dwarf_r5_s390x, + dwarf_r6_s390x, + dwarf_r7_s390x, + dwarf_r8_s390x, + dwarf_r9_s390x, + dwarf_r10_s390x, + dwarf_r11_s390x, + dwarf_r12_s390x, + dwarf_r13_s390x, + dwarf_r14_s390x, + dwarf_r15_s390x, + // Floating Point Registers / Vector Registers 0-15 + dwarf_f0_s390x = 16, + dwarf_f2_s390x, + dwarf_f4_s390x, + dwarf_f6_s390x, + dwarf_f1_s390x, + dwarf_f3_s390x, + dwarf_f5_s390x, + dwarf_f7_s390x, + dwarf_f8_s390x, + dwarf_f10_s390x, + dwarf_f12_s390x, + dwarf_f14_s390x, + dwarf_f9_s390x, + dwarf_f11_s390x, + dwarf_f13_s390x, + dwarf_f15_s390x, + // Access Registers + dwarf_acr0_s390x = 48, + dwarf_acr1_s390x, + dwarf_acr2_s390x, + dwarf_acr3_s390x, + dwarf_acr4_s390x, + dwarf_acr5_s390x, + dwarf_acr6_s390x, + dwarf_acr7_s390x, + dwarf_acr8_s390x, + dwarf_acr9_s390x, + dwarf_acr10_s390x, + dwarf_acr11_s390x, + dwarf_acr12_s390x, + dwarf_acr13_s390x, + dwarf_acr14_s390x, + dwarf_acr15_s390x, + // Program Status Word + dwarf_pswm_s390x = 64, + dwarf_pswa_s390x, + // Vector Registers 16-31 + dwarf_v16_s390x = 68, + dwarf_v18_s390x, + dwarf_v20_s390x, + dwarf_v22_s390x, + dwarf_v17_s390x, + dwarf_v19_s390x, + dwarf_v21_s390x, + dwarf_v23_s390x, + dwarf_v24_s390x, + dwarf_v26_s390x, + dwarf_v28_s390x, + dwarf_v30_s390x, + dwarf_v25_s390x, + dwarf_v27_s390x, + dwarf_v29_s390x, + dwarf_v31_s390x, }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h index 7b4fb85f7c2..32e2a7fdc57 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h @@ -17,315 +17,307 @@ // i386 ehframe, dwarf regnums //--------------------------------------------------------------------------- -// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems (non-Darwin) +// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems +// (non-Darwin) // -enum -{ - ehframe_eax_i386 = 0, - ehframe_ecx_i386, - ehframe_edx_i386, - ehframe_ebx_i386, +enum { + ehframe_eax_i386 = 0, + ehframe_ecx_i386, + ehframe_edx_i386, + ehframe_ebx_i386, - // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus dwarf's reg numbering). - // To be specific: - // i386+darwin eh_frame: 4 is ebp, 5 is esp - // i386+everyone else eh_frame: 4 is esp, 5 is ebp - // i386 dwarf: 4 is esp, 5 is ebp - // lldb will get the darwin-specific eh_frame reg numberings from debugserver, or the ABI, so we - // only encode the generally correct 4 == esp, 5 == ebp numbers in this generic header. + // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus + // dwarf's reg numbering). + // To be specific: + // i386+darwin eh_frame: 4 is ebp, 5 is esp + // i386+everyone else eh_frame: 4 is esp, 5 is ebp + // i386 dwarf: 4 is esp, 5 is ebp + // lldb will get the darwin-specific eh_frame reg numberings from debugserver, + // or the ABI, so we + // only encode the generally correct 4 == esp, 5 == ebp numbers in this + // generic header. - ehframe_esp_i386, - ehframe_ebp_i386, - ehframe_esi_i386, - ehframe_edi_i386, - ehframe_eip_i386, - ehframe_eflags_i386, - ehframe_st0_i386 = 12, - ehframe_st1_i386, - ehframe_st2_i386, - ehframe_st3_i386, - ehframe_st4_i386, - ehframe_st5_i386, - ehframe_st6_i386, - ehframe_st7_i386, - ehframe_xmm0_i386 = 21, - ehframe_xmm1_i386, - ehframe_xmm2_i386, - ehframe_xmm3_i386, - ehframe_xmm4_i386, - ehframe_xmm5_i386, - ehframe_xmm6_i386, - ehframe_xmm7_i386, - ehframe_mm0_i386 = 29, - ehframe_mm1_i386, - ehframe_mm2_i386, - ehframe_mm3_i386, - ehframe_mm4_i386, - ehframe_mm5_i386, - ehframe_mm6_i386, - ehframe_mm7_i386, + ehframe_esp_i386, + ehframe_ebp_i386, + ehframe_esi_i386, + ehframe_edi_i386, + ehframe_eip_i386, + ehframe_eflags_i386, + ehframe_st0_i386 = 12, + ehframe_st1_i386, + ehframe_st2_i386, + ehframe_st3_i386, + ehframe_st4_i386, + ehframe_st5_i386, + ehframe_st6_i386, + ehframe_st7_i386, + ehframe_xmm0_i386 = 21, + ehframe_xmm1_i386, + ehframe_xmm2_i386, + ehframe_xmm3_i386, + ehframe_xmm4_i386, + ehframe_xmm5_i386, + ehframe_xmm6_i386, + ehframe_xmm7_i386, + ehframe_mm0_i386 = 29, + ehframe_mm1_i386, + ehframe_mm2_i386, + ehframe_mm3_i386, + ehframe_mm4_i386, + ehframe_mm5_i386, + ehframe_mm6_i386, + ehframe_mm7_i386, }; // DWARF register numbers (eRegisterKindDWARF) // Intel's x86 or IA-32 -enum -{ - // General Purpose Registers. - dwarf_eax_i386 = 0, - dwarf_ecx_i386, - dwarf_edx_i386, - dwarf_ebx_i386, - dwarf_esp_i386, - dwarf_ebp_i386, - dwarf_esi_i386, - dwarf_edi_i386, - dwarf_eip_i386, - dwarf_eflags_i386, - // Floating Point Registers - dwarf_st0_i386 = 11, - dwarf_st1_i386, - dwarf_st2_i386, - dwarf_st3_i386, - dwarf_st4_i386, - dwarf_st5_i386, - dwarf_st6_i386, - dwarf_st7_i386, - // SSE Registers - dwarf_xmm0_i386 = 21, - dwarf_xmm1_i386, - dwarf_xmm2_i386, - dwarf_xmm3_i386, - dwarf_xmm4_i386, - dwarf_xmm5_i386, - dwarf_xmm6_i386, - dwarf_xmm7_i386, - // MMX Registers - dwarf_mm0_i386 = 29, - dwarf_mm1_i386, - dwarf_mm2_i386, - dwarf_mm3_i386, - dwarf_mm4_i386, - dwarf_mm5_i386, - dwarf_mm6_i386, - dwarf_mm7_i386, - dwarf_fctrl_i386 = 37, // x87 control word - dwarf_fstat_i386 = 38, // x87 status word - dwarf_mxcsr_i386 = 39, - dwarf_es_i386 = 40, - dwarf_cs_i386 = 41, - dwarf_ss_i386 = 42, - dwarf_ds_i386 = 43, - dwarf_fs_i386 = 44, - dwarf_gs_i386 = 45 +enum { + // General Purpose Registers. + dwarf_eax_i386 = 0, + dwarf_ecx_i386, + dwarf_edx_i386, + dwarf_ebx_i386, + dwarf_esp_i386, + dwarf_ebp_i386, + dwarf_esi_i386, + dwarf_edi_i386, + dwarf_eip_i386, + dwarf_eflags_i386, + // Floating Point Registers + dwarf_st0_i386 = 11, + dwarf_st1_i386, + dwarf_st2_i386, + dwarf_st3_i386, + dwarf_st4_i386, + dwarf_st5_i386, + dwarf_st6_i386, + dwarf_st7_i386, + // SSE Registers + dwarf_xmm0_i386 = 21, + dwarf_xmm1_i386, + dwarf_xmm2_i386, + dwarf_xmm3_i386, + dwarf_xmm4_i386, + dwarf_xmm5_i386, + dwarf_xmm6_i386, + dwarf_xmm7_i386, + // MMX Registers + dwarf_mm0_i386 = 29, + dwarf_mm1_i386, + dwarf_mm2_i386, + dwarf_mm3_i386, + dwarf_mm4_i386, + dwarf_mm5_i386, + dwarf_mm6_i386, + dwarf_mm7_i386, + dwarf_fctrl_i386 = 37, // x87 control word + dwarf_fstat_i386 = 38, // x87 status word + dwarf_mxcsr_i386 = 39, + dwarf_es_i386 = 40, + dwarf_cs_i386 = 41, + dwarf_ss_i386 = 42, + dwarf_ds_i386 = 43, + dwarf_fs_i386 = 44, + dwarf_gs_i386 = 45 - // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and - // then differentiate based on size of the register. + // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and + // then differentiate based on size of the register. }; //--------------------------------------------------------------------------- // AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums //--------------------------------------------------------------------------- -// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF) +// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & +// eRegisterKindDWARF) // This is the spec I used (as opposed to x86-64-abi-0.99.pdf): // http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf -enum -{ - // GP Registers - dwarf_rax_x86_64 = 0, - dwarf_rdx_x86_64, - dwarf_rcx_x86_64, - dwarf_rbx_x86_64, - dwarf_rsi_x86_64, - dwarf_rdi_x86_64, - dwarf_rbp_x86_64, - dwarf_rsp_x86_64, - // Extended GP Registers - dwarf_r8_x86_64 = 8, - dwarf_r9_x86_64, - dwarf_r10_x86_64, - dwarf_r11_x86_64, - dwarf_r12_x86_64, - dwarf_r13_x86_64, - dwarf_r14_x86_64, - dwarf_r15_x86_64, - // Return Address (RA) mapped to RIP - dwarf_rip_x86_64 = 16, - // SSE Vector Registers - dwarf_xmm0_x86_64 = 17, - dwarf_xmm1_x86_64, - dwarf_xmm2_x86_64, - dwarf_xmm3_x86_64, - dwarf_xmm4_x86_64, - dwarf_xmm5_x86_64, - dwarf_xmm6_x86_64, - dwarf_xmm7_x86_64, - dwarf_xmm8_x86_64, - dwarf_xmm9_x86_64, - dwarf_xmm10_x86_64, - dwarf_xmm11_x86_64, - dwarf_xmm12_x86_64, - dwarf_xmm13_x86_64, - dwarf_xmm14_x86_64, - dwarf_xmm15_x86_64, - // Floating Point Registers - dwarf_st0_x86_64 = 33, - dwarf_st1_x86_64, - dwarf_st2_x86_64, - dwarf_st3_x86_64, - dwarf_st4_x86_64, - dwarf_st5_x86_64, - dwarf_st6_x86_64, - dwarf_st7_x86_64, - // MMX Registers - dwarf_mm0_x86_64 = 41, - dwarf_mm1_x86_64, - dwarf_mm2_x86_64, - dwarf_mm3_x86_64, - dwarf_mm4_x86_64, - dwarf_mm5_x86_64, - dwarf_mm6_x86_64, - dwarf_mm7_x86_64, - // Control and Status Flags Register - dwarf_rflags_x86_64 = 49, - // selector registers - dwarf_es_x86_64 = 50, - dwarf_cs_x86_64, - dwarf_ss_x86_64, - dwarf_ds_x86_64, - dwarf_fs_x86_64, - dwarf_gs_x86_64, - // Floating point control registers - dwarf_mxcsr_x86_64 = 64, // Media Control and Status - dwarf_fctrl_x86_64, // x87 control word - dwarf_fstat_x86_64, // x87 status word - // Upper Vector Registers - dwarf_ymm0h_x86_64 = 67, - dwarf_ymm1h_x86_64, - dwarf_ymm2h_x86_64, - dwarf_ymm3h_x86_64, - dwarf_ymm4h_x86_64, - dwarf_ymm5h_x86_64, - dwarf_ymm6h_x86_64, - dwarf_ymm7h_x86_64, - dwarf_ymm8h_x86_64, - dwarf_ymm9h_x86_64, - dwarf_ymm10h_x86_64, - dwarf_ymm11h_x86_64, - dwarf_ymm12h_x86_64, - dwarf_ymm13h_x86_64, - dwarf_ymm14h_x86_64, - dwarf_ymm15h_x86_64, - // AVX2 Vector Mask Registers - // dwarf_k0_x86_64 = 118, - // dwarf_k1_x86_64, - // dwarf_k2_x86_64, - // dwarf_k3_x86_64, - // dwarf_k4_x86_64, - // dwarf_k5_x86_64, - // dwarf_k6_x86_64, - // dwarf_k7_x86_64, +enum { + // GP Registers + dwarf_rax_x86_64 = 0, + dwarf_rdx_x86_64, + dwarf_rcx_x86_64, + dwarf_rbx_x86_64, + dwarf_rsi_x86_64, + dwarf_rdi_x86_64, + dwarf_rbp_x86_64, + dwarf_rsp_x86_64, + // Extended GP Registers + dwarf_r8_x86_64 = 8, + dwarf_r9_x86_64, + dwarf_r10_x86_64, + dwarf_r11_x86_64, + dwarf_r12_x86_64, + dwarf_r13_x86_64, + dwarf_r14_x86_64, + dwarf_r15_x86_64, + // Return Address (RA) mapped to RIP + dwarf_rip_x86_64 = 16, + // SSE Vector Registers + dwarf_xmm0_x86_64 = 17, + dwarf_xmm1_x86_64, + dwarf_xmm2_x86_64, + dwarf_xmm3_x86_64, + dwarf_xmm4_x86_64, + dwarf_xmm5_x86_64, + dwarf_xmm6_x86_64, + dwarf_xmm7_x86_64, + dwarf_xmm8_x86_64, + dwarf_xmm9_x86_64, + dwarf_xmm10_x86_64, + dwarf_xmm11_x86_64, + dwarf_xmm12_x86_64, + dwarf_xmm13_x86_64, + dwarf_xmm14_x86_64, + dwarf_xmm15_x86_64, + // Floating Point Registers + dwarf_st0_x86_64 = 33, + dwarf_st1_x86_64, + dwarf_st2_x86_64, + dwarf_st3_x86_64, + dwarf_st4_x86_64, + dwarf_st5_x86_64, + dwarf_st6_x86_64, + dwarf_st7_x86_64, + // MMX Registers + dwarf_mm0_x86_64 = 41, + dwarf_mm1_x86_64, + dwarf_mm2_x86_64, + dwarf_mm3_x86_64, + dwarf_mm4_x86_64, + dwarf_mm5_x86_64, + dwarf_mm6_x86_64, + dwarf_mm7_x86_64, + // Control and Status Flags Register + dwarf_rflags_x86_64 = 49, + // selector registers + dwarf_es_x86_64 = 50, + dwarf_cs_x86_64, + dwarf_ss_x86_64, + dwarf_ds_x86_64, + dwarf_fs_x86_64, + dwarf_gs_x86_64, + // Floating point control registers + dwarf_mxcsr_x86_64 = 64, // Media Control and Status + dwarf_fctrl_x86_64, // x87 control word + dwarf_fstat_x86_64, // x87 status word + // Upper Vector Registers + dwarf_ymm0h_x86_64 = 67, + dwarf_ymm1h_x86_64, + dwarf_ymm2h_x86_64, + dwarf_ymm3h_x86_64, + dwarf_ymm4h_x86_64, + dwarf_ymm5h_x86_64, + dwarf_ymm6h_x86_64, + dwarf_ymm7h_x86_64, + dwarf_ymm8h_x86_64, + dwarf_ymm9h_x86_64, + dwarf_ymm10h_x86_64, + dwarf_ymm11h_x86_64, + dwarf_ymm12h_x86_64, + dwarf_ymm13h_x86_64, + dwarf_ymm14h_x86_64, + dwarf_ymm15h_x86_64, + // AVX2 Vector Mask Registers + // dwarf_k0_x86_64 = 118, + // dwarf_k1_x86_64, + // dwarf_k2_x86_64, + // dwarf_k3_x86_64, + // dwarf_k4_x86_64, + // dwarf_k5_x86_64, + // dwarf_k6_x86_64, + // dwarf_k7_x86_64, }; //--------------------------------------------------------------------------- // Generic floating-point registers //--------------------------------------------------------------------------- -struct MMSReg -{ - uint8_t bytes[10]; - uint8_t pad[6]; +struct MMSReg { + uint8_t bytes[10]; + uint8_t pad[6]; }; -struct XMMReg -{ - uint8_t bytes[16]; // 128-bits for each XMM register +struct XMMReg { + uint8_t bytes[16]; // 128-bits for each XMM register }; // i387_fxsave_struct -struct FXSAVE -{ - uint16_t fctrl; // FPU Control Word (fcw) - uint16_t fstat; // FPU Status Word (fsw) - uint8_t ftag; // FPU Tag Word (ftw) - uint8_t reserved_1; // Reserved - uint16_t fop; // Last Instruction Opcode (fop) - union - { - struct - { - uint64_t fip; // Instruction Pointer - uint64_t fdp; // Data Pointer - } x86_64; - struct - { - uint32_t fioff; // FPU IP Offset (fip) - uint32_t fiseg; // FPU IP Selector (fcs) - uint32_t fooff; // FPU Operand Pointer Offset (foo) - uint32_t foseg; // FPU Operand Pointer Selector (fos) - } i386_;// Added _ in the end to avoid error with gcc defining i386 in some cases - } ptr; - uint32_t mxcsr; // MXCSR Register State - uint32_t mxcsrmask; // MXCSR Mask - MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes - XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes - uint32_t padding[24]; +struct FXSAVE { + uint16_t fctrl; // FPU Control Word (fcw) + uint16_t fstat; // FPU Status Word (fsw) + uint8_t ftag; // FPU Tag Word (ftw) + uint8_t reserved_1; // Reserved + uint16_t fop; // Last Instruction Opcode (fop) + union { + struct { + uint64_t fip; // Instruction Pointer + uint64_t fdp; // Data Pointer + } x86_64; + struct { + uint32_t fioff; // FPU IP Offset (fip) + uint32_t fiseg; // FPU IP Selector (fcs) + uint32_t fooff; // FPU Operand Pointer Offset (foo) + uint32_t foseg; // FPU Operand Pointer Selector (fos) + } i386_; // Added _ in the end to avoid error with gcc defining i386 in some + // cases + } ptr; + uint32_t mxcsr; // MXCSR Register State + uint32_t mxcsrmask; // MXCSR Mask + MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes + XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes + uint32_t padding[24]; }; //--------------------------------------------------------------------------- // Extended floating-point registers //--------------------------------------------------------------------------- -struct YMMHReg -{ - uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register +struct YMMHReg { + uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register }; -struct YMMReg -{ - uint8_t bytes[32]; // 16 * 16 bits for each YMM register +struct YMMReg { + uint8_t bytes[32]; // 16 * 16 bits for each YMM register }; -struct YMM -{ - YMMReg ymm[16]; // assembled from ymmh and xmm registers +struct YMM { + YMMReg ymm[16]; // assembled from ymmh and xmm registers }; -struct XSAVE_HDR -{ - uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor - uint64_t reserved1[2]; - uint64_t reserved2[5]; +struct XSAVE_HDR { + uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states + // supported by the processor + uint64_t reserved1[2]; + uint64_t reserved2[5]; } __attribute__((packed)); -// x86 extensions to FXSAVE (i.e. for AVX processors) -struct XSAVE -{ - FXSAVE i387; // floating point registers typical in i387_fxsave_struct - XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable - YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE) - // Slot any extensions to the register file here -} __attribute__((packed, aligned (64))); +// x86 extensions to FXSAVE (i.e. for AVX processors) +struct XSAVE { + FXSAVE i387; // floating point registers typical in i387_fxsave_struct + XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the + // following extensions are usable + YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes + // are in FXSAVE.xmm for compatibility with SSE) + // Slot any extensions to the register file here +} __attribute__((packed, aligned(64))); // Floating-point registers -struct FPR -{ - // Thread state for the floating-point unit of the processor read by ptrace. - union XSTATE - { - FXSAVE fxsave; // Generic floating-point registers. - XSAVE xsave; // x86 extended processor state. - } xstate; +struct FPR { + // Thread state for the floating-point unit of the processor read by ptrace. + union XSTATE { + FXSAVE fxsave; // Generic floating-point registers. + XSAVE xsave; // x86 extended processor state. + } xstate; }; //--------------------------------------------------------------------------- // ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure //--------------------------------------------------------------------------- -struct IOVEC -{ - void *iov_base; // pointer to XSAVE - size_t iov_len; // sizeof(XSAVE) +struct IOVEC { + void *iov_base; // pointer to XSAVE + size_t iov_len; // sizeof(XSAVE) }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h index 801885d5f4c..12db366d7a5 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -14,69 +14,60 @@ #include "lldb/Core/ArchSpec.h" -namespace lldb_private -{ +namespace lldb_private { - ///------------------------------------------------------------------------------ - /// @class RegisterInfoInterface - /// - /// @brief RegisterInfo interface to patch RegisterInfo structure for archs. - ///------------------------------------------------------------------------------ - class RegisterInfoInterface - { - public: - RegisterInfoInterface(const lldb_private::ArchSpec& target_arch) : m_target_arch(target_arch) {} - virtual ~RegisterInfoInterface () {} +///------------------------------------------------------------------------------ +/// @class RegisterInfoInterface +/// +/// @brief RegisterInfo interface to patch RegisterInfo structure for archs. +///------------------------------------------------------------------------------ +class RegisterInfoInterface { +public: + RegisterInfoInterface(const lldb_private::ArchSpec &target_arch) + : m_target_arch(target_arch) {} + virtual ~RegisterInfoInterface() {} - virtual size_t - GetGPRSize () const = 0; + virtual size_t GetGPRSize() const = 0; - virtual const lldb_private::RegisterInfo * - GetRegisterInfo () const = 0; + virtual const lldb_private::RegisterInfo *GetRegisterInfo() const = 0; - // Returns the number of registers including the user registers and the - // lldb internal registers also - virtual uint32_t - GetRegisterCount () const = 0; + // Returns the number of registers including the user registers and the + // lldb internal registers also + virtual uint32_t GetRegisterCount() const = 0; - // Returns the number of the user registers (excluding the registers - // kept for lldb internal use only). Subclasses should override it if - // they belongs to an architecture with lldb internal registers. - virtual uint32_t - GetUserRegisterCount () const - { - return GetRegisterCount(); - } + // Returns the number of the user registers (excluding the registers + // kept for lldb internal use only). Subclasses should override it if + // they belongs to an architecture with lldb internal registers. + virtual uint32_t GetUserRegisterCount() const { return GetRegisterCount(); } - const lldb_private::ArchSpec& - GetTargetArchitecture() const - { return m_target_arch; } + const lldb_private::ArchSpec &GetTargetArchitecture() const { + return m_target_arch; + } - virtual const lldb_private::RegisterInfo * - GetDynamicRegisterInfo(const char *reg_name) const - { - const std::vector <lldb_private::RegisterInfo> * d_register_infos = GetDynamicRegisterInfoP(); - if(d_register_infos != nullptr) - { - std::vector <lldb_private::RegisterInfo> ::const_iterator pos = d_register_infos->begin(); - for(; pos < d_register_infos->end() ; pos++) - { - if(::strcmp(reg_name, pos->name) == 0) - return(d_register_infos->data() + (pos - d_register_infos->begin()) ); - } - } - return nullptr; - } + virtual const lldb_private::RegisterInfo * + GetDynamicRegisterInfo(const char *reg_name) const { + const std::vector<lldb_private::RegisterInfo> *d_register_infos = + GetDynamicRegisterInfoP(); + if (d_register_infos != nullptr) { + std::vector<lldb_private::RegisterInfo>::const_iterator pos = + d_register_infos->begin(); + for (; pos < d_register_infos->end(); pos++) { + if (::strcmp(reg_name, pos->name) == 0) + return (d_register_infos->data() + (pos - d_register_infos->begin())); + } + } + return nullptr; + } - virtual const std::vector<lldb_private::RegisterInfo> * - GetDynamicRegisterInfoP() const - { return nullptr; } - - public: - // FIXME make private. - lldb_private::ArchSpec m_target_arch; - }; + virtual const std::vector<lldb_private::RegisterInfo> * + GetDynamicRegisterInfoP() const { + return nullptr; + } +public: + // FIXME make private. + lldb_private::ArchSpec m_target_arch; +}; } #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h index e3c7473bf71..74d3226c8a5 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h @@ -15,12 +15,12 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" -#include "Utility/ARM_ehframe_Registers.h" #include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" using namespace lldb; using namespace lldb_private; @@ -45,461 +45,1580 @@ using namespace lldb_private; #error DEFINE_DBG must be defined before including this header file #endif -enum -{ - gpr_r0 = 0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, gpr_sp = gpr_r13, - gpr_r14, gpr_lr = gpr_r14, - gpr_r15, gpr_pc = gpr_r15, - gpr_cpsr, - - fpu_s0, - fpu_s1, - fpu_s2, - fpu_s3, - fpu_s4, - fpu_s5, - fpu_s6, - fpu_s7, - fpu_s8, - fpu_s9, - fpu_s10, - fpu_s11, - fpu_s12, - fpu_s13, - fpu_s14, - fpu_s15, - fpu_s16, - fpu_s17, - fpu_s18, - fpu_s19, - fpu_s20, - fpu_s21, - fpu_s22, - fpu_s23, - fpu_s24, - fpu_s25, - fpu_s26, - fpu_s27, - fpu_s28, - fpu_s29, - fpu_s30, - fpu_s31, - fpu_fpscr, - - fpu_d0, - fpu_d1, - fpu_d2, - fpu_d3, - fpu_d4, - fpu_d5, - fpu_d6, - fpu_d7, - fpu_d8, - fpu_d9, - fpu_d10, - fpu_d11, - fpu_d12, - fpu_d13, - fpu_d14, - fpu_d15, - fpu_d16, - fpu_d17, - fpu_d18, - fpu_d19, - fpu_d20, - fpu_d21, - fpu_d22, - fpu_d23, - fpu_d24, - fpu_d25, - fpu_d26, - fpu_d27, - fpu_d28, - fpu_d29, - fpu_d30, - fpu_d31, - - fpu_q0, - fpu_q1, - fpu_q2, - fpu_q3, - fpu_q4, - fpu_q5, - fpu_q6, - fpu_q7, - fpu_q8, - fpu_q9, - fpu_q10, - fpu_q11, - fpu_q12, - fpu_q13, - fpu_q14, - fpu_q15, - - exc_exception, - exc_fsr, - exc_far, - - dbg_bvr0, - dbg_bvr1, - dbg_bvr2, - dbg_bvr3, - dbg_bvr4, - dbg_bvr5, - dbg_bvr6, - dbg_bvr7, - dbg_bvr8, - dbg_bvr9, - dbg_bvr10, - dbg_bvr11, - dbg_bvr12, - dbg_bvr13, - dbg_bvr14, - dbg_bvr15, - - dbg_bcr0, - dbg_bcr1, - dbg_bcr2, - dbg_bcr3, - dbg_bcr4, - dbg_bcr5, - dbg_bcr6, - dbg_bcr7, - dbg_bcr8, - dbg_bcr9, - dbg_bcr10, - dbg_bcr11, - dbg_bcr12, - dbg_bcr13, - dbg_bcr14, - dbg_bcr15, - - dbg_wvr0, - dbg_wvr1, - dbg_wvr2, - dbg_wvr3, - dbg_wvr4, - dbg_wvr5, - dbg_wvr6, - dbg_wvr7, - dbg_wvr8, - dbg_wvr9, - dbg_wvr10, - dbg_wvr11, - dbg_wvr12, - dbg_wvr13, - dbg_wvr14, - dbg_wvr15, - - dbg_wcr0, - dbg_wcr1, - dbg_wcr2, - dbg_wcr3, - dbg_wcr4, - dbg_wcr5, - dbg_wcr6, - dbg_wcr7, - dbg_wcr8, - dbg_wcr9, - dbg_wcr10, - dbg_wcr11, - dbg_wcr12, - dbg_wcr13, - dbg_wcr14, - dbg_wcr15, - - k_num_registers +enum { + gpr_r0 = 0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_sp = gpr_r13, + gpr_r14, + gpr_lr = gpr_r14, + gpr_r15, + gpr_pc = gpr_r15, + gpr_cpsr, + + fpu_s0, + fpu_s1, + fpu_s2, + fpu_s3, + fpu_s4, + fpu_s5, + fpu_s6, + fpu_s7, + fpu_s8, + fpu_s9, + fpu_s10, + fpu_s11, + fpu_s12, + fpu_s13, + fpu_s14, + fpu_s15, + fpu_s16, + fpu_s17, + fpu_s18, + fpu_s19, + fpu_s20, + fpu_s21, + fpu_s22, + fpu_s23, + fpu_s24, + fpu_s25, + fpu_s26, + fpu_s27, + fpu_s28, + fpu_s29, + fpu_s30, + fpu_s31, + fpu_fpscr, + + fpu_d0, + fpu_d1, + fpu_d2, + fpu_d3, + fpu_d4, + fpu_d5, + fpu_d6, + fpu_d7, + fpu_d8, + fpu_d9, + fpu_d10, + fpu_d11, + fpu_d12, + fpu_d13, + fpu_d14, + fpu_d15, + fpu_d16, + fpu_d17, + fpu_d18, + fpu_d19, + fpu_d20, + fpu_d21, + fpu_d22, + fpu_d23, + fpu_d24, + fpu_d25, + fpu_d26, + fpu_d27, + fpu_d28, + fpu_d29, + fpu_d30, + fpu_d31, + + fpu_q0, + fpu_q1, + fpu_q2, + fpu_q3, + fpu_q4, + fpu_q5, + fpu_q6, + fpu_q7, + fpu_q8, + fpu_q9, + fpu_q10, + fpu_q11, + fpu_q12, + fpu_q13, + fpu_q14, + fpu_q15, + + exc_exception, + exc_fsr, + exc_far, + + dbg_bvr0, + dbg_bvr1, + dbg_bvr2, + dbg_bvr3, + dbg_bvr4, + dbg_bvr5, + dbg_bvr6, + dbg_bvr7, + dbg_bvr8, + dbg_bvr9, + dbg_bvr10, + dbg_bvr11, + dbg_bvr12, + dbg_bvr13, + dbg_bvr14, + dbg_bvr15, + + dbg_bcr0, + dbg_bcr1, + dbg_bcr2, + dbg_bcr3, + dbg_bcr4, + dbg_bcr5, + dbg_bcr6, + dbg_bcr7, + dbg_bcr8, + dbg_bcr9, + dbg_bcr10, + dbg_bcr11, + dbg_bcr12, + dbg_bcr13, + dbg_bcr14, + dbg_bcr15, + + dbg_wvr0, + dbg_wvr1, + dbg_wvr2, + dbg_wvr3, + dbg_wvr4, + dbg_wvr5, + dbg_wvr6, + dbg_wvr7, + dbg_wvr8, + dbg_wvr9, + dbg_wvr10, + dbg_wvr11, + dbg_wvr12, + dbg_wvr13, + dbg_wvr14, + dbg_wvr15, + + dbg_wcr0, + dbg_wcr1, + dbg_wcr2, + dbg_wcr3, + dbg_wcr4, + dbg_wcr5, + dbg_wcr6, + dbg_wcr7, + dbg_wcr8, + dbg_wcr9, + dbg_wcr10, + dbg_wcr11, + dbg_wcr12, + dbg_wcr13, + dbg_wcr14, + dbg_wcr15, + + k_num_registers }; -static uint32_t g_s0_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_s1_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_s2_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_s3_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_s4_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_s5_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_s6_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_s7_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_s8_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_s9_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_s10_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_s11_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_s12_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_s13_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_s14_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_s15_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_s16_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_s17_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_s18_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_s19_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_s20_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_s21_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_s22_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_s23_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_s24_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_s25_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_s26_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_s27_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_s28_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM }; -static uint32_t g_s29_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM }; -static uint32_t g_s30_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM }; -static uint32_t g_s31_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM }; - -static uint32_t g_d0_contains[] = { fpu_s0, fpu_s1, LLDB_INVALID_REGNUM }; -static uint32_t g_d1_contains[] = { fpu_s2, fpu_s3, LLDB_INVALID_REGNUM }; -static uint32_t g_d2_contains[] = { fpu_s4, fpu_s5, LLDB_INVALID_REGNUM }; -static uint32_t g_d3_contains[] = { fpu_s6, fpu_s7, LLDB_INVALID_REGNUM }; -static uint32_t g_d4_contains[] = { fpu_s8, fpu_s9, LLDB_INVALID_REGNUM }; -static uint32_t g_d5_contains[] = { fpu_s10, fpu_s11, LLDB_INVALID_REGNUM }; -static uint32_t g_d6_contains[] = { fpu_s12, fpu_s13, LLDB_INVALID_REGNUM }; -static uint32_t g_d7_contains[] = { fpu_s14, fpu_s15, LLDB_INVALID_REGNUM }; -static uint32_t g_d8_contains[] = { fpu_s16, fpu_s17, LLDB_INVALID_REGNUM }; -static uint32_t g_d9_contains[] = { fpu_s18, fpu_s19, LLDB_INVALID_REGNUM }; -static uint32_t g_d10_contains[] = { fpu_s20, fpu_s21, LLDB_INVALID_REGNUM }; -static uint32_t g_d11_contains[] = { fpu_s22, fpu_s23, LLDB_INVALID_REGNUM }; -static uint32_t g_d12_contains[] = { fpu_s24, fpu_s25, LLDB_INVALID_REGNUM }; -static uint32_t g_d13_contains[] = { fpu_s26, fpu_s27, LLDB_INVALID_REGNUM }; -static uint32_t g_d14_contains[] = { fpu_s28, fpu_s29, LLDB_INVALID_REGNUM }; -static uint32_t g_d15_contains[] = { fpu_s30, fpu_s31, LLDB_INVALID_REGNUM }; - -static uint32_t g_d0_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_d1_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM }; -static uint32_t g_d2_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_d3_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM }; -static uint32_t g_d4_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_d5_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM }; -static uint32_t g_d6_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_d7_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM }; -static uint32_t g_d8_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_d9_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM }; -static uint32_t g_d10_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_d11_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM }; -static uint32_t g_d12_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_d13_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM }; -static uint32_t g_d14_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM }; -static uint32_t g_d15_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM }; -static uint32_t g_d16_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM }; -static uint32_t g_d17_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM }; -static uint32_t g_d18_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM }; -static uint32_t g_d19_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM }; -static uint32_t g_d20_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM }; -static uint32_t g_d21_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM }; -static uint32_t g_d22_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM }; -static uint32_t g_d23_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM }; -static uint32_t g_d24_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM }; -static uint32_t g_d25_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM }; -static uint32_t g_d26_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM }; -static uint32_t g_d27_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM }; -static uint32_t g_d28_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM }; -static uint32_t g_d29_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM }; -static uint32_t g_d30_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM }; -static uint32_t g_d31_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM }; - -static uint32_t g_q0_contains[] = { fpu_d0, fpu_d1, fpu_s0, fpu_s1, fpu_s2, fpu_s3, LLDB_INVALID_REGNUM }; -static uint32_t g_q1_contains[] = { fpu_d2, fpu_d3, fpu_s4, fpu_s5, fpu_s6, fpu_s7, LLDB_INVALID_REGNUM }; -static uint32_t g_q2_contains[] = { fpu_d4, fpu_d5, fpu_s8, fpu_s9, fpu_s10, fpu_s11, LLDB_INVALID_REGNUM }; -static uint32_t g_q3_contains[] = { fpu_d6, fpu_d7, fpu_s12, fpu_s13, fpu_s14, fpu_s15, LLDB_INVALID_REGNUM }; -static uint32_t g_q4_contains[] = { fpu_d8, fpu_d9, fpu_s16, fpu_s17, fpu_s18, fpu_s19, LLDB_INVALID_REGNUM }; -static uint32_t g_q5_contains[] = { fpu_d10, fpu_d11, fpu_s20, fpu_s21, fpu_s22, fpu_s23, LLDB_INVALID_REGNUM }; -static uint32_t g_q6_contains[] = { fpu_d12, fpu_d13, fpu_s24, fpu_s25, fpu_s26, fpu_s27, LLDB_INVALID_REGNUM }; -static uint32_t g_q7_contains[] = { fpu_d14, fpu_d15, fpu_s28, fpu_s29, fpu_s30, fpu_s31, LLDB_INVALID_REGNUM }; -static uint32_t g_q8_contains[] = { fpu_d16, fpu_d17, LLDB_INVALID_REGNUM }; -static uint32_t g_q9_contains[] = { fpu_d18, fpu_d19, LLDB_INVALID_REGNUM }; -static uint32_t g_q10_contains[] = { fpu_d20, fpu_d21, LLDB_INVALID_REGNUM }; -static uint32_t g_q11_contains[] = { fpu_d22, fpu_d23, LLDB_INVALID_REGNUM }; -static uint32_t g_q12_contains[] = { fpu_d24, fpu_d25, LLDB_INVALID_REGNUM }; -static uint32_t g_q13_contains[] = { fpu_d26, fpu_d27, LLDB_INVALID_REGNUM }; -static uint32_t g_q14_contains[] = { fpu_d28, fpu_d29, LLDB_INVALID_REGNUM }; -static uint32_t g_q15_contains[] = { fpu_d30, fpu_d31, LLDB_INVALID_REGNUM }; +static uint32_t g_s0_invalidates[] = {fpu_d0, fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_s1_invalidates[] = {fpu_d0, fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_s2_invalidates[] = {fpu_d1, fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_s3_invalidates[] = {fpu_d1, fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_s4_invalidates[] = {fpu_d2, fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_s5_invalidates[] = {fpu_d2, fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_s6_invalidates[] = {fpu_d3, fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_s7_invalidates[] = {fpu_d3, fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_s8_invalidates[] = {fpu_d4, fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_s9_invalidates[] = {fpu_d4, fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_s10_invalidates[] = {fpu_d5, fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_s11_invalidates[] = {fpu_d5, fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_s12_invalidates[] = {fpu_d6, fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_s13_invalidates[] = {fpu_d6, fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_s14_invalidates[] = {fpu_d7, fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_s15_invalidates[] = {fpu_d7, fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_s16_invalidates[] = {fpu_d8, fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_s17_invalidates[] = {fpu_d8, fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_s18_invalidates[] = {fpu_d9, fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_s19_invalidates[] = {fpu_d9, fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_s20_invalidates[] = {fpu_d10, fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_s21_invalidates[] = {fpu_d10, fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_s22_invalidates[] = {fpu_d11, fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_s23_invalidates[] = {fpu_d11, fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_s24_invalidates[] = {fpu_d12, fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_s25_invalidates[] = {fpu_d12, fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_s26_invalidates[] = {fpu_d13, fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_s27_invalidates[] = {fpu_d13, fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_s28_invalidates[] = {fpu_d14, fpu_q7, LLDB_INVALID_REGNUM}; +static uint32_t g_s29_invalidates[] = {fpu_d14, fpu_q7, LLDB_INVALID_REGNUM}; +static uint32_t g_s30_invalidates[] = {fpu_d15, fpu_q7, LLDB_INVALID_REGNUM}; +static uint32_t g_s31_invalidates[] = {fpu_d15, fpu_q7, LLDB_INVALID_REGNUM}; + +static uint32_t g_d0_contains[] = {fpu_s0, fpu_s1, LLDB_INVALID_REGNUM}; +static uint32_t g_d1_contains[] = {fpu_s2, fpu_s3, LLDB_INVALID_REGNUM}; +static uint32_t g_d2_contains[] = {fpu_s4, fpu_s5, LLDB_INVALID_REGNUM}; +static uint32_t g_d3_contains[] = {fpu_s6, fpu_s7, LLDB_INVALID_REGNUM}; +static uint32_t g_d4_contains[] = {fpu_s8, fpu_s9, LLDB_INVALID_REGNUM}; +static uint32_t g_d5_contains[] = {fpu_s10, fpu_s11, LLDB_INVALID_REGNUM}; +static uint32_t g_d6_contains[] = {fpu_s12, fpu_s13, LLDB_INVALID_REGNUM}; +static uint32_t g_d7_contains[] = {fpu_s14, fpu_s15, LLDB_INVALID_REGNUM}; +static uint32_t g_d8_contains[] = {fpu_s16, fpu_s17, LLDB_INVALID_REGNUM}; +static uint32_t g_d9_contains[] = {fpu_s18, fpu_s19, LLDB_INVALID_REGNUM}; +static uint32_t g_d10_contains[] = {fpu_s20, fpu_s21, LLDB_INVALID_REGNUM}; +static uint32_t g_d11_contains[] = {fpu_s22, fpu_s23, LLDB_INVALID_REGNUM}; +static uint32_t g_d12_contains[] = {fpu_s24, fpu_s25, LLDB_INVALID_REGNUM}; +static uint32_t g_d13_contains[] = {fpu_s26, fpu_s27, LLDB_INVALID_REGNUM}; +static uint32_t g_d14_contains[] = {fpu_s28, fpu_s29, LLDB_INVALID_REGNUM}; +static uint32_t g_d15_contains[] = {fpu_s30, fpu_s31, LLDB_INVALID_REGNUM}; + +static uint32_t g_d0_invalidates[] = {fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_d1_invalidates[] = {fpu_q0, LLDB_INVALID_REGNUM}; +static uint32_t g_d2_invalidates[] = {fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_d3_invalidates[] = {fpu_q1, LLDB_INVALID_REGNUM}; +static uint32_t g_d4_invalidates[] = {fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_d5_invalidates[] = {fpu_q2, LLDB_INVALID_REGNUM}; +static uint32_t g_d6_invalidates[] = {fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_d7_invalidates[] = {fpu_q3, LLDB_INVALID_REGNUM}; +static uint32_t g_d8_invalidates[] = {fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_d9_invalidates[] = {fpu_q4, LLDB_INVALID_REGNUM}; +static uint32_t g_d10_invalidates[] = {fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_d11_invalidates[] = {fpu_q5, LLDB_INVALID_REGNUM}; +static uint32_t g_d12_invalidates[] = {fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_d13_invalidates[] = {fpu_q6, LLDB_INVALID_REGNUM}; +static uint32_t g_d14_invalidates[] = {fpu_q7, LLDB_INVALID_REGNUM}; +static uint32_t g_d15_invalidates[] = {fpu_q7, LLDB_INVALID_REGNUM}; +static uint32_t g_d16_invalidates[] = {fpu_q8, LLDB_INVALID_REGNUM}; +static uint32_t g_d17_invalidates[] = {fpu_q8, LLDB_INVALID_REGNUM}; +static uint32_t g_d18_invalidates[] = {fpu_q9, LLDB_INVALID_REGNUM}; +static uint32_t g_d19_invalidates[] = {fpu_q9, LLDB_INVALID_REGNUM}; +static uint32_t g_d20_invalidates[] = {fpu_q10, LLDB_INVALID_REGNUM}; +static uint32_t g_d21_invalidates[] = {fpu_q10, LLDB_INVALID_REGNUM}; +static uint32_t g_d22_invalidates[] = {fpu_q11, LLDB_INVALID_REGNUM}; +static uint32_t g_d23_invalidates[] = {fpu_q11, LLDB_INVALID_REGNUM}; +static uint32_t g_d24_invalidates[] = {fpu_q12, LLDB_INVALID_REGNUM}; +static uint32_t g_d25_invalidates[] = {fpu_q12, LLDB_INVALID_REGNUM}; +static uint32_t g_d26_invalidates[] = {fpu_q13, LLDB_INVALID_REGNUM}; +static uint32_t g_d27_invalidates[] = {fpu_q13, LLDB_INVALID_REGNUM}; +static uint32_t g_d28_invalidates[] = {fpu_q14, LLDB_INVALID_REGNUM}; +static uint32_t g_d29_invalidates[] = {fpu_q14, LLDB_INVALID_REGNUM}; +static uint32_t g_d30_invalidates[] = {fpu_q15, LLDB_INVALID_REGNUM}; +static uint32_t g_d31_invalidates[] = {fpu_q15, LLDB_INVALID_REGNUM}; + +static uint32_t g_q0_contains[] = { + fpu_d0, fpu_d1, fpu_s0, fpu_s1, fpu_s2, fpu_s3, LLDB_INVALID_REGNUM}; +static uint32_t g_q1_contains[] = { + fpu_d2, fpu_d3, fpu_s4, fpu_s5, fpu_s6, fpu_s7, LLDB_INVALID_REGNUM}; +static uint32_t g_q2_contains[] = { + fpu_d4, fpu_d5, fpu_s8, fpu_s9, fpu_s10, fpu_s11, LLDB_INVALID_REGNUM}; +static uint32_t g_q3_contains[] = { + fpu_d6, fpu_d7, fpu_s12, fpu_s13, fpu_s14, fpu_s15, LLDB_INVALID_REGNUM}; +static uint32_t g_q4_contains[] = { + fpu_d8, fpu_d9, fpu_s16, fpu_s17, fpu_s18, fpu_s19, LLDB_INVALID_REGNUM}; +static uint32_t g_q5_contains[] = { + fpu_d10, fpu_d11, fpu_s20, fpu_s21, fpu_s22, fpu_s23, LLDB_INVALID_REGNUM}; +static uint32_t g_q6_contains[] = { + fpu_d12, fpu_d13, fpu_s24, fpu_s25, fpu_s26, fpu_s27, LLDB_INVALID_REGNUM}; +static uint32_t g_q7_contains[] = { + fpu_d14, fpu_d15, fpu_s28, fpu_s29, fpu_s30, fpu_s31, LLDB_INVALID_REGNUM}; +static uint32_t g_q8_contains[] = {fpu_d16, fpu_d17, LLDB_INVALID_REGNUM}; +static uint32_t g_q9_contains[] = {fpu_d18, fpu_d19, LLDB_INVALID_REGNUM}; +static uint32_t g_q10_contains[] = {fpu_d20, fpu_d21, LLDB_INVALID_REGNUM}; +static uint32_t g_q11_contains[] = {fpu_d22, fpu_d23, LLDB_INVALID_REGNUM}; +static uint32_t g_q12_contains[] = {fpu_d24, fpu_d25, LLDB_INVALID_REGNUM}; +static uint32_t g_q13_contains[] = {fpu_d26, fpu_d27, LLDB_INVALID_REGNUM}; +static uint32_t g_q14_contains[] = {fpu_d28, fpu_d29, LLDB_INVALID_REGNUM}; +static uint32_t g_q15_contains[] = {fpu_d30, fpu_d31, LLDB_INVALID_REGNUM}; static RegisterInfo g_register_infos_arm[] = { -// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS -// =========== ======= == ============== ================ ==================== =================== =================== ========================== =================== ============= ============== ================= -{ "r0", nullptr, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_r0 }, nullptr, nullptr, nullptr, 0}, -{ "r1", nullptr, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_r1 }, nullptr, nullptr, nullptr, 0}, -{ "r2", nullptr, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_r2 }, nullptr, nullptr, nullptr, 0}, -{ "r3", nullptr, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_r3 }, nullptr, nullptr, nullptr, 0}, -{ "r4", nullptr, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, nullptr, nullptr, nullptr, 0}, -{ "r5", nullptr, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, nullptr, nullptr, nullptr, 0}, -{ "r6", nullptr, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, nullptr, nullptr, nullptr, 0}, -{ "r7", nullptr, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r7 }, nullptr, nullptr, nullptr, 0}, -{ "r8", nullptr, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, nullptr, nullptr, nullptr, 0}, -{ "r9", nullptr, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, nullptr, nullptr, nullptr, 0}, -{ "r10", nullptr, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, nullptr, nullptr, nullptr, 0}, -{ "r11", nullptr, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r11 }, nullptr, nullptr, nullptr, 0}, -{ "r12", nullptr, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, nullptr, nullptr, nullptr, 0}, -{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr, nullptr, 0}, -{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr, nullptr, 0}, -{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr, nullptr, 0}, -{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr, nullptr, 0}, - -{ "s0", nullptr, 4, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, nullptr, g_s0_invalidates, nullptr, 0}, -{ "s1", nullptr, 4, FPU_OFFSET(1), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, nullptr, g_s1_invalidates, nullptr, 0}, -{ "s2", nullptr, 4, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, nullptr, g_s2_invalidates, nullptr, 0}, -{ "s3", nullptr, 4, FPU_OFFSET(3), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, nullptr, g_s3_invalidates, nullptr, 0}, -{ "s4", nullptr, 4, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, nullptr, g_s4_invalidates, nullptr, 0}, -{ "s5", nullptr, 4, FPU_OFFSET(5), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, nullptr, g_s5_invalidates, nullptr, 0}, -{ "s6", nullptr, 4, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, nullptr, g_s6_invalidates, nullptr, 0}, -{ "s7", nullptr, 4, FPU_OFFSET(7), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, nullptr, g_s7_invalidates, nullptr, 0}, -{ "s8", nullptr, 4, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, nullptr, g_s8_invalidates, nullptr, 0}, -{ "s9", nullptr, 4, FPU_OFFSET(9), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, nullptr, g_s9_invalidates, nullptr, 0}, -{ "s10", nullptr, 4, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, nullptr, g_s10_invalidates, nullptr, 0}, -{ "s11", nullptr, 4, FPU_OFFSET(11), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, nullptr, g_s11_invalidates, nullptr, 0}, -{ "s12", nullptr, 4, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, nullptr, g_s12_invalidates, nullptr, 0}, -{ "s13", nullptr, 4, FPU_OFFSET(13), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, nullptr, g_s13_invalidates, nullptr, 0}, -{ "s14", nullptr, 4, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, nullptr, g_s14_invalidates, nullptr, 0}, -{ "s15", nullptr, 4, FPU_OFFSET(15), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, nullptr, g_s15_invalidates, nullptr, 0}, -{ "s16", nullptr, 4, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, nullptr, g_s16_invalidates, nullptr, 0}, -{ "s17", nullptr, 4, FPU_OFFSET(17), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, nullptr, g_s17_invalidates, nullptr, 0}, -{ "s18", nullptr, 4, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, nullptr, g_s18_invalidates, nullptr, 0}, -{ "s19", nullptr, 4, FPU_OFFSET(19), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, nullptr, g_s19_invalidates, nullptr, 0}, -{ "s20", nullptr, 4, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, nullptr, g_s20_invalidates, nullptr, 0}, -{ "s21", nullptr, 4, FPU_OFFSET(21), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, nullptr, g_s21_invalidates, nullptr, 0}, -{ "s22", nullptr, 4, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, nullptr, g_s22_invalidates, nullptr, 0}, -{ "s23", nullptr, 4, FPU_OFFSET(23), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, nullptr, g_s23_invalidates, nullptr, 0}, -{ "s24", nullptr, 4, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, nullptr, g_s24_invalidates, nullptr, 0}, -{ "s25", nullptr, 4, FPU_OFFSET(25), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, nullptr, g_s25_invalidates, nullptr, 0}, -{ "s26", nullptr, 4, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, nullptr, g_s26_invalidates, nullptr, 0}, -{ "s27", nullptr, 4, FPU_OFFSET(27), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, nullptr, g_s27_invalidates, nullptr, 0}, -{ "s28", nullptr, 4, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, nullptr, g_s28_invalidates, nullptr, 0}, -{ "s29", nullptr, 4, FPU_OFFSET(29), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, nullptr, g_s29_invalidates, nullptr, 0}, -{ "s30", nullptr, 4, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, nullptr, g_s30_invalidates, nullptr, 0}, -{ "s31", nullptr, 4, FPU_OFFSET(31), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, nullptr, g_s31_invalidates, nullptr, 0}, -{ "fpscr", nullptr, 4, FPSCR_OFFSET, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, nullptr, nullptr, nullptr, 0}, - -{ "d0", nullptr, 8, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d0 }, g_d0_contains, g_d0_invalidates, nullptr, 0}, -{ "d1", nullptr, 8, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d1 }, g_d1_contains, g_d1_invalidates, nullptr, 0}, -{ "d2", nullptr, 8, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d2 }, g_d2_contains, g_d2_invalidates, nullptr, 0}, -{ "d3", nullptr, 8, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d3 }, g_d3_contains, g_d3_invalidates, nullptr, 0}, -{ "d4", nullptr, 8, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d4 }, g_d4_contains, g_d4_invalidates, nullptr, 0}, -{ "d5", nullptr, 8, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d5 }, g_d5_contains, g_d5_invalidates, nullptr, 0}, -{ "d6", nullptr, 8, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d6 }, g_d6_contains, g_d6_invalidates, nullptr, 0}, -{ "d7", nullptr, 8, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d7 }, g_d7_contains, g_d7_invalidates, nullptr, 0}, -{ "d8", nullptr, 8, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d8 }, g_d8_contains, g_d8_invalidates, nullptr, 0}, -{ "d9", nullptr, 8, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d9 }, g_d9_contains, g_d9_invalidates, nullptr, 0}, -{ "d10", nullptr, 8, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d10 }, g_d10_contains, g_d10_invalidates, nullptr, 0}, -{ "d11", nullptr, 8, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d11 }, g_d11_contains, g_d11_invalidates, nullptr, 0}, -{ "d12", nullptr, 8, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d12 }, g_d12_contains, g_d12_invalidates, nullptr, 0}, -{ "d13", nullptr, 8, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d13 }, g_d13_contains, g_d13_invalidates, nullptr, 0}, -{ "d14", nullptr, 8, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d14 }, g_d14_contains, g_d14_invalidates, nullptr, 0}, -{ "d15", nullptr, 8, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d15 }, g_d15_contains, g_d15_invalidates, nullptr, 0}, -{ "d16", nullptr, 8, FPU_OFFSET(32), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d16 }, nullptr, g_d16_invalidates, nullptr, 0 }, -{ "d17", nullptr, 8, FPU_OFFSET(34), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d17 }, nullptr, g_d17_invalidates, nullptr, 0}, -{ "d18", nullptr, 8, FPU_OFFSET(36), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d18 }, nullptr, g_d18_invalidates, nullptr, 0}, -{ "d19", nullptr, 8, FPU_OFFSET(38), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d19 }, nullptr, g_d19_invalidates, nullptr, 0}, -{ "d20", nullptr, 8, FPU_OFFSET(40), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d20 }, nullptr, g_d20_invalidates, nullptr, 0}, -{ "d21", nullptr, 8, FPU_OFFSET(42), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d21 }, nullptr, g_d21_invalidates, nullptr, 0}, -{ "d22", nullptr, 8, FPU_OFFSET(44), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d22 }, nullptr, g_d22_invalidates, nullptr, 0}, -{ "d23", nullptr, 8, FPU_OFFSET(46), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d23 }, nullptr, g_d23_invalidates, nullptr, 0}, -{ "d24", nullptr, 8, FPU_OFFSET(48), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d24 }, nullptr, g_d24_invalidates, nullptr, 0}, -{ "d25", nullptr, 8, FPU_OFFSET(50), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d25 }, nullptr, g_d25_invalidates, nullptr, 0}, -{ "d26", nullptr, 8, FPU_OFFSET(52), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d26 }, nullptr, g_d26_invalidates, nullptr, 0}, -{ "d27", nullptr, 8, FPU_OFFSET(54), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d27 }, nullptr, g_d27_invalidates, nullptr, 0}, -{ "d28", nullptr, 8, FPU_OFFSET(56), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d28 }, nullptr, g_d28_invalidates, nullptr, 0}, -{ "d29", nullptr, 8, FPU_OFFSET(58), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d29 }, nullptr, g_d29_invalidates, nullptr, 0}, -{ "d30", nullptr, 8, FPU_OFFSET(60), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d30 }, nullptr, g_d30_invalidates, nullptr, 0}, -{ "d31", nullptr, 8, FPU_OFFSET(62), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d31 }, nullptr, g_d31_invalidates, nullptr, 0}, - -{ "q0", nullptr, 16, FPU_OFFSET(0), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q0 }, g_q0_contains, nullptr, nullptr, 0}, -{ "q1", nullptr, 16, FPU_OFFSET(4), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q1 }, g_q1_contains, nullptr, nullptr, 0}, -{ "q2", nullptr, 16, FPU_OFFSET(8), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q2 }, g_q2_contains, nullptr, nullptr, 0}, -{ "q3", nullptr, 16, FPU_OFFSET(12), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q3 }, g_q3_contains, nullptr, nullptr, 0}, -{ "q4", nullptr, 16, FPU_OFFSET(16), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q4 }, g_q4_contains, nullptr, nullptr, 0}, -{ "q5", nullptr, 16, FPU_OFFSET(20), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q5 }, g_q5_contains, nullptr, nullptr, 0}, -{ "q6", nullptr, 16, FPU_OFFSET(24), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q6 }, g_q6_contains, nullptr, nullptr, 0}, -{ "q7", nullptr, 16, FPU_OFFSET(28), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q7 }, g_q7_contains, nullptr, nullptr, 0}, -{ "q8", nullptr, 16, FPU_OFFSET(32), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q8 }, g_q8_contains, nullptr, nullptr, 0}, -{ "q9", nullptr, 16, FPU_OFFSET(36), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q9 }, g_q9_contains, nullptr, nullptr, 0}, -{ "q10", nullptr, 16, FPU_OFFSET(40), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q10 }, g_q10_contains, nullptr, nullptr, 0}, -{ "q11", nullptr, 16, FPU_OFFSET(44), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q11 }, g_q11_contains, nullptr, nullptr, 0}, -{ "q12", nullptr, 16, FPU_OFFSET(48), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q12 }, g_q12_contains, nullptr, nullptr, 0}, -{ "q13", nullptr, 16, FPU_OFFSET(52), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q13 }, g_q13_contains, nullptr, nullptr, 0}, -{ "q14", nullptr, 16, FPU_OFFSET(56), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q14 }, g_q14_contains, nullptr, nullptr, 0}, -{ "q15", nullptr, 16, FPU_OFFSET(60), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q15 }, g_q15_contains, nullptr, nullptr, 0}, - -{ "exception", nullptr, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr, nullptr, 0}, -{ "fsr", nullptr, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, nullptr, nullptr, nullptr, 0}, -{ "far", nullptr, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr, nullptr, 0}, - -{ DEFINE_DBG (bvr, 0) }, -{ DEFINE_DBG (bvr, 1) }, -{ DEFINE_DBG (bvr, 2) }, -{ DEFINE_DBG (bvr, 3) }, -{ DEFINE_DBG (bvr, 4) }, -{ DEFINE_DBG (bvr, 5) }, -{ DEFINE_DBG (bvr, 6) }, -{ DEFINE_DBG (bvr, 7) }, -{ DEFINE_DBG (bvr, 8) }, -{ DEFINE_DBG (bvr, 9) }, -{ DEFINE_DBG (bvr, 10) }, -{ DEFINE_DBG (bvr, 11) }, -{ DEFINE_DBG (bvr, 12) }, -{ DEFINE_DBG (bvr, 13) }, -{ DEFINE_DBG (bvr, 14) }, -{ DEFINE_DBG (bvr, 15) }, - -{ DEFINE_DBG (bcr, 0) }, -{ DEFINE_DBG (bcr, 1) }, -{ DEFINE_DBG (bcr, 2) }, -{ DEFINE_DBG (bcr, 3) }, -{ DEFINE_DBG (bcr, 4) }, -{ DEFINE_DBG (bcr, 5) }, -{ DEFINE_DBG (bcr, 6) }, -{ DEFINE_DBG (bcr, 7) }, -{ DEFINE_DBG (bcr, 8) }, -{ DEFINE_DBG (bcr, 9) }, -{ DEFINE_DBG (bcr, 10) }, -{ DEFINE_DBG (bcr, 11) }, -{ DEFINE_DBG (bcr, 12) }, -{ DEFINE_DBG (bcr, 13) }, -{ DEFINE_DBG (bcr, 14) }, -{ DEFINE_DBG (bcr, 15) }, - -{ DEFINE_DBG (wvr, 0) }, -{ DEFINE_DBG (wvr, 1) }, -{ DEFINE_DBG (wvr, 2) }, -{ DEFINE_DBG (wvr, 3) }, -{ DEFINE_DBG (wvr, 4) }, -{ DEFINE_DBG (wvr, 5) }, -{ DEFINE_DBG (wvr, 6) }, -{ DEFINE_DBG (wvr, 7) }, -{ DEFINE_DBG (wvr, 8) }, -{ DEFINE_DBG (wvr, 9) }, -{ DEFINE_DBG (wvr, 10) }, -{ DEFINE_DBG (wvr, 11) }, -{ DEFINE_DBG (wvr, 12) }, -{ DEFINE_DBG (wvr, 13) }, -{ DEFINE_DBG (wvr, 14) }, -{ DEFINE_DBG (wvr, 15) }, - -{ DEFINE_DBG (wcr, 0) }, -{ DEFINE_DBG (wcr, 1) }, -{ DEFINE_DBG (wcr, 2) }, -{ DEFINE_DBG (wcr, 3) }, -{ DEFINE_DBG (wcr, 4) }, -{ DEFINE_DBG (wcr, 5) }, -{ DEFINE_DBG (wcr, 6) }, -{ DEFINE_DBG (wcr, 7) }, -{ DEFINE_DBG (wcr, 8) }, -{ DEFINE_DBG (wcr, 9) }, -{ DEFINE_DBG (wcr, 10) }, -{ DEFINE_DBG (wcr, 11) }, -{ DEFINE_DBG (wcr, 12) }, -{ DEFINE_DBG (wcr, 13) }, -{ DEFINE_DBG (wcr, 14) }, -{ DEFINE_DBG (wcr, 15) } -}; + // NAME ALT SZ OFFSET ENCODING FORMAT + // EH_FRAME DWARF GENERIC + // PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS + // =========== ======= == ============== ================ + // ==================== =================== =================== + // ========================== =================== ============= + // ============== ================= + {"r0", + nullptr, + 4, + GPR_OFFSET(0), + eEncodingUint, + eFormatHex, + {ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, + gpr_r0}, + nullptr, + nullptr, + nullptr, + 0}, + {"r1", + nullptr, + 4, + GPR_OFFSET(1), + eEncodingUint, + eFormatHex, + {ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, + gpr_r1}, + nullptr, + nullptr, + nullptr, + 0}, + {"r2", + nullptr, + 4, + GPR_OFFSET(2), + eEncodingUint, + eFormatHex, + {ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, + gpr_r2}, + nullptr, + nullptr, + nullptr, + 0}, + {"r3", + nullptr, + 4, + GPR_OFFSET(3), + eEncodingUint, + eFormatHex, + {ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, + gpr_r3}, + nullptr, + nullptr, + nullptr, + 0}, + {"r4", + nullptr, + 4, + GPR_OFFSET(4), + eEncodingUint, + eFormatHex, + {ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4}, + nullptr, + nullptr, + nullptr, + 0}, + {"r5", + nullptr, + 4, + GPR_OFFSET(5), + eEncodingUint, + eFormatHex, + {ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5}, + nullptr, + nullptr, + nullptr, + 0}, + {"r6", + nullptr, + 4, + GPR_OFFSET(6), + eEncodingUint, + eFormatHex, + {ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6}, + nullptr, + nullptr, + nullptr, + 0}, + {"r7", + nullptr, + 4, + GPR_OFFSET(7), + eEncodingUint, + eFormatHex, + {ehframe_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r7}, + nullptr, + nullptr, + nullptr, + 0}, + {"r8", + nullptr, + 4, + GPR_OFFSET(8), + eEncodingUint, + eFormatHex, + {ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8}, + nullptr, + nullptr, + nullptr, + 0}, + {"r9", + nullptr, + 4, + GPR_OFFSET(9), + eEncodingUint, + eFormatHex, + {ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9}, + nullptr, + nullptr, + nullptr, + 0}, + {"r10", + nullptr, + 4, + GPR_OFFSET(10), + eEncodingUint, + eFormatHex, + {ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_r10}, + nullptr, + nullptr, + nullptr, + 0}, + {"r11", + nullptr, + 4, + GPR_OFFSET(11), + eEncodingUint, + eFormatHex, + {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, + gpr_r11}, + nullptr, + nullptr, + nullptr, + 0}, + {"r12", + nullptr, + 4, + GPR_OFFSET(12), + eEncodingUint, + eFormatHex, + {ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + gpr_r12}, + nullptr, + nullptr, + nullptr, + 0}, + {"sp", + "r13", + 4, + GPR_OFFSET(13), + eEncodingUint, + eFormatHex, + {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, + gpr_sp}, + nullptr, + nullptr, + nullptr, + 0}, + {"lr", + "r14", + 4, + GPR_OFFSET(14), + eEncodingUint, + eFormatHex, + {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, + gpr_lr}, + nullptr, + nullptr, + nullptr, + 0}, + {"pc", + "r15", + 4, + GPR_OFFSET(15), + eEncodingUint, + eFormatHex, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + gpr_pc}, + nullptr, + nullptr, + nullptr, + 0}, + {"cpsr", + "psr", + 4, + GPR_OFFSET(16), + eEncodingUint, + eFormatHex, + {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, + gpr_cpsr}, + nullptr, + nullptr, + nullptr, + 0}, + + {"s0", + nullptr, + 4, + FPU_OFFSET(0), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s0}, + nullptr, + g_s0_invalidates, + nullptr, + 0}, + {"s1", + nullptr, + 4, + FPU_OFFSET(1), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s1}, + nullptr, + g_s1_invalidates, + nullptr, + 0}, + {"s2", + nullptr, + 4, + FPU_OFFSET(2), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s2}, + nullptr, + g_s2_invalidates, + nullptr, + 0}, + {"s3", + nullptr, + 4, + FPU_OFFSET(3), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s3}, + nullptr, + g_s3_invalidates, + nullptr, + 0}, + {"s4", + nullptr, + 4, + FPU_OFFSET(4), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s4}, + nullptr, + g_s4_invalidates, + nullptr, + 0}, + {"s5", + nullptr, + 4, + FPU_OFFSET(5), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s5}, + nullptr, + g_s5_invalidates, + nullptr, + 0}, + {"s6", + nullptr, + 4, + FPU_OFFSET(6), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s6}, + nullptr, + g_s6_invalidates, + nullptr, + 0}, + {"s7", + nullptr, + 4, + FPU_OFFSET(7), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s7}, + nullptr, + g_s7_invalidates, + nullptr, + 0}, + {"s8", + nullptr, + 4, + FPU_OFFSET(8), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s8}, + nullptr, + g_s8_invalidates, + nullptr, + 0}, + {"s9", + nullptr, + 4, + FPU_OFFSET(9), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s9}, + nullptr, + g_s9_invalidates, + nullptr, + 0}, + {"s10", + nullptr, + 4, + FPU_OFFSET(10), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s10}, + nullptr, + g_s10_invalidates, + nullptr, + 0}, + {"s11", + nullptr, + 4, + FPU_OFFSET(11), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s11}, + nullptr, + g_s11_invalidates, + nullptr, + 0}, + {"s12", + nullptr, + 4, + FPU_OFFSET(12), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s12}, + nullptr, + g_s12_invalidates, + nullptr, + 0}, + {"s13", + nullptr, + 4, + FPU_OFFSET(13), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s13}, + nullptr, + g_s13_invalidates, + nullptr, + 0}, + {"s14", + nullptr, + 4, + FPU_OFFSET(14), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s14}, + nullptr, + g_s14_invalidates, + nullptr, + 0}, + {"s15", + nullptr, + 4, + FPU_OFFSET(15), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s15}, + nullptr, + g_s15_invalidates, + nullptr, + 0}, + {"s16", + nullptr, + 4, + FPU_OFFSET(16), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s16}, + nullptr, + g_s16_invalidates, + nullptr, + 0}, + {"s17", + nullptr, + 4, + FPU_OFFSET(17), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s17}, + nullptr, + g_s17_invalidates, + nullptr, + 0}, + {"s18", + nullptr, + 4, + FPU_OFFSET(18), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s18}, + nullptr, + g_s18_invalidates, + nullptr, + 0}, + {"s19", + nullptr, + 4, + FPU_OFFSET(19), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s19}, + nullptr, + g_s19_invalidates, + nullptr, + 0}, + {"s20", + nullptr, + 4, + FPU_OFFSET(20), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s20}, + nullptr, + g_s20_invalidates, + nullptr, + 0}, + {"s21", + nullptr, + 4, + FPU_OFFSET(21), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s21}, + nullptr, + g_s21_invalidates, + nullptr, + 0}, + {"s22", + nullptr, + 4, + FPU_OFFSET(22), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s22}, + nullptr, + g_s22_invalidates, + nullptr, + 0}, + {"s23", + nullptr, + 4, + FPU_OFFSET(23), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s23}, + nullptr, + g_s23_invalidates, + nullptr, + 0}, + {"s24", + nullptr, + 4, + FPU_OFFSET(24), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s24}, + nullptr, + g_s24_invalidates, + nullptr, + 0}, + {"s25", + nullptr, + 4, + FPU_OFFSET(25), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s25}, + nullptr, + g_s25_invalidates, + nullptr, + 0}, + {"s26", + nullptr, + 4, + FPU_OFFSET(26), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s26}, + nullptr, + g_s26_invalidates, + nullptr, + 0}, + {"s27", + nullptr, + 4, + FPU_OFFSET(27), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s27}, + nullptr, + g_s27_invalidates, + nullptr, + 0}, + {"s28", + nullptr, + 4, + FPU_OFFSET(28), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s28}, + nullptr, + g_s28_invalidates, + nullptr, + 0}, + {"s29", + nullptr, + 4, + FPU_OFFSET(29), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s29}, + nullptr, + g_s29_invalidates, + nullptr, + 0}, + {"s30", + nullptr, + 4, + FPU_OFFSET(30), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s30}, + nullptr, + g_s30_invalidates, + nullptr, + 0}, + {"s31", + nullptr, + 4, + FPU_OFFSET(31), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_s31}, + nullptr, + g_s31_invalidates, + nullptr, + 0}, + {"fpscr", + nullptr, + 4, + FPSCR_OFFSET, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fpscr}, + nullptr, + nullptr, + nullptr, + 0}, + + {"d0", + nullptr, + 8, + FPU_OFFSET(0), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d0}, + g_d0_contains, + g_d0_invalidates, + nullptr, + 0}, + {"d1", + nullptr, + 8, + FPU_OFFSET(2), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d1}, + g_d1_contains, + g_d1_invalidates, + nullptr, + 0}, + {"d2", + nullptr, + 8, + FPU_OFFSET(4), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d2}, + g_d2_contains, + g_d2_invalidates, + nullptr, + 0}, + {"d3", + nullptr, + 8, + FPU_OFFSET(6), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d3}, + g_d3_contains, + g_d3_invalidates, + nullptr, + 0}, + {"d4", + nullptr, + 8, + FPU_OFFSET(8), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d4}, + g_d4_contains, + g_d4_invalidates, + nullptr, + 0}, + {"d5", + nullptr, + 8, + FPU_OFFSET(10), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d5}, + g_d5_contains, + g_d5_invalidates, + nullptr, + 0}, + {"d6", + nullptr, + 8, + FPU_OFFSET(12), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d6}, + g_d6_contains, + g_d6_invalidates, + nullptr, + 0}, + {"d7", + nullptr, + 8, + FPU_OFFSET(14), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d7}, + g_d7_contains, + g_d7_invalidates, + nullptr, + 0}, + {"d8", + nullptr, + 8, + FPU_OFFSET(16), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d8}, + g_d8_contains, + g_d8_invalidates, + nullptr, + 0}, + {"d9", + nullptr, + 8, + FPU_OFFSET(18), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d9}, + g_d9_contains, + g_d9_invalidates, + nullptr, + 0}, + {"d10", + nullptr, + 8, + FPU_OFFSET(20), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d10}, + g_d10_contains, + g_d10_invalidates, + nullptr, + 0}, + {"d11", + nullptr, + 8, + FPU_OFFSET(22), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d11}, + g_d11_contains, + g_d11_invalidates, + nullptr, + 0}, + {"d12", + nullptr, + 8, + FPU_OFFSET(24), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d12}, + g_d12_contains, + g_d12_invalidates, + nullptr, + 0}, + {"d13", + nullptr, + 8, + FPU_OFFSET(26), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d13}, + g_d13_contains, + g_d13_invalidates, + nullptr, + 0}, + {"d14", + nullptr, + 8, + FPU_OFFSET(28), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d14}, + g_d14_contains, + g_d14_invalidates, + nullptr, + 0}, + {"d15", + nullptr, + 8, + FPU_OFFSET(30), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d15}, + g_d15_contains, + g_d15_invalidates, + nullptr, + 0}, + {"d16", + nullptr, + 8, + FPU_OFFSET(32), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d16}, + nullptr, + g_d16_invalidates, + nullptr, + 0}, + {"d17", + nullptr, + 8, + FPU_OFFSET(34), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d17}, + nullptr, + g_d17_invalidates, + nullptr, + 0}, + {"d18", + nullptr, + 8, + FPU_OFFSET(36), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d18}, + nullptr, + g_d18_invalidates, + nullptr, + 0}, + {"d19", + nullptr, + 8, + FPU_OFFSET(38), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d19}, + nullptr, + g_d19_invalidates, + nullptr, + 0}, + {"d20", + nullptr, + 8, + FPU_OFFSET(40), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d20}, + nullptr, + g_d20_invalidates, + nullptr, + 0}, + {"d21", + nullptr, + 8, + FPU_OFFSET(42), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d21}, + nullptr, + g_d21_invalidates, + nullptr, + 0}, + {"d22", + nullptr, + 8, + FPU_OFFSET(44), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d22}, + nullptr, + g_d22_invalidates, + nullptr, + 0}, + {"d23", + nullptr, + 8, + FPU_OFFSET(46), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d23}, + nullptr, + g_d23_invalidates, + nullptr, + 0}, + {"d24", + nullptr, + 8, + FPU_OFFSET(48), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d24}, + nullptr, + g_d24_invalidates, + nullptr, + 0}, + {"d25", + nullptr, + 8, + FPU_OFFSET(50), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d25}, + nullptr, + g_d25_invalidates, + nullptr, + 0}, + {"d26", + nullptr, + 8, + FPU_OFFSET(52), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d26}, + nullptr, + g_d26_invalidates, + nullptr, + 0}, + {"d27", + nullptr, + 8, + FPU_OFFSET(54), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d27}, + nullptr, + g_d27_invalidates, + nullptr, + 0}, + {"d28", + nullptr, + 8, + FPU_OFFSET(56), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d28}, + nullptr, + g_d28_invalidates, + nullptr, + 0}, + {"d29", + nullptr, + 8, + FPU_OFFSET(58), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d29}, + nullptr, + g_d29_invalidates, + nullptr, + 0}, + {"d30", + nullptr, + 8, + FPU_OFFSET(60), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d30}, + nullptr, + g_d30_invalidates, + nullptr, + 0}, + {"d31", + nullptr, + 8, + FPU_OFFSET(62), + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_d31}, + nullptr, + g_d31_invalidates, + nullptr, + 0}, + + {"q0", + nullptr, + 16, + FPU_OFFSET(0), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q0}, + g_q0_contains, + nullptr, + nullptr, + 0}, + {"q1", + nullptr, + 16, + FPU_OFFSET(4), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q1}, + g_q1_contains, + nullptr, + nullptr, + 0}, + {"q2", + nullptr, + 16, + FPU_OFFSET(8), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q2}, + g_q2_contains, + nullptr, + nullptr, + 0}, + {"q3", + nullptr, + 16, + FPU_OFFSET(12), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q3}, + g_q3_contains, + nullptr, + nullptr, + 0}, + {"q4", + nullptr, + 16, + FPU_OFFSET(16), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q4}, + g_q4_contains, + nullptr, + nullptr, + 0}, + {"q5", + nullptr, + 16, + FPU_OFFSET(20), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q5}, + g_q5_contains, + nullptr, + nullptr, + 0}, + {"q6", + nullptr, + 16, + FPU_OFFSET(24), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q6}, + g_q6_contains, + nullptr, + nullptr, + 0}, + {"q7", + nullptr, + 16, + FPU_OFFSET(28), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q7}, + g_q7_contains, + nullptr, + nullptr, + 0}, + {"q8", + nullptr, + 16, + FPU_OFFSET(32), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q8}, + g_q8_contains, + nullptr, + nullptr, + 0}, + {"q9", + nullptr, + 16, + FPU_OFFSET(36), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q9}, + g_q9_contains, + nullptr, + nullptr, + 0}, + {"q10", + nullptr, + 16, + FPU_OFFSET(40), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q10}, + g_q10_contains, + nullptr, + nullptr, + 0}, + {"q11", + nullptr, + 16, + FPU_OFFSET(44), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q11}, + g_q11_contains, + nullptr, + nullptr, + 0}, + {"q12", + nullptr, + 16, + FPU_OFFSET(48), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q12}, + g_q12_contains, + nullptr, + nullptr, + 0}, + {"q13", + nullptr, + 16, + FPU_OFFSET(52), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q13}, + g_q13_contains, + nullptr, + nullptr, + 0}, + {"q14", + nullptr, + 16, + FPU_OFFSET(56), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q14}, + g_q14_contains, + nullptr, + nullptr, + 0}, + {"q15", + nullptr, + 16, + FPU_OFFSET(60), + eEncodingVector, + eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + fpu_q15}, + g_q15_contains, + nullptr, + nullptr, + 0}, + + {"exception", + nullptr, + 4, + EXC_OFFSET(0), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_exception}, + nullptr, + nullptr, + nullptr, + 0}, + {"fsr", + nullptr, + 4, + EXC_OFFSET(1), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_fsr}, + nullptr, + nullptr, + nullptr, + 0}, + {"far", + nullptr, + 4, + EXC_OFFSET(2), + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_far}, + nullptr, + nullptr, + nullptr, + 0}, + + {DEFINE_DBG(bvr, 0)}, + {DEFINE_DBG(bvr, 1)}, + {DEFINE_DBG(bvr, 2)}, + {DEFINE_DBG(bvr, 3)}, + {DEFINE_DBG(bvr, 4)}, + {DEFINE_DBG(bvr, 5)}, + {DEFINE_DBG(bvr, 6)}, + {DEFINE_DBG(bvr, 7)}, + {DEFINE_DBG(bvr, 8)}, + {DEFINE_DBG(bvr, 9)}, + {DEFINE_DBG(bvr, 10)}, + {DEFINE_DBG(bvr, 11)}, + {DEFINE_DBG(bvr, 12)}, + {DEFINE_DBG(bvr, 13)}, + {DEFINE_DBG(bvr, 14)}, + {DEFINE_DBG(bvr, 15)}, + + {DEFINE_DBG(bcr, 0)}, + {DEFINE_DBG(bcr, 1)}, + {DEFINE_DBG(bcr, 2)}, + {DEFINE_DBG(bcr, 3)}, + {DEFINE_DBG(bcr, 4)}, + {DEFINE_DBG(bcr, 5)}, + {DEFINE_DBG(bcr, 6)}, + {DEFINE_DBG(bcr, 7)}, + {DEFINE_DBG(bcr, 8)}, + {DEFINE_DBG(bcr, 9)}, + {DEFINE_DBG(bcr, 10)}, + {DEFINE_DBG(bcr, 11)}, + {DEFINE_DBG(bcr, 12)}, + {DEFINE_DBG(bcr, 13)}, + {DEFINE_DBG(bcr, 14)}, + {DEFINE_DBG(bcr, 15)}, + + {DEFINE_DBG(wvr, 0)}, + {DEFINE_DBG(wvr, 1)}, + {DEFINE_DBG(wvr, 2)}, + {DEFINE_DBG(wvr, 3)}, + {DEFINE_DBG(wvr, 4)}, + {DEFINE_DBG(wvr, 5)}, + {DEFINE_DBG(wvr, 6)}, + {DEFINE_DBG(wvr, 7)}, + {DEFINE_DBG(wvr, 8)}, + {DEFINE_DBG(wvr, 9)}, + {DEFINE_DBG(wvr, 10)}, + {DEFINE_DBG(wvr, 11)}, + {DEFINE_DBG(wvr, 12)}, + {DEFINE_DBG(wvr, 13)}, + {DEFINE_DBG(wvr, 14)}, + {DEFINE_DBG(wvr, 15)}, + + {DEFINE_DBG(wcr, 0)}, + {DEFINE_DBG(wcr, 1)}, + {DEFINE_DBG(wcr, 2)}, + {DEFINE_DBG(wcr, 3)}, + {DEFINE_DBG(wcr, 4)}, + {DEFINE_DBG(wcr, 5)}, + {DEFINE_DBG(wcr, 6)}, + {DEFINE_DBG(wcr, 7)}, + {DEFINE_DBG(wcr, 8)}, + {DEFINE_DBG(wcr, 9)}, + {DEFINE_DBG(wcr, 10)}, + {DEFINE_DBG(wcr, 11)}, + {DEFINE_DBG(wcr, 12)}, + {DEFINE_DBG(wcr, 13)}, + {DEFINE_DBG(wcr, 14)}, + {DEFINE_DBG(wcr, 15)}}; #endif // DECLARE_REGISTER_INFOS_ARM_STRUCT diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h index f360f25501e..928e699643b 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -15,9 +15,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" #include "Utility/ARM64_DWARF_Registers.h" #include "Utility/ARM64_ehframe_Registers.h" @@ -50,302 +50,1091 @@ #error DEFINE_DBG must be defined before including this header file #endif -enum -{ - gpr_x0 = 0, - gpr_x1, - gpr_x2, - gpr_x3, - gpr_x4, - gpr_x5, - gpr_x6, - gpr_x7, - gpr_x8, - gpr_x9, - gpr_x10, - gpr_x11, - gpr_x12, - gpr_x13, - gpr_x14, - gpr_x15, - gpr_x16, - gpr_x17, - gpr_x18, - gpr_x19, - gpr_x20, - gpr_x21, - gpr_x22, - gpr_x23, - gpr_x24, - gpr_x25, - gpr_x26, - gpr_x27, - gpr_x28, - gpr_x29 = 29, gpr_fp = gpr_x29, - gpr_x30 = 30, gpr_lr = gpr_x30, gpr_ra = gpr_x30, - gpr_x31 = 31, gpr_sp = gpr_x31, - gpr_pc = 32, - gpr_cpsr, +enum { + gpr_x0 = 0, + gpr_x1, + gpr_x2, + gpr_x3, + gpr_x4, + gpr_x5, + gpr_x6, + gpr_x7, + gpr_x8, + gpr_x9, + gpr_x10, + gpr_x11, + gpr_x12, + gpr_x13, + gpr_x14, + gpr_x15, + gpr_x16, + gpr_x17, + gpr_x18, + gpr_x19, + gpr_x20, + gpr_x21, + gpr_x22, + gpr_x23, + gpr_x24, + gpr_x25, + gpr_x26, + gpr_x27, + gpr_x28, + gpr_x29 = 29, + gpr_fp = gpr_x29, + gpr_x30 = 30, + gpr_lr = gpr_x30, + gpr_ra = gpr_x30, + gpr_x31 = 31, + gpr_sp = gpr_x31, + gpr_pc = 32, + gpr_cpsr, - fpu_v0, - fpu_v1, - fpu_v2, - fpu_v3, - fpu_v4, - fpu_v5, - fpu_v6, - fpu_v7, - fpu_v8, - fpu_v9, - fpu_v10, - fpu_v11, - fpu_v12, - fpu_v13, - fpu_v14, - fpu_v15, - fpu_v16, - fpu_v17, - fpu_v18, - fpu_v19, - fpu_v20, - fpu_v21, - fpu_v22, - fpu_v23, - fpu_v24, - fpu_v25, - fpu_v26, - fpu_v27, - fpu_v28, - fpu_v29, - fpu_v30, - fpu_v31, + fpu_v0, + fpu_v1, + fpu_v2, + fpu_v3, + fpu_v4, + fpu_v5, + fpu_v6, + fpu_v7, + fpu_v8, + fpu_v9, + fpu_v10, + fpu_v11, + fpu_v12, + fpu_v13, + fpu_v14, + fpu_v15, + fpu_v16, + fpu_v17, + fpu_v18, + fpu_v19, + fpu_v20, + fpu_v21, + fpu_v22, + fpu_v23, + fpu_v24, + fpu_v25, + fpu_v26, + fpu_v27, + fpu_v28, + fpu_v29, + fpu_v30, + fpu_v31, - fpu_fpsr, - fpu_fpcr, + fpu_fpsr, + fpu_fpcr, - exc_far, - exc_esr, - exc_exception, + exc_far, + exc_esr, + exc_exception, - dbg_bvr0, - dbg_bvr1, - dbg_bvr2, - dbg_bvr3, - dbg_bvr4, - dbg_bvr5, - dbg_bvr6, - dbg_bvr7, - dbg_bvr8, - dbg_bvr9, - dbg_bvr10, - dbg_bvr11, - dbg_bvr12, - dbg_bvr13, - dbg_bvr14, - dbg_bvr15, + dbg_bvr0, + dbg_bvr1, + dbg_bvr2, + dbg_bvr3, + dbg_bvr4, + dbg_bvr5, + dbg_bvr6, + dbg_bvr7, + dbg_bvr8, + dbg_bvr9, + dbg_bvr10, + dbg_bvr11, + dbg_bvr12, + dbg_bvr13, + dbg_bvr14, + dbg_bvr15, - dbg_bcr0, - dbg_bcr1, - dbg_bcr2, - dbg_bcr3, - dbg_bcr4, - dbg_bcr5, - dbg_bcr6, - dbg_bcr7, - dbg_bcr8, - dbg_bcr9, - dbg_bcr10, - dbg_bcr11, - dbg_bcr12, - dbg_bcr13, - dbg_bcr14, - dbg_bcr15, + dbg_bcr0, + dbg_bcr1, + dbg_bcr2, + dbg_bcr3, + dbg_bcr4, + dbg_bcr5, + dbg_bcr6, + dbg_bcr7, + dbg_bcr8, + dbg_bcr9, + dbg_bcr10, + dbg_bcr11, + dbg_bcr12, + dbg_bcr13, + dbg_bcr14, + dbg_bcr15, - dbg_wvr0, - dbg_wvr1, - dbg_wvr2, - dbg_wvr3, - dbg_wvr4, - dbg_wvr5, - dbg_wvr6, - dbg_wvr7, - dbg_wvr8, - dbg_wvr9, - dbg_wvr10, - dbg_wvr11, - dbg_wvr12, - dbg_wvr13, - dbg_wvr14, - dbg_wvr15, + dbg_wvr0, + dbg_wvr1, + dbg_wvr2, + dbg_wvr3, + dbg_wvr4, + dbg_wvr5, + dbg_wvr6, + dbg_wvr7, + dbg_wvr8, + dbg_wvr9, + dbg_wvr10, + dbg_wvr11, + dbg_wvr12, + dbg_wvr13, + dbg_wvr14, + dbg_wvr15, - dbg_wcr0, - dbg_wcr1, - dbg_wcr2, - dbg_wcr3, - dbg_wcr4, - dbg_wcr5, - dbg_wcr6, - dbg_wcr7, - dbg_wcr8, - dbg_wcr9, - dbg_wcr10, - dbg_wcr11, - dbg_wcr12, - dbg_wcr13, - dbg_wcr14, - dbg_wcr15, + dbg_wcr0, + dbg_wcr1, + dbg_wcr2, + dbg_wcr3, + dbg_wcr4, + dbg_wcr5, + dbg_wcr6, + dbg_wcr7, + dbg_wcr8, + dbg_wcr9, + dbg_wcr10, + dbg_wcr11, + dbg_wcr12, + dbg_wcr13, + dbg_wcr14, + dbg_wcr15, - k_num_registers + k_num_registers }; static lldb_private::RegisterInfo g_register_infos_arm64[] = { -// General purpose registers -// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS -// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== =============== -{ "x0", nullptr, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x0 }, nullptr, nullptr, nullptr, 0}, -{ "x1", nullptr, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x1 }, nullptr, nullptr, nullptr, 0}, -{ "x2", nullptr, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x2 }, nullptr, nullptr, nullptr, 0}, -{ "x3", nullptr, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x3 }, nullptr, nullptr, nullptr, 0}, -{ "x4", nullptr, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x4 }, nullptr, nullptr, nullptr, 0}, -{ "x5", nullptr, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x5 }, nullptr, nullptr, nullptr, 0}, -{ "x6", nullptr, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x6 }, nullptr, nullptr, nullptr, 0}, -{ "x7", nullptr, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x7 }, nullptr, nullptr, nullptr, 0}, -{ "x8", nullptr, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x8 }, nullptr, nullptr, nullptr, 0}, -{ "x9", nullptr, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9 }, nullptr, nullptr, nullptr, 0}, -{ "x10", nullptr, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x10 }, nullptr, nullptr, nullptr, 0}, -{ "x11", nullptr, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x11 }, nullptr, nullptr, nullptr, 0}, -{ "x12", nullptr, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x12 }, nullptr, nullptr, nullptr, 0}, -{ "x13", nullptr, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x13 }, nullptr, nullptr, nullptr, 0}, -{ "x14", nullptr, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x14 }, nullptr, nullptr, nullptr, 0}, -{ "x15", nullptr, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x15 }, nullptr, nullptr, nullptr, 0}, -{ "x16", nullptr, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x16 }, nullptr, nullptr, nullptr, 0}, -{ "x17", nullptr, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x17 }, nullptr, nullptr, nullptr, 0}, -{ "x18", nullptr, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18 }, nullptr, nullptr, nullptr, 0}, -{ "x19", nullptr, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19 }, nullptr, nullptr, nullptr, 0}, -{ "x20", nullptr, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20 }, nullptr, nullptr, nullptr, 0}, -{ "x21", nullptr, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21 }, nullptr, nullptr, nullptr, 0}, -{ "x22", nullptr, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22 }, nullptr, nullptr, nullptr, 0}, -{ "x23", nullptr, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23 }, nullptr, nullptr, nullptr, 0}, -{ "x24", nullptr, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24 }, nullptr, nullptr, nullptr, 0}, -{ "x25", nullptr, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25 }, nullptr, nullptr, nullptr, 0}, -{ "x26", nullptr, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26 }, nullptr, nullptr, nullptr, 0}, -{ "x27", nullptr, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27 }, nullptr, nullptr, nullptr, 0}, -{ "x28", nullptr, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28 }, nullptr, nullptr, nullptr, 0}, + // General purpose registers + // NAME ALT SZ OFFSET ENCODING + // FORMAT EH_FRAME DWARF + // GENERIC PROCESS PLUGIN LLDB NATIVE VALUE + // REGS INVALIDATE REGS + // ====== ======= == ============= ============= + // ============ =============== =============== + // ========================= ===================== ============= + // ========== =============== + {"x0", + nullptr, + 8, + GPR_OFFSET(0), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, + LLDB_INVALID_REGNUM, gpr_x0}, + nullptr, + nullptr, + nullptr, + 0}, + {"x1", + nullptr, + 8, + GPR_OFFSET(1), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, + LLDB_INVALID_REGNUM, gpr_x1}, + nullptr, + nullptr, + nullptr, + 0}, + {"x2", + nullptr, + 8, + GPR_OFFSET(2), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, + LLDB_INVALID_REGNUM, gpr_x2}, + nullptr, + nullptr, + nullptr, + 0}, + {"x3", + nullptr, + 8, + GPR_OFFSET(3), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, + LLDB_INVALID_REGNUM, gpr_x3}, + nullptr, + nullptr, + nullptr, + 0}, + {"x4", + nullptr, + 8, + GPR_OFFSET(4), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, + LLDB_INVALID_REGNUM, gpr_x4}, + nullptr, + nullptr, + nullptr, + 0}, + {"x5", + nullptr, + 8, + GPR_OFFSET(5), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, + LLDB_INVALID_REGNUM, gpr_x5}, + nullptr, + nullptr, + nullptr, + 0}, + {"x6", + nullptr, + 8, + GPR_OFFSET(6), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, + LLDB_INVALID_REGNUM, gpr_x6}, + nullptr, + nullptr, + nullptr, + 0}, + {"x7", + nullptr, + 8, + GPR_OFFSET(7), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, + LLDB_INVALID_REGNUM, gpr_x7}, + nullptr, + nullptr, + nullptr, + 0}, + {"x8", + nullptr, + 8, + GPR_OFFSET(8), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x8}, + nullptr, + nullptr, + nullptr, + 0}, + {"x9", + nullptr, + 8, + GPR_OFFSET(9), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x9}, + nullptr, + nullptr, + nullptr, + 0}, + {"x10", + nullptr, + 8, + GPR_OFFSET(10), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x10}, + nullptr, + nullptr, + nullptr, + 0}, + {"x11", + nullptr, + 8, + GPR_OFFSET(11), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x11}, + nullptr, + nullptr, + nullptr, + 0}, + {"x12", + nullptr, + 8, + GPR_OFFSET(12), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x12}, + nullptr, + nullptr, + nullptr, + 0}, + {"x13", + nullptr, + 8, + GPR_OFFSET(13), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x13}, + nullptr, + nullptr, + nullptr, + 0}, + {"x14", + nullptr, + 8, + GPR_OFFSET(14), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x14}, + nullptr, + nullptr, + nullptr, + 0}, + {"x15", + nullptr, + 8, + GPR_OFFSET(15), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x15}, + nullptr, + nullptr, + nullptr, + 0}, + {"x16", + nullptr, + 8, + GPR_OFFSET(16), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x16}, + nullptr, + nullptr, + nullptr, + 0}, + {"x17", + nullptr, + 8, + GPR_OFFSET(17), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x17}, + nullptr, + nullptr, + nullptr, + 0}, + {"x18", + nullptr, + 8, + GPR_OFFSET(18), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x18}, + nullptr, + nullptr, + nullptr, + 0}, + {"x19", + nullptr, + 8, + GPR_OFFSET(19), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x19}, + nullptr, + nullptr, + nullptr, + 0}, + {"x20", + nullptr, + 8, + GPR_OFFSET(20), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x20}, + nullptr, + nullptr, + nullptr, + 0}, + {"x21", + nullptr, + 8, + GPR_OFFSET(21), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x21}, + nullptr, + nullptr, + nullptr, + 0}, + {"x22", + nullptr, + 8, + GPR_OFFSET(22), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x22}, + nullptr, + nullptr, + nullptr, + 0}, + {"x23", + nullptr, + 8, + GPR_OFFSET(23), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x23}, + nullptr, + nullptr, + nullptr, + 0}, + {"x24", + nullptr, + 8, + GPR_OFFSET(24), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x24}, + nullptr, + nullptr, + nullptr, + 0}, + {"x25", + nullptr, + 8, + GPR_OFFSET(25), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x25}, + nullptr, + nullptr, + nullptr, + 0}, + {"x26", + nullptr, + 8, + GPR_OFFSET(26), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x26}, + nullptr, + nullptr, + nullptr, + 0}, + {"x27", + nullptr, + 8, + GPR_OFFSET(27), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x27}, + nullptr, + nullptr, + nullptr, + 0}, + {"x28", + nullptr, + 8, + GPR_OFFSET(28), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, gpr_x28}, + nullptr, + nullptr, + nullptr, + 0}, -{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_fp }, nullptr, nullptr, nullptr, 0}, -{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr, nullptr, 0}, -{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr, nullptr, 0}, -{ "pc", nullptr, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr, nullptr, 0}, + {"fp", + "x29", + 8, + GPR_OFFSET(29), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, gpr_fp}, + nullptr, + nullptr, + nullptr, + 0}, + {"lr", + "x30", + 8, + GPR_OFFSET(30), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, + LLDB_INVALID_REGNUM, gpr_lr}, + nullptr, + nullptr, + nullptr, + 0}, + {"sp", + "x31", + 8, + GPR_OFFSET(31), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, gpr_sp}, + nullptr, + nullptr, + nullptr, + 0}, + {"pc", + nullptr, + 8, + GPR_OFFSET(32), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, gpr_pc}, + nullptr, + nullptr, + nullptr, + 0}, -{ "cpsr", nullptr, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr, nullptr, 0}, + {"cpsr", + nullptr, + 4, + GPR_OFFSET_NAME(cpsr), + lldb::eEncodingUint, + lldb::eFormatHex, + {arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, gpr_cpsr}, + nullptr, + nullptr, + nullptr, + 0}, -{ "v0", nullptr, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v0 }, nullptr, nullptr, nullptr, 0}, -{ "v1", nullptr, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v1 }, nullptr, nullptr, nullptr, 0}, -{ "v2", nullptr, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v2 }, nullptr, nullptr, nullptr, 0}, -{ "v3", nullptr, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v3 }, nullptr, nullptr, nullptr, 0}, -{ "v4", nullptr, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v4 }, nullptr, nullptr, nullptr, 0}, -{ "v5", nullptr, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v5 }, nullptr, nullptr, nullptr, 0}, -{ "v6", nullptr, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v6 }, nullptr, nullptr, nullptr, 0}, -{ "v7", nullptr, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v7 }, nullptr, nullptr, nullptr, 0}, -{ "v8", nullptr, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v8 }, nullptr, nullptr, nullptr, 0}, -{ "v9", nullptr, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v9 }, nullptr, nullptr, nullptr, 0}, -{ "v10", nullptr, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v10 }, nullptr, nullptr, nullptr, 0}, -{ "v11", nullptr, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v11 }, nullptr, nullptr, nullptr, 0}, -{ "v12", nullptr, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v12 }, nullptr, nullptr, nullptr, 0}, -{ "v13", nullptr, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v13 }, nullptr, nullptr, nullptr, 0}, -{ "v14", nullptr, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v14 }, nullptr, nullptr, nullptr, 0}, -{ "v15", nullptr, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v15 }, nullptr, nullptr, nullptr, 0}, -{ "v16", nullptr, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v16 }, nullptr, nullptr, nullptr, 0}, -{ "v17", nullptr, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v17 }, nullptr, nullptr, nullptr, 0}, -{ "v18", nullptr, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v18 }, nullptr, nullptr, nullptr, 0}, -{ "v19", nullptr, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v19 }, nullptr, nullptr, nullptr, 0}, -{ "v20", nullptr, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v20 }, nullptr, nullptr, nullptr, 0}, -{ "v21", nullptr, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v21 }, nullptr, nullptr, nullptr, 0}, -{ "v22", nullptr, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v22 }, nullptr, nullptr, nullptr, 0}, -{ "v23", nullptr, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v23 }, nullptr, nullptr, nullptr, 0}, -{ "v24", nullptr, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v24 }, nullptr, nullptr, nullptr, 0}, -{ "v25", nullptr, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v25 }, nullptr, nullptr, nullptr, 0}, -{ "v26", nullptr, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v26 }, nullptr, nullptr, nullptr, 0}, -{ "v27", nullptr, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v27 }, nullptr, nullptr, nullptr, 0}, -{ "v28", nullptr, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v28 }, nullptr, nullptr, nullptr, 0}, -{ "v29", nullptr, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v29 }, nullptr, nullptr, nullptr, 0}, -{ "v30", nullptr, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v30 }, nullptr, nullptr, nullptr, 0}, -{ "v31", nullptr, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v31 }, nullptr, nullptr, nullptr, 0}, + {"v0", + nullptr, + 16, + FPU_OFFSET(0), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v0}, + nullptr, + nullptr, + nullptr, + 0}, + {"v1", + nullptr, + 16, + FPU_OFFSET(1), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v1}, + nullptr, + nullptr, + nullptr, + 0}, + {"v2", + nullptr, + 16, + FPU_OFFSET(2), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v2}, + nullptr, + nullptr, + nullptr, + 0}, + {"v3", + nullptr, + 16, + FPU_OFFSET(3), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v3}, + nullptr, + nullptr, + nullptr, + 0}, + {"v4", + nullptr, + 16, + FPU_OFFSET(4), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v4}, + nullptr, + nullptr, + nullptr, + 0}, + {"v5", + nullptr, + 16, + FPU_OFFSET(5), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v5}, + nullptr, + nullptr, + nullptr, + 0}, + {"v6", + nullptr, + 16, + FPU_OFFSET(6), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v6}, + nullptr, + nullptr, + nullptr, + 0}, + {"v7", + nullptr, + 16, + FPU_OFFSET(7), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v7}, + nullptr, + nullptr, + nullptr, + 0}, + {"v8", + nullptr, + 16, + FPU_OFFSET(8), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v8}, + nullptr, + nullptr, + nullptr, + 0}, + {"v9", + nullptr, + 16, + FPU_OFFSET(9), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v9}, + nullptr, + nullptr, + nullptr, + 0}, + {"v10", + nullptr, + 16, + FPU_OFFSET(10), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v10}, + nullptr, + nullptr, + nullptr, + 0}, + {"v11", + nullptr, + 16, + FPU_OFFSET(11), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v11}, + nullptr, + nullptr, + nullptr, + 0}, + {"v12", + nullptr, + 16, + FPU_OFFSET(12), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v12}, + nullptr, + nullptr, + nullptr, + 0}, + {"v13", + nullptr, + 16, + FPU_OFFSET(13), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v13}, + nullptr, + nullptr, + nullptr, + 0}, + {"v14", + nullptr, + 16, + FPU_OFFSET(14), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v14}, + nullptr, + nullptr, + nullptr, + 0}, + {"v15", + nullptr, + 16, + FPU_OFFSET(15), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v15}, + nullptr, + nullptr, + nullptr, + 0}, + {"v16", + nullptr, + 16, + FPU_OFFSET(16), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v16}, + nullptr, + nullptr, + nullptr, + 0}, + {"v17", + nullptr, + 16, + FPU_OFFSET(17), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v17}, + nullptr, + nullptr, + nullptr, + 0}, + {"v18", + nullptr, + 16, + FPU_OFFSET(18), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v18}, + nullptr, + nullptr, + nullptr, + 0}, + {"v19", + nullptr, + 16, + FPU_OFFSET(19), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v19}, + nullptr, + nullptr, + nullptr, + 0}, + {"v20", + nullptr, + 16, + FPU_OFFSET(20), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v20}, + nullptr, + nullptr, + nullptr, + 0}, + {"v21", + nullptr, + 16, + FPU_OFFSET(21), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v21}, + nullptr, + nullptr, + nullptr, + 0}, + {"v22", + nullptr, + 16, + FPU_OFFSET(22), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v22}, + nullptr, + nullptr, + nullptr, + 0}, + {"v23", + nullptr, + 16, + FPU_OFFSET(23), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v23}, + nullptr, + nullptr, + nullptr, + 0}, + {"v24", + nullptr, + 16, + FPU_OFFSET(24), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v24}, + nullptr, + nullptr, + nullptr, + 0}, + {"v25", + nullptr, + 16, + FPU_OFFSET(25), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v25}, + nullptr, + nullptr, + nullptr, + 0}, + {"v26", + nullptr, + 16, + FPU_OFFSET(26), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v26}, + nullptr, + nullptr, + nullptr, + 0}, + {"v27", + nullptr, + 16, + FPU_OFFSET(27), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v27}, + nullptr, + nullptr, + nullptr, + 0}, + {"v28", + nullptr, + 16, + FPU_OFFSET(28), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v28}, + nullptr, + nullptr, + nullptr, + 0}, + {"v29", + nullptr, + 16, + FPU_OFFSET(29), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v29}, + nullptr, + nullptr, + nullptr, + 0}, + {"v30", + nullptr, + 16, + FPU_OFFSET(30), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v30}, + nullptr, + nullptr, + nullptr, + 0}, + {"v31", + nullptr, + 16, + FPU_OFFSET(31), + lldb::eEncodingVector, + lldb::eFormatVectorOfUInt8, + {LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_v31}, + nullptr, + nullptr, + nullptr, + 0}, -{ "fpsr", nullptr, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, nullptr, nullptr, nullptr, 0}, -{ "fpcr", nullptr, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, nullptr, nullptr, nullptr, 0}, + {"fpsr", + nullptr, + 4, + FPU_OFFSET_NAME(fpsr), + lldb::eEncodingUint, + lldb::eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fpsr}, + nullptr, + nullptr, + nullptr, + 0}, + {"fpcr", + nullptr, + 4, + FPU_OFFSET_NAME(fpcr), + lldb::eEncodingUint, + lldb::eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, fpu_fpcr}, + nullptr, + nullptr, + nullptr, + 0}, -{ "far", nullptr, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr, nullptr, 0}, -{ "esr", nullptr, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, nullptr, nullptr, nullptr, 0}, -{ "exception",nullptr, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr, nullptr, 0}, + {"far", + nullptr, + 8, + EXC_OFFSET_NAME(far), + lldb::eEncodingUint, + lldb::eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_far}, + nullptr, + nullptr, + nullptr, + 0}, + {"esr", + nullptr, + 4, + EXC_OFFSET_NAME(esr), + lldb::eEncodingUint, + lldb::eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_esr}, + nullptr, + nullptr, + nullptr, + 0}, + {"exception", + nullptr, + 4, + EXC_OFFSET_NAME(exception), + lldb::eEncodingUint, + lldb::eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, exc_exception}, + nullptr, + nullptr, + nullptr, + 0}, -{ DEFINE_DBG (bvr, 0) }, -{ DEFINE_DBG (bvr, 1) }, -{ DEFINE_DBG (bvr, 2) }, -{ DEFINE_DBG (bvr, 3) }, -{ DEFINE_DBG (bvr, 4) }, -{ DEFINE_DBG (bvr, 5) }, -{ DEFINE_DBG (bvr, 6) }, -{ DEFINE_DBG (bvr, 7) }, -{ DEFINE_DBG (bvr, 8) }, -{ DEFINE_DBG (bvr, 9) }, -{ DEFINE_DBG (bvr, 10) }, -{ DEFINE_DBG (bvr, 11) }, -{ DEFINE_DBG (bvr, 12) }, -{ DEFINE_DBG (bvr, 13) }, -{ DEFINE_DBG (bvr, 14) }, -{ DEFINE_DBG (bvr, 15) }, + {DEFINE_DBG(bvr, 0)}, + {DEFINE_DBG(bvr, 1)}, + {DEFINE_DBG(bvr, 2)}, + {DEFINE_DBG(bvr, 3)}, + {DEFINE_DBG(bvr, 4)}, + {DEFINE_DBG(bvr, 5)}, + {DEFINE_DBG(bvr, 6)}, + {DEFINE_DBG(bvr, 7)}, + {DEFINE_DBG(bvr, 8)}, + {DEFINE_DBG(bvr, 9)}, + {DEFINE_DBG(bvr, 10)}, + {DEFINE_DBG(bvr, 11)}, + {DEFINE_DBG(bvr, 12)}, + {DEFINE_DBG(bvr, 13)}, + {DEFINE_DBG(bvr, 14)}, + {DEFINE_DBG(bvr, 15)}, -{ DEFINE_DBG (bcr, 0) }, -{ DEFINE_DBG (bcr, 1) }, -{ DEFINE_DBG (bcr, 2) }, -{ DEFINE_DBG (bcr, 3) }, -{ DEFINE_DBG (bcr, 4) }, -{ DEFINE_DBG (bcr, 5) }, -{ DEFINE_DBG (bcr, 6) }, -{ DEFINE_DBG (bcr, 7) }, -{ DEFINE_DBG (bcr, 8) }, -{ DEFINE_DBG (bcr, 9) }, -{ DEFINE_DBG (bcr, 10) }, -{ DEFINE_DBG (bcr, 11) }, -{ DEFINE_DBG (bcr, 12) }, -{ DEFINE_DBG (bcr, 13) }, -{ DEFINE_DBG (bcr, 14) }, -{ DEFINE_DBG (bcr, 15) }, + {DEFINE_DBG(bcr, 0)}, + {DEFINE_DBG(bcr, 1)}, + {DEFINE_DBG(bcr, 2)}, + {DEFINE_DBG(bcr, 3)}, + {DEFINE_DBG(bcr, 4)}, + {DEFINE_DBG(bcr, 5)}, + {DEFINE_DBG(bcr, 6)}, + {DEFINE_DBG(bcr, 7)}, + {DEFINE_DBG(bcr, 8)}, + {DEFINE_DBG(bcr, 9)}, + {DEFINE_DBG(bcr, 10)}, + {DEFINE_DBG(bcr, 11)}, + {DEFINE_DBG(bcr, 12)}, + {DEFINE_DBG(bcr, 13)}, + {DEFINE_DBG(bcr, 14)}, + {DEFINE_DBG(bcr, 15)}, -{ DEFINE_DBG (wvr, 0) }, -{ DEFINE_DBG (wvr, 1) }, -{ DEFINE_DBG (wvr, 2) }, -{ DEFINE_DBG (wvr, 3) }, -{ DEFINE_DBG (wvr, 4) }, -{ DEFINE_DBG (wvr, 5) }, -{ DEFINE_DBG (wvr, 6) }, -{ DEFINE_DBG (wvr, 7) }, -{ DEFINE_DBG (wvr, 8) }, -{ DEFINE_DBG (wvr, 9) }, -{ DEFINE_DBG (wvr, 10) }, -{ DEFINE_DBG (wvr, 11) }, -{ DEFINE_DBG (wvr, 12) }, -{ DEFINE_DBG (wvr, 13) }, -{ DEFINE_DBG (wvr, 14) }, -{ DEFINE_DBG (wvr, 15) }, + {DEFINE_DBG(wvr, 0)}, + {DEFINE_DBG(wvr, 1)}, + {DEFINE_DBG(wvr, 2)}, + {DEFINE_DBG(wvr, 3)}, + {DEFINE_DBG(wvr, 4)}, + {DEFINE_DBG(wvr, 5)}, + {DEFINE_DBG(wvr, 6)}, + {DEFINE_DBG(wvr, 7)}, + {DEFINE_DBG(wvr, 8)}, + {DEFINE_DBG(wvr, 9)}, + {DEFINE_DBG(wvr, 10)}, + {DEFINE_DBG(wvr, 11)}, + {DEFINE_DBG(wvr, 12)}, + {DEFINE_DBG(wvr, 13)}, + {DEFINE_DBG(wvr, 14)}, + {DEFINE_DBG(wvr, 15)}, -{ DEFINE_DBG (wcr, 0) }, -{ DEFINE_DBG (wcr, 1) }, -{ DEFINE_DBG (wcr, 2) }, -{ DEFINE_DBG (wcr, 3) }, -{ DEFINE_DBG (wcr, 4) }, -{ DEFINE_DBG (wcr, 5) }, -{ DEFINE_DBG (wcr, 6) }, -{ DEFINE_DBG (wcr, 7) }, -{ DEFINE_DBG (wcr, 8) }, -{ DEFINE_DBG (wcr, 9) }, -{ DEFINE_DBG (wcr, 10) }, -{ DEFINE_DBG (wcr, 11) }, -{ DEFINE_DBG (wcr, 12) }, -{ DEFINE_DBG (wcr, 13) }, -{ DEFINE_DBG (wcr, 14) }, -{ DEFINE_DBG (wcr, 15) } -}; + {DEFINE_DBG(wcr, 0)}, + {DEFINE_DBG(wcr, 1)}, + {DEFINE_DBG(wcr, 2)}, + {DEFINE_DBG(wcr, 3)}, + {DEFINE_DBG(wcr, 4)}, + {DEFINE_DBG(wcr, 5)}, + {DEFINE_DBG(wcr, 6)}, + {DEFINE_DBG(wcr, 7)}, + {DEFINE_DBG(wcr, 8)}, + {DEFINE_DBG(wcr, 9)}, + {DEFINE_DBG(wcr, 10)}, + {DEFINE_DBG(wcr, 11)}, + {DEFINE_DBG(wcr, 12)}, + {DEFINE_DBG(wcr, 13)}, + {DEFINE_DBG(wcr, 14)}, + {DEFINE_DBG(wcr, 15)}}; #endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h index a94b790b680..1b3dad8a22a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -19,29 +19,28 @@ #ifdef DECLARE_REGISTER_INFOS_I386_STRUCT // Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(GPR, regname)) +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) // Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR_i386, regname)) +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR_i386, regname)) // Computes the offset of the YMM register assembled from register halves. // Based on DNBArchImplI386.cpp from debugserver -#define YMM_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(FXSAVE, xmm[7]) + \ - sizeof(XMMReg) + (32 * reg_index)) +#define YMM_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, xmm[7]) + sizeof(XMMReg) + \ + (32 * reg_index)) // Number of bytes needed to represent a FPR. #if !defined(FPR_SIZE) -#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) +#define FPR_SIZE(reg) sizeof(((FXSAVE *)NULL)->reg) #endif // Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) +#define FP_SIZE sizeof(((MMSReg *)NULL)->bytes) // Number of bytes needed to represent an XMM register. #define XMM_SIZE sizeof(XMMReg) @@ -50,157 +49,200 @@ #define YMM_SIZE sizeof(YMMReg) // Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, NULL, NULL, NULL, 0} +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR *) NULL)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##reg##_i386 }, \ + NULL, NULL, NULL, 0 \ + } -#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ - { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_i386 }, NULL, NULL, NULL, 0} +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { \ + #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##name##_i386 }, \ + NULL, NULL, NULL, 0 \ + } // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB -#define DEFINE_FP_ST(reg, i) \ - { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_i386 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_FP_MM(reg, i) \ - { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingUint, eFormatHex, \ - { ehframe_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_i386 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { ehframe_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386}, \ - NULL, NULL, NULL, 0} - -// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size. -#define DEFINE_YMM(reg, i) \ - { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_DR(reg, i) \ - { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \ - { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL, NULL, 0} - -#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ - { #reg16, NULL, 2, GPR_OFFSET(reg32), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0} -#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ - { #reg8, NULL, 1, GPR_OFFSET(reg32)+1, eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0} -#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ - { #reg8, NULL, 1, GPR_OFFSET(reg32), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0} - -static RegisterInfo -g_register_infos_i386[] = -{ +#define DEFINE_FP_ST(reg, i) \ + { \ + #reg #i, NULL, FP_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_st##i##_i386 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FP_MM(reg, i) \ + { \ + #reg #i, NULL, sizeof(uint64_t), \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingUint, eFormatHex, \ + {ehframe_mm##i##_i386, dwarf_mm##i##_i386, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_mm##i##_i386 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_XMM(reg, i) \ + { \ + #reg #i, NULL, XMM_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {ehframe_##reg##i##_i386, dwarf_##reg##i##_i386, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \ + NULL, NULL, NULL, 0 \ + } + +// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then +// differentiate based on register size. +#define DEFINE_YMM(reg, i) \ + { \ + #reg #i, NULL, YMM_SIZE, \ + LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8, \ + {LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg##i##_i386 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_DR(reg, i) \ + { \ + #reg #i, NULL, DR_SIZE, \ + DR_OFFSET(i), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ + { \ + #reg16, NULL, 2, \ + GPR_OFFSET(reg32), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg16##_i386 }, \ + RegisterContextPOSIX_x86::g_contained_##reg32, \ + RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0 \ + } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ + { \ + #reg8, NULL, 1, \ + GPR_OFFSET(reg32) + 1, eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_i386 }, \ + RegisterContextPOSIX_x86::g_contained_##reg32, \ + RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0 \ + } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ + { \ + #reg8, NULL, 1, \ + GPR_OFFSET(reg32), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_i386 }, \ + RegisterContextPOSIX_x86::g_contained_##reg32, \ + RegisterContextPOSIX_x86::g_invalidate_##reg32, NULL, 0 \ + } + +static RegisterInfo g_register_infos_i386[] = { // General purpose registers. - DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - DEFINE_GPR_PSEUDO_16(ax, eax), - DEFINE_GPR_PSEUDO_16(bx, ebx), - DEFINE_GPR_PSEUDO_16(cx, ecx), - DEFINE_GPR_PSEUDO_16(dx, edx), - DEFINE_GPR_PSEUDO_16(di, edi), - DEFINE_GPR_PSEUDO_16(si, esi), - DEFINE_GPR_PSEUDO_16(bp, ebp), - DEFINE_GPR_PSEUDO_16(sp, esp), - DEFINE_GPR_PSEUDO_8H(ah, eax), - DEFINE_GPR_PSEUDO_8H(bh, ebx), - DEFINE_GPR_PSEUDO_8H(ch, ecx), - DEFINE_GPR_PSEUDO_8H(dh, edx), - DEFINE_GPR_PSEUDO_8L(al, eax), - DEFINE_GPR_PSEUDO_8L(bl, ebx), - DEFINE_GPR_PSEUDO_8L(cl, ecx), - DEFINE_GPR_PSEUDO_8L(dl, edx), + DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, + LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + DEFINE_GPR_PSEUDO_16(ax, eax), DEFINE_GPR_PSEUDO_16(bx, ebx), + DEFINE_GPR_PSEUDO_16(cx, ecx), DEFINE_GPR_PSEUDO_16(dx, edx), + DEFINE_GPR_PSEUDO_16(di, edi), DEFINE_GPR_PSEUDO_16(si, esi), + DEFINE_GPR_PSEUDO_16(bp, ebp), DEFINE_GPR_PSEUDO_16(sp, esp), + DEFINE_GPR_PSEUDO_8H(ah, eax), DEFINE_GPR_PSEUDO_8H(bh, ebx), + DEFINE_GPR_PSEUDO_8H(ch, ecx), DEFINE_GPR_PSEUDO_8H(dh, edx), + DEFINE_GPR_PSEUDO_8L(al, eax), DEFINE_GPR_PSEUDO_8L(bl, ebx), + DEFINE_GPR_PSEUDO_8L(cl, ecx), DEFINE_GPR_PSEUDO_8L(dl, edx), // i387 Floating point registers. - DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), // FP registers. - DEFINE_FP_ST(st, 0), - DEFINE_FP_ST(st, 1), - DEFINE_FP_ST(st, 2), - DEFINE_FP_ST(st, 3), - DEFINE_FP_ST(st, 4), - DEFINE_FP_ST(st, 5), - DEFINE_FP_ST(st, 6), - DEFINE_FP_ST(st, 7), - DEFINE_FP_MM(mm, 0), - DEFINE_FP_MM(mm, 1), - DEFINE_FP_MM(mm, 2), - DEFINE_FP_MM(mm, 3), - DEFINE_FP_MM(mm, 4), - DEFINE_FP_MM(mm, 5), - DEFINE_FP_MM(mm, 6), + DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7), DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), DEFINE_FP_MM(mm, 2), DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), DEFINE_FP_MM(mm, 5), DEFINE_FP_MM(mm, 6), DEFINE_FP_MM(mm, 7), // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), + DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), // Copy of YMM registers assembled from xmm and ymmh - DEFINE_YMM(ymm, 0), - DEFINE_YMM(ymm, 1), - DEFINE_YMM(ymm, 2), - DEFINE_YMM(ymm, 3), - DEFINE_YMM(ymm, 4), - DEFINE_YMM(ymm, 5), - DEFINE_YMM(ymm, 6), - DEFINE_YMM(ymm, 7), + DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), // Debug registers for lldb internal use - DEFINE_DR(dr, 0), - DEFINE_DR(dr, 1), - DEFINE_DR(dr, 2), - DEFINE_DR(dr, 3), - DEFINE_DR(dr, 4), - DEFINE_DR(dr, 5), - DEFINE_DR(dr, 6), - DEFINE_DR(dr, 7) -}; - -static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386, - "g_register_infos_x86_64 has wrong number of register infos"); + DEFINE_DR(dr, 0), DEFINE_DR(dr, 1), DEFINE_DR(dr, 2), DEFINE_DR(dr, 3), + DEFINE_DR(dr, 4), DEFINE_DR(dr, 5), DEFINE_DR(dr, 6), DEFINE_DR(dr, 7)}; + +static_assert((sizeof(g_register_infos_i386) / + sizeof(g_register_infos_i386[0])) == k_num_registers_i386, + "g_register_infos_x86_64 has wrong number of register infos"); #undef GPR_OFFSET #undef FPR_OFFSET diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h index 5852d799aa9..82f7c0012e5 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h @@ -12,175 +12,309 @@ // C++ Includes // Other libraries and framework includes -#include "llvm/Support/Compiler.h" #include "lldb/Core/dwarf.h" +#include "llvm/Support/Compiler.h" // Project includes #ifdef DECLARE_REGISTER_INFOS_MIPS_STRUCT // Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, gpr) + \ - LLVM_EXTENSION offsetof(GPR_linux_mips, regname)) +#define GPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, gpr) + \ + LLVM_EXTENSION offsetof(GPR_linux_mips, regname)) // Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR_linux_mips, regname)) +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR_linux_mips, regname)) // Computes the offset of the given MSA in the extended data area. -#define MSA_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, msa) + \ - LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) +#define MSA_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, msa) + \ + LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) // Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR_linux_mips*)NULL)->reg) / 2, GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips }, NULL, NULL, NULL, 0} +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR_linux_mips *) NULL)->reg) / 2, \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + gpr_##reg##_mips }, \ + NULL, NULL, NULL, 0 \ + } -const uint8_t dwarf_opcode_mips [] = { - llvm::dwarf::DW_OP_regx, dwarf_sr_mips, llvm::dwarf::DW_OP_lit1, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr - }; +const uint8_t dwarf_opcode_mips[] = { + llvm::dwarf::DW_OP_regx, dwarf_sr_mips, llvm::dwarf::DW_OP_lit1, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr}; -#define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ - eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL, dwarf_opcode_mips, sizeof(dwarf_opcode_mips)} +#define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((FPR_linux_mips *) NULL)->reg), \ + FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \ + {kind1, kind2, kind3, kind4, \ + fpr_##reg##_mips }, \ + NULL, NULL, dwarf_opcode_mips, \ + sizeof(dwarf_opcode_mips) \ + } -#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL, NULL, 0} +#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((FPR_linux_mips *) NULL)->reg), \ + FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + fpr_##reg##_mips }, \ + NULL, NULL, NULL, 0 \ + } -#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingVector, \ - eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL, NULL, 0} +#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ + MSA_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt8, \ + {kind1, kind2, kind3, kind4, \ + msa_##reg##_mips }, \ + NULL, NULL, NULL, 0 \ + } -#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL, NULL, 0} +#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ + MSA_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + msa_##reg##_mips }, \ + NULL, NULL, NULL, 0 \ + } // RegisterKind: EH_Frame, DWARF, Generic, Procss Plugin, LLDB -static RegisterInfo -g_register_infos_mips[] = -{ - DEFINE_GPR (zero, "zero", dwarf_zero_mips, dwarf_zero_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r1, "at", dwarf_r1_mips, dwarf_r1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r2, nullptr, dwarf_r2_mips, dwarf_r2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r3, nullptr, dwarf_r3_mips, dwarf_r3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r4, nullptr, dwarf_r4_mips, dwarf_r4_mips, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR (r5, nullptr, dwarf_r5_mips, dwarf_r5_mips, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR (r6, nullptr, dwarf_r6_mips, dwarf_r6_mips, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR (r7, nullptr, dwarf_r7_mips, dwarf_r7_mips, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR (r8, nullptr, dwarf_r8_mips, dwarf_r8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r9, nullptr, dwarf_r9_mips, dwarf_r9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r10, nullptr, dwarf_r10_mips, dwarf_r10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r11, nullptr, dwarf_r11_mips, dwarf_r11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r12, nullptr, dwarf_r12_mips, dwarf_r12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r13, nullptr, dwarf_r13_mips, dwarf_r13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r14, nullptr, dwarf_r14_mips, dwarf_r14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r15, nullptr, dwarf_r15_mips, dwarf_r15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r16, nullptr, dwarf_r16_mips, dwarf_r16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r17, nullptr, dwarf_r17_mips, dwarf_r17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r18, nullptr, dwarf_r18_mips, dwarf_r18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r19, nullptr, dwarf_r19_mips, dwarf_r19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r20, nullptr, dwarf_r20_mips, dwarf_r20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r21, nullptr, dwarf_r21_mips, dwarf_r21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r22, nullptr, dwarf_r22_mips, dwarf_r22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r23, nullptr, dwarf_r23_mips, dwarf_r23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r24, nullptr, dwarf_r24_mips, dwarf_r24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r25, nullptr, dwarf_r25_mips, dwarf_r25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r26, nullptr, dwarf_r26_mips, dwarf_r26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (r27, nullptr, dwarf_r27_mips, dwarf_r27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (gp, "gp", dwarf_gp_mips, dwarf_gp_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (sp, "sp", dwarf_sp_mips, dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR (r30, "fp", dwarf_r30_mips, dwarf_r30_mips, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR (ra, "ra", dwarf_ra_mips, dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), - DEFINE_GPR (sr, "status", dwarf_sr_mips, dwarf_sr_mips, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR (mullo, nullptr, dwarf_lo_mips, dwarf_lo_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (mulhi, nullptr, dwarf_hi_mips, dwarf_hi_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (badvaddr, nullptr, dwarf_bad_mips, dwarf_bad_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (cause, nullptr, dwarf_cause_mips, dwarf_cause_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR (pc, nullptr, dwarf_pc_mips, dwarf_pc_mips, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f0, nullptr, dwarf_f0_mips, dwarf_f0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f1, nullptr, dwarf_f1_mips, dwarf_f1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f2, nullptr, dwarf_f2_mips, dwarf_f2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f3, nullptr, dwarf_f3_mips, dwarf_f3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f4, nullptr, dwarf_f4_mips, dwarf_f4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f5, nullptr, dwarf_f5_mips, dwarf_f5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f6, nullptr, dwarf_f6_mips, dwarf_f6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f7, nullptr, dwarf_f7_mips, dwarf_f7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f8, nullptr, dwarf_f8_mips, dwarf_f8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f9, nullptr, dwarf_f9_mips, dwarf_f9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f10, nullptr, dwarf_f10_mips, dwarf_f10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f11, nullptr, dwarf_f11_mips, dwarf_f11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f12, nullptr, dwarf_f12_mips, dwarf_f12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f13, nullptr, dwarf_f13_mips, dwarf_f13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f14, nullptr, dwarf_f14_mips, dwarf_f14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f15, nullptr, dwarf_f15_mips, dwarf_f15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f16, nullptr, dwarf_f16_mips, dwarf_f16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f17, nullptr, dwarf_f17_mips, dwarf_f17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f18, nullptr, dwarf_f18_mips, dwarf_f18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f19, nullptr, dwarf_f19_mips, dwarf_f19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f20, nullptr, dwarf_f20_mips, dwarf_f20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f21, nullptr, dwarf_f21_mips, dwarf_f21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f22, nullptr, dwarf_f22_mips, dwarf_f22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f23, nullptr, dwarf_f23_mips, dwarf_f23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f24, nullptr, dwarf_f24_mips, dwarf_f24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f25, nullptr, dwarf_f25_mips, dwarf_f25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f26, nullptr, dwarf_f26_mips, dwarf_f26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f27, nullptr, dwarf_f27_mips, dwarf_f27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f28, nullptr, dwarf_f28_mips, dwarf_f28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f29, nullptr, dwarf_f29_mips, dwarf_f29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f30, nullptr, dwarf_f30_mips, dwarf_f30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f31, nullptr, dwarf_f31_mips, dwarf_f31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w0, nullptr, dwarf_w0_mips, dwarf_w0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w1, nullptr, dwarf_w1_mips, dwarf_w1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w2, nullptr, dwarf_w2_mips, dwarf_w2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w3, nullptr, dwarf_w3_mips, dwarf_w3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w4, nullptr, dwarf_w4_mips, dwarf_w4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w5, nullptr, dwarf_w5_mips, dwarf_w5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w6, nullptr, dwarf_w6_mips, dwarf_w6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w7, nullptr, dwarf_w7_mips, dwarf_w7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w8, nullptr, dwarf_w8_mips, dwarf_w8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w9, nullptr, dwarf_w9_mips, dwarf_w9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w10, nullptr, dwarf_w10_mips, dwarf_w10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w11, nullptr, dwarf_w11_mips, dwarf_w11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w12, nullptr, dwarf_w12_mips, dwarf_w12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w13, nullptr, dwarf_w13_mips, dwarf_w13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w14, nullptr, dwarf_w14_mips, dwarf_w14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w15, nullptr, dwarf_w15_mips, dwarf_w15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w16, nullptr, dwarf_w16_mips, dwarf_w16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w17, nullptr, dwarf_w17_mips, dwarf_w17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w18, nullptr, dwarf_w18_mips, dwarf_w18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w19, nullptr, dwarf_w19_mips, dwarf_w19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w20, nullptr, dwarf_w10_mips, dwarf_w20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w21, nullptr, dwarf_w21_mips, dwarf_w21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w22, nullptr, dwarf_w22_mips, dwarf_w22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w23, nullptr, dwarf_w23_mips, dwarf_w23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w24, nullptr, dwarf_w24_mips, dwarf_w24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w25, nullptr, dwarf_w25_mips, dwarf_w25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w26, nullptr, dwarf_w26_mips, dwarf_w26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w27, nullptr, dwarf_w27_mips, dwarf_w27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w28, nullptr, dwarf_w28_mips, dwarf_w28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w29, nullptr, dwarf_w29_mips, dwarf_w29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w30, nullptr, dwarf_w30_mips, dwarf_w30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w31, nullptr, dwarf_w31_mips, dwarf_w31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips, dwarf_mcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips, dwarf_mir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM) -}; - -static_assert((sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])) == k_num_registers_mips, - "g_register_infos_mips has wrong number of register infos"); +static RegisterInfo g_register_infos_mips[] = { + DEFINE_GPR(zero, "zero", dwarf_zero_mips, dwarf_zero_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, "at", dwarf_r1_mips, dwarf_r1_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, nullptr, dwarf_r2_mips, dwarf_r2_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, nullptr, dwarf_r3_mips, dwarf_r3_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, nullptr, dwarf_r4_mips, dwarf_r4_mips, + LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, nullptr, dwarf_r5_mips, dwarf_r5_mips, + LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, nullptr, dwarf_r6_mips, dwarf_r6_mips, + LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, nullptr, dwarf_r7_mips, dwarf_r7_mips, + LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, nullptr, dwarf_r8_mips, dwarf_r8_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, nullptr, dwarf_r9_mips, dwarf_r9_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_mips, dwarf_r10_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_mips, dwarf_r11_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_mips, dwarf_r12_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_mips, dwarf_r13_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_mips, dwarf_r14_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_mips, dwarf_r15_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, nullptr, dwarf_r16_mips, dwarf_r16_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, nullptr, dwarf_r17_mips, dwarf_r17_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, nullptr, dwarf_r18_mips, dwarf_r18_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, nullptr, dwarf_r19_mips, dwarf_r19_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, nullptr, dwarf_r20_mips, dwarf_r20_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, nullptr, dwarf_r21_mips, dwarf_r21_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, nullptr, dwarf_r22_mips, dwarf_r22_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, nullptr, dwarf_r23_mips, dwarf_r23_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, nullptr, dwarf_r24_mips, dwarf_r24_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, nullptr, dwarf_r25_mips, dwarf_r25_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, nullptr, dwarf_r26_mips, dwarf_r26_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, nullptr, dwarf_r27_mips, dwarf_r27_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gp, "gp", dwarf_gp_mips, dwarf_gp_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(sp, "sp", dwarf_sp_mips, dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, "fp", dwarf_r30_mips, dwarf_r30_mips, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(ra, "ra", dwarf_ra_mips, dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, + LLDB_INVALID_REGNUM), + DEFINE_GPR(sr, "status", dwarf_sr_mips, dwarf_sr_mips, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(mullo, nullptr, dwarf_lo_mips, dwarf_lo_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips, dwarf_hi_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips, dwarf_bad_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(cause, nullptr, dwarf_cause_mips, dwarf_cause_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, nullptr, dwarf_pc_mips, dwarf_pc_mips, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f0, nullptr, dwarf_f0_mips, dwarf_f0_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f1, nullptr, dwarf_f1_mips, dwarf_f1_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f2, nullptr, dwarf_f2_mips, dwarf_f2_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f3, nullptr, dwarf_f3_mips, dwarf_f3_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f4, nullptr, dwarf_f4_mips, dwarf_f4_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f5, nullptr, dwarf_f5_mips, dwarf_f5_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f6, nullptr, dwarf_f6_mips, dwarf_f6_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f7, nullptr, dwarf_f7_mips, dwarf_f7_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f8, nullptr, dwarf_f8_mips, dwarf_f8_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f9, nullptr, dwarf_f9_mips, dwarf_f9_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f10, nullptr, dwarf_f10_mips, dwarf_f10_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f11, nullptr, dwarf_f11_mips, dwarf_f11_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f12, nullptr, dwarf_f12_mips, dwarf_f12_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f13, nullptr, dwarf_f13_mips, dwarf_f13_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f14, nullptr, dwarf_f14_mips, dwarf_f14_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f15, nullptr, dwarf_f15_mips, dwarf_f15_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f16, nullptr, dwarf_f16_mips, dwarf_f16_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f17, nullptr, dwarf_f17_mips, dwarf_f17_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f18, nullptr, dwarf_f18_mips, dwarf_f18_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f19, nullptr, dwarf_f19_mips, dwarf_f19_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f20, nullptr, dwarf_f20_mips, dwarf_f20_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f21, nullptr, dwarf_f21_mips, dwarf_f21_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f22, nullptr, dwarf_f22_mips, dwarf_f22_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f23, nullptr, dwarf_f23_mips, dwarf_f23_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f24, nullptr, dwarf_f24_mips, dwarf_f24_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f25, nullptr, dwarf_f25_mips, dwarf_f25_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f26, nullptr, dwarf_f26_mips, dwarf_f26_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f27, nullptr, dwarf_f27_mips, dwarf_f27_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f28, nullptr, dwarf_f28_mips, dwarf_f28_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f29, nullptr, dwarf_f29_mips, dwarf_f29_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f30, nullptr, dwarf_f30_mips, dwarf_f30_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f31, nullptr, dwarf_f31_mips, dwarf_f31_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w0, nullptr, dwarf_w0_mips, dwarf_w0_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w1, nullptr, dwarf_w1_mips, dwarf_w1_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w2, nullptr, dwarf_w2_mips, dwarf_w2_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w3, nullptr, dwarf_w3_mips, dwarf_w3_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w4, nullptr, dwarf_w4_mips, dwarf_w4_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w5, nullptr, dwarf_w5_mips, dwarf_w5_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w6, nullptr, dwarf_w6_mips, dwarf_w6_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w7, nullptr, dwarf_w7_mips, dwarf_w7_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w8, nullptr, dwarf_w8_mips, dwarf_w8_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w9, nullptr, dwarf_w9_mips, dwarf_w9_mips, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w10, nullptr, dwarf_w10_mips, dwarf_w10_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w11, nullptr, dwarf_w11_mips, dwarf_w11_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w12, nullptr, dwarf_w12_mips, dwarf_w12_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w13, nullptr, dwarf_w13_mips, dwarf_w13_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w14, nullptr, dwarf_w14_mips, dwarf_w14_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w15, nullptr, dwarf_w15_mips, dwarf_w15_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w16, nullptr, dwarf_w16_mips, dwarf_w16_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w17, nullptr, dwarf_w17_mips, dwarf_w17_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w18, nullptr, dwarf_w18_mips, dwarf_w18_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w19, nullptr, dwarf_w19_mips, dwarf_w19_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w20, nullptr, dwarf_w10_mips, dwarf_w20_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w21, nullptr, dwarf_w21_mips, dwarf_w21_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w22, nullptr, dwarf_w22_mips, dwarf_w22_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w23, nullptr, dwarf_w23_mips, dwarf_w23_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w24, nullptr, dwarf_w24_mips, dwarf_w24_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w25, nullptr, dwarf_w25_mips, dwarf_w25_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w26, nullptr, dwarf_w26_mips, dwarf_w26_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w27, nullptr, dwarf_w27_mips, dwarf_w27_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w28, nullptr, dwarf_w28_mips, dwarf_w28_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w29, nullptr, dwarf_w29_mips, dwarf_w29_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w30, nullptr, dwarf_w30_mips, dwarf_w30_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w31, nullptr, dwarf_w31_mips, dwarf_w31_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(mcsr, nullptr, dwarf_mcsr_mips, dwarf_mcsr_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(mir, nullptr, dwarf_mir_mips, dwarf_mir_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM)}; + +static_assert((sizeof(g_register_infos_mips) / + sizeof(g_register_infos_mips[0])) == k_num_registers_mips, + "g_register_infos_mips has wrong number of register infos"); #undef GPR_OFFSET #undef FPR_OFFSET diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h index c0691b75410..f972920c847 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h @@ -12,8 +12,8 @@ // C++ Includes // Other libraries and framework includes -#include "llvm/Support/Compiler.h" #include "lldb/Core/dwarf.h" +#include "llvm/Support/Compiler.h" // Project includes @@ -21,226 +21,413 @@ // Computes the offset of the given GPR in the user data area. #ifdef LINUX_MIPS64 - #define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, gpr) + \ - LLVM_EXTENSION offsetof(GPR_linux_mips, regname)) +#define GPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, gpr) + \ + LLVM_EXTENSION offsetof(GPR_linux_mips, regname)) #else - #define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(GPR_freebsd_mips, regname)) +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR_freebsd_mips, regname)) #endif // Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR_linux_mips, regname)) +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR_linux_mips, regname)) // Computes the offset of the given MSA in the extended data area. -#define MSA_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, msa) + \ - LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) +#define MSA_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, msa) + \ + LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB // Note that the size and offset will be updated by platform-specific classes. #ifdef LINUX_MIPS64 - #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR_linux_mips*)0)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + gpr_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } #else - #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR_freebsd_mips*)0)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR_freebsd_mips *) 0)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + gpr_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } #endif -#define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR_linux_mips*)0)->reg) / 2, GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} - -const uint8_t dwarf_opcode_mips64 [] = { - llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr - }; +#define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg) / 2, \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + gpr_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } +const uint8_t dwarf_opcode_mips64[] = { + llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr}; -#define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ - eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL, dwarf_opcode_mips64, sizeof(dwarf_opcode_mips64)} +#define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \ + FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \ + {kind1, kind2, kind3, kind4, \ + fpr_##reg##_mips64 }, \ + NULL, NULL, dwarf_opcode_mips64, \ + sizeof(dwarf_opcode_mips64) \ + } -#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL, NULL, 0} +#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \ + FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + fpr_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } -#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingVector, \ - eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL, NULL, 0} +#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ + MSA_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt8, \ + {kind1, kind2, kind3, kind4, \ + msa_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } -#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL, NULL, 0} +#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ + MSA_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + msa_##reg##_mips64 }, \ + NULL, NULL, NULL, 0 \ + } -static RegisterInfo -g_register_infos_mips64[] = -{ - // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin +static RegisterInfo g_register_infos_mips64[] = { +// General purpose registers. EH_Frame, DWARF, +// Generic, Process Plugin #ifndef LINUX_MIPS64 - DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), - DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), - DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), - DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), - DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), - DEFINE_GPR(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR(ic, nullptr, dwarf_ic_mips64, dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, + LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, + LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, + LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, + LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, + LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, + LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, + LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, + LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, + LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, + LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(ic, nullptr, dwarf_ic_mips64, dwarf_ic_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), #else - DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), - DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), - DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), - DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), - DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), - DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR (f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA (w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM) + DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, + LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, + LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, + LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, + LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, + LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, + LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, + LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, + LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, + LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, + LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64, + dwarf_config5_mips64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_FPR(f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO(config5, nullptr, dwarf_config5_mips64, + dwarf_config5_mips64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM), + DEFINE_MSA(w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA(w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_MSA_INFO(config5, nullptr, dwarf_config5_mips64, + dwarf_config5_mips64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM) #endif }; -static_assert((sizeof(g_register_infos_mips64) / sizeof(g_register_infos_mips64[0])) == k_num_registers_mips64, - "g_register_infos_mips64 has wrong number of register infos"); +static_assert((sizeof(g_register_infos_mips64) / + sizeof(g_register_infos_mips64[0])) == k_num_registers_mips64, + "g_register_infos_mips64 has wrong number of register infos"); #undef DEFINE_GPR #undef DEFINE_GPR_INFO diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index 3a254db019f..c0d47f0d991 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -10,170 +10,216 @@ #include <stddef.h> // Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(GPR, regname)) -#define FPR_OFFSET(regname) \ - (offsetof(FPR, regname)) -#define VMX_OFFSET(regname) \ - (offsetof(VMX, regname)) -#define GPR_SIZE(regname) \ - (sizeof(((GPR*)NULL)->regname)) +#define GPR_OFFSET(regname) (offsetof(GPR, regname)) +#define FPR_OFFSET(regname) (offsetof(FPR, regname)) +#define VMX_OFFSET(regname) (offsetof(VMX, regname)) +#define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname)) #ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT // Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, lldb_kind) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, gpr_##reg##_powerpc }, NULL, NULL, NULL, 0} -#define DEFINE_FPR(reg, lldb_kind) \ - { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ - eFormatFloat, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, fpr_##reg##_powerpc }, NULL, NULL, NULL, 0} -#define DEFINE_VMX(reg, lldb_kind) \ - { #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \ - eFormatVectorOfUInt32, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, vmx_##reg##_powerpc }, NULL, NULL, NULL, 0} +#define DEFINE_GPR(reg, alt, lldb_kind) \ + { \ + #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {dwarf_##reg##_powerpc, \ + dwarf_##reg##_powerpc, lldb_kind, \ + LLDB_INVALID_REGNUM, \ + gpr_##reg##_powerpc }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_FPR(reg, lldb_kind) \ + { \ + #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \ + {dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, \ + lldb_kind, LLDB_INVALID_REGNUM, \ + fpr_##reg##_powerpc }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_VMX(reg, lldb_kind) \ + { \ + #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt32, \ + {dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, \ + lldb_kind, LLDB_INVALID_REGNUM, \ + vmx_##reg##_powerpc }, \ + NULL, NULL, NULL, 0 \ + } - // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin -#define POWERPC_REGS \ - DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \ - DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r3, "arg1",LLDB_REGNUM_GENERIC_ARG1), \ - DEFINE_GPR(r4, "arg2",LLDB_REGNUM_GENERIC_ARG2), \ - DEFINE_GPR(r5, "arg3",LLDB_REGNUM_GENERIC_ARG3), \ - DEFINE_GPR(r6, "arg4",LLDB_REGNUM_GENERIC_ARG4), \ - DEFINE_GPR(r7, "arg5",LLDB_REGNUM_GENERIC_ARG5), \ - DEFINE_GPR(r8, "arg6",LLDB_REGNUM_GENERIC_ARG6), \ - DEFINE_GPR(r9, "arg7",LLDB_REGNUM_GENERIC_ARG7), \ - DEFINE_GPR(r10, "arg8",LLDB_REGNUM_GENERIC_ARG8), \ - DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \ - DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \ - DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \ - DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \ - DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \ - DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \ - DEFINE_FPR(f0, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f1, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f2, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f3, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f4, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f5, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f6, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f7, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f8, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f9, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f10, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f11, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f12, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f13, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f14, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f15, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f16, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f17, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f18, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f19, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f20, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f21, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f22, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f23, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f24, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f25, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f26, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f27, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f28, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ - DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ - { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { dwarf_fpscr_powerpc, dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_fpscr_powerpc }, NULL, NULL, NULL, 0 }, \ - DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v3, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v4, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v5, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v6, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v7, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v8, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v9, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v10, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v11, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v12, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v13, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v14, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v15, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v16, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v17, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v18, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v19, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v20, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v21, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v22, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v23, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v24, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v25, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v26, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v27, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v28, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \ - DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \ - { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { dwarf_vrsave_powerpc, dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vrsave_powerpc }, NULL, NULL, NULL, 0}, \ - { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { dwarf_vscr_powerpc, dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_powerpc }, NULL, NULL, NULL, 0}, +// General purpose registers. EH_Frame, DWARF, +// Generic, Process Plugin +#define POWERPC_REGS \ + DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM) \ + , DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \ + DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r3, "arg1", LLDB_REGNUM_GENERIC_ARG1), \ + DEFINE_GPR(r4, "arg2", LLDB_REGNUM_GENERIC_ARG2), \ + DEFINE_GPR(r5, "arg3", LLDB_REGNUM_GENERIC_ARG3), \ + DEFINE_GPR(r6, "arg4", LLDB_REGNUM_GENERIC_ARG4), \ + DEFINE_GPR(r7, "arg5", LLDB_REGNUM_GENERIC_ARG5), \ + DEFINE_GPR(r8, "arg6", LLDB_REGNUM_GENERIC_ARG6), \ + DEFINE_GPR(r9, "arg7", LLDB_REGNUM_GENERIC_ARG7), \ + DEFINE_GPR(r10, "arg8", LLDB_REGNUM_GENERIC_ARG8), \ + DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \ + DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \ + DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \ + DEFINE_FPR(f0, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f1, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f2, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f3, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f4, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f5, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f6, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f7, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f8, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f9, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f10, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f11, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f12, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f13, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f14, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f15, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f16, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f17, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f18, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f19, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f20, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f21, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f22, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f23, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f24, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f25, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f26, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f27, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f28, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ + {"fpscr", \ + NULL, \ + 8, \ + FPR_OFFSET(fpscr), \ + eEncodingUint, \ + eFormatHex, \ + {dwarf_fpscr_powerpc, dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpr_fpscr_powerpc}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \ + {"vrsave", \ + NULL, \ + 4, \ + VMX_OFFSET(vrsave), \ + eEncodingUint, \ + eFormatHex, \ + {dwarf_vrsave_powerpc, dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, vmx_vrsave_powerpc}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + {"vscr", \ + NULL, \ + 4, \ + VMX_OFFSET(vscr), \ + eEncodingUint, \ + eFormatHex, \ + {dwarf_vscr_powerpc, dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, vmx_vscr_powerpc}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, -static RegisterInfo -g_register_infos_powerpc64[] = -{ +static RegisterInfo g_register_infos_powerpc64[] = { #define GPR GPR64 POWERPC_REGS #undef GPR }; -static RegisterInfo -g_register_infos_powerpc32[] = -{ +static RegisterInfo g_register_infos_powerpc32[] = { #define GPR GPR32 POWERPC_REGS #undef GPR }; -static RegisterInfo -g_register_infos_powerpc64_32[] = -{ +static RegisterInfo g_register_infos_powerpc64_32[] = { #define GPR GPR64 #undef GPR_SIZE -#define GPR_SIZE(reg) (sizeof(uint32_t)) +#define GPR_SIZE(reg) (sizeof(uint32_t)) #undef GPR_OFFSET -#define GPR_OFFSET(regname) \ - (offsetof(GPR, regname) + (sizeof(((GPR *)NULL)->regname) - GPR_SIZE(reg))) +#define GPR_OFFSET(regname) \ + (offsetof(GPR, regname) + (sizeof(((GPR *)NULL)->regname) - GPR_SIZE(reg))) POWERPC_REGS #undef GPR }; -static_assert((sizeof(g_register_infos_powerpc32) / sizeof(g_register_infos_powerpc32[0])) == k_num_registers_powerpc, - "g_register_infos_powerpc32 has wrong number of register infos"); -static_assert((sizeof(g_register_infos_powerpc64) / sizeof(g_register_infos_powerpc64[0])) == k_num_registers_powerpc, - "g_register_infos_powerpc64 has wrong number of register infos"); -static_assert(sizeof(g_register_infos_powerpc64_32) == sizeof(g_register_infos_powerpc64), - "g_register_infos_powerpc64_32 doesn't match size of g_register_infos_powerpc64"); +static_assert((sizeof(g_register_infos_powerpc32) / + sizeof(g_register_infos_powerpc32[0])) == + k_num_registers_powerpc, + "g_register_infos_powerpc32 has wrong number of register infos"); +static_assert((sizeof(g_register_infos_powerpc64) / + sizeof(g_register_infos_powerpc64[0])) == + k_num_registers_powerpc, + "g_register_infos_powerpc64 has wrong number of register infos"); +static_assert(sizeof(g_register_infos_powerpc64_32) == + sizeof(g_register_infos_powerpc64), + "g_register_infos_powerpc64_32 doesn't match size of " + "g_register_infos_powerpc64"); #undef DEFINE_FPR #undef DEFINE_GPR @@ -181,4 +227,3 @@ static_assert(sizeof(g_register_infos_powerpc64_32) == sizeof(g_register_infos_p #endif // DECLARE_REGISTER_INFOS_POWERPC_STRUCT #undef GPR_OFFSET - diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h index 0710174c0a8..0bbf422405e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h @@ -27,36 +27,39 @@ // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB -#define DEFINE_GPR(name, size, offset, alt, generic) \ - { \ - #name, alt, size, offset, eEncodingUint, eFormatHex, \ - { dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ - NULL, NULL, NULL, 0 \ - } - -#define DEFINE_GPR_NODWARF(name, size, offset, alt, generic) \ - { \ - #name, alt, size, offset, eEncodingUint, eFormatHex, \ - { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ - NULL, NULL, NULL, 0 \ - } - -#define DEFINE_FPR(name, size, offset) \ - { \ - #name, NULL, size, offset, eEncodingUint, eFormatHex, \ - { dwarf_##name##_s390x, dwarf_##name##_s390x, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ - NULL, NULL, NULL, 0 \ - } - -#define DEFINE_FPR_NODWARF(name, size, offset) \ - { \ - #name, NULL, size, offset, eEncodingUint, eFormatHex, \ - { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ - NULL, NULL, NULL, 0 \ - } - -static RegisterInfo g_register_infos_s390x[] = -{ +#define DEFINE_GPR(name, size, offset, alt, generic) \ + { \ + #name, alt, size, offset, eEncodingUint, eFormatHex, \ + {dwarf_##name##_s390x, dwarf_##name##_s390x, generic, \ + LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_GPR_NODWARF(name, size, offset, alt, generic) \ + { \ + #name, alt, size, offset, eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, generic, \ + LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FPR(name, size, offset) \ + { \ + #name, NULL, size, offset, eEncodingUint, eFormatHex, \ + {dwarf_##name##_s390x, dwarf_##name##_s390x, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FPR_NODWARF(name, size, offset) \ + { \ + #name, NULL, size, offset, eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, NULL, 0 \ + } + +static RegisterInfo g_register_infos_s390x[] = { // General purpose registers. DEFINE_GPR(r0, 8, GPR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM), DEFINE_GPR(r1, 8, GPR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM), @@ -94,31 +97,25 @@ static RegisterInfo g_register_infos_s390x[] = DEFINE_GPR(pswa, 8, 8, "pc", LLDB_REGNUM_GENERIC_PC), // Floating point registers. - DEFINE_FPR(f0, 8, FPR_OFFSET(0)), - DEFINE_FPR(f1, 8, FPR_OFFSET(1)), - DEFINE_FPR(f2, 8, FPR_OFFSET(2)), - DEFINE_FPR(f3, 8, FPR_OFFSET(3)), - DEFINE_FPR(f4, 8, FPR_OFFSET(4)), - DEFINE_FPR(f5, 8, FPR_OFFSET(5)), - DEFINE_FPR(f6, 8, FPR_OFFSET(6)), - DEFINE_FPR(f7, 8, FPR_OFFSET(7)), - DEFINE_FPR(f8, 8, FPR_OFFSET(8)), - DEFINE_FPR(f9, 8, FPR_OFFSET(9)), - DEFINE_FPR(f10, 8, FPR_OFFSET(10)), - DEFINE_FPR(f11, 8, FPR_OFFSET(11)), - DEFINE_FPR(f12, 8, FPR_OFFSET(12)), - DEFINE_FPR(f13, 8, FPR_OFFSET(13)), - DEFINE_FPR(f14, 8, FPR_OFFSET(14)), - DEFINE_FPR(f15, 8, FPR_OFFSET(15)), + DEFINE_FPR(f0, 8, FPR_OFFSET(0)), DEFINE_FPR(f1, 8, FPR_OFFSET(1)), + DEFINE_FPR(f2, 8, FPR_OFFSET(2)), DEFINE_FPR(f3, 8, FPR_OFFSET(3)), + DEFINE_FPR(f4, 8, FPR_OFFSET(4)), DEFINE_FPR(f5, 8, FPR_OFFSET(5)), + DEFINE_FPR(f6, 8, FPR_OFFSET(6)), DEFINE_FPR(f7, 8, FPR_OFFSET(7)), + DEFINE_FPR(f8, 8, FPR_OFFSET(8)), DEFINE_FPR(f9, 8, FPR_OFFSET(9)), + DEFINE_FPR(f10, 8, FPR_OFFSET(10)), DEFINE_FPR(f11, 8, FPR_OFFSET(11)), + DEFINE_FPR(f12, 8, FPR_OFFSET(12)), DEFINE_FPR(f13, 8, FPR_OFFSET(13)), + DEFINE_FPR(f14, 8, FPR_OFFSET(14)), DEFINE_FPR(f15, 8, FPR_OFFSET(15)), DEFINE_FPR_NODWARF(fpc, 4, 0), // Linux operating-specific info. - DEFINE_GPR_NODWARF(orig_r2, 8, 16 + 16 * 8 + 16 * 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR_NODWARF(orig_r2, 8, 16 + 16 * 8 + 16 * 4, nullptr, + LLDB_INVALID_REGNUM), DEFINE_GPR_NODWARF(last_break, 8, 0, nullptr, LLDB_INVALID_REGNUM), DEFINE_GPR_NODWARF(system_call, 4, 0, nullptr, LLDB_INVALID_REGNUM), }; -static_assert((sizeof(g_register_infos_s390x) / sizeof(g_register_infos_s390x[0])) == k_num_registers_s390x, +static_assert((sizeof(g_register_infos_s390x) / + sizeof(g_register_infos_s390x[0])) == k_num_registers_s390x, "g_register_infos_s390x has wrong number of register infos"); #undef GPR_OFFSET diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h index aeb6672ec94..5dcbc6772ed 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h @@ -17,30 +17,28 @@ // Project includes // Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(GPR, regname)) +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) // Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(FXSAVE, regname)) +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, regname)) // Computes the offset of the YMM register assembled from register halves. // Based on DNBArchImplX86_64.cpp from debugserver -#define YMM_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + \ - (32 * reg_index)) +#define YMM_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) #ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT // Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) +#define FPR_SIZE(reg) sizeof(((FXSAVE *)NULL)->reg) // Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) +#define FP_SIZE sizeof(((MMSReg *)NULL)->bytes) // Number of bytes needed to represent an XMM register. #define XMM_SIZE sizeof(XMMReg) @@ -48,222 +46,255 @@ // Number of bytes needed to represent a YMM register. #define YMM_SIZE sizeof(YMMReg) -#define DR_SIZE sizeof(((DBG*)NULL)->dr[0]) +#define DR_SIZE sizeof(((DBG *)NULL)->dr[0]) // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB // Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, NULL, NULL, NULL, 0} - -#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ - { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_x86_64 }, NULL, NULL, NULL, 0} - -#define DEFINE_FP_ST(reg, i) \ - { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_FP_MM(reg, i) \ - { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ - eEncodingUint, eFormatHex, \ - { dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_x86_64 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64}, \ - NULL, NULL, NULL, 0} - -#define DEFINE_YMM(reg, i) \ - { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64 }, \ - NULL, NULL, NULL, 0} - -#define DEFINE_DR(reg, i) \ - { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \ - { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL, NULL, 0} - -#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ - { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0} -#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ - { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0} -#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ - { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0} -#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ - { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0} - -static RegisterInfo -g_register_infos_x86_64[] = -{ - // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin - DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), - DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), - DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - DEFINE_GPR_PSEUDO_32(eax, rax), - DEFINE_GPR_PSEUDO_32(ebx, rbx), - DEFINE_GPR_PSEUDO_32(ecx, rcx), - DEFINE_GPR_PSEUDO_32(edx, rdx), - DEFINE_GPR_PSEUDO_32(edi, rdi), - DEFINE_GPR_PSEUDO_32(esi, rsi), - DEFINE_GPR_PSEUDO_32(ebp, rbp), - DEFINE_GPR_PSEUDO_32(esp, rsp), - DEFINE_GPR_PSEUDO_32(r8d, r8), - DEFINE_GPR_PSEUDO_32(r9d, r9), - DEFINE_GPR_PSEUDO_32(r10d, r10), - DEFINE_GPR_PSEUDO_32(r11d, r11), - DEFINE_GPR_PSEUDO_32(r12d, r12), - DEFINE_GPR_PSEUDO_32(r13d, r13), - DEFINE_GPR_PSEUDO_32(r14d, r14), - DEFINE_GPR_PSEUDO_32(r15d, r15), - DEFINE_GPR_PSEUDO_16(ax, rax), - DEFINE_GPR_PSEUDO_16(bx, rbx), - DEFINE_GPR_PSEUDO_16(cx, rcx), - DEFINE_GPR_PSEUDO_16(dx, rdx), - DEFINE_GPR_PSEUDO_16(di, rdi), - DEFINE_GPR_PSEUDO_16(si, rsi), - DEFINE_GPR_PSEUDO_16(bp, rbp), - DEFINE_GPR_PSEUDO_16(sp, rsp), - DEFINE_GPR_PSEUDO_16(r8w, r8), - DEFINE_GPR_PSEUDO_16(r9w, r9), - DEFINE_GPR_PSEUDO_16(r10w, r10), - DEFINE_GPR_PSEUDO_16(r11w, r11), - DEFINE_GPR_PSEUDO_16(r12w, r12), - DEFINE_GPR_PSEUDO_16(r13w, r13), - DEFINE_GPR_PSEUDO_16(r14w, r14), - DEFINE_GPR_PSEUDO_16(r15w, r15), - DEFINE_GPR_PSEUDO_8H(ah, rax), - DEFINE_GPR_PSEUDO_8H(bh, rbx), - DEFINE_GPR_PSEUDO_8H(ch, rcx), - DEFINE_GPR_PSEUDO_8H(dh, rdx), - DEFINE_GPR_PSEUDO_8L(al, rax), - DEFINE_GPR_PSEUDO_8L(bl, rbx), - DEFINE_GPR_PSEUDO_8L(cl, rcx), - DEFINE_GPR_PSEUDO_8L(dl, rdx), - DEFINE_GPR_PSEUDO_8L(dil, rdi), - DEFINE_GPR_PSEUDO_8L(sil, rsi), - DEFINE_GPR_PSEUDO_8L(bpl, rbp), - DEFINE_GPR_PSEUDO_8L(spl, rsp), - DEFINE_GPR_PSEUDO_8L(r8l, r8), - DEFINE_GPR_PSEUDO_8L(r9l, r9), - DEFINE_GPR_PSEUDO_8L(r10l, r10), - DEFINE_GPR_PSEUDO_8L(r11l, r11), - DEFINE_GPR_PSEUDO_8L(r12l, r12), - DEFINE_GPR_PSEUDO_8L(r13l, r13), - DEFINE_GPR_PSEUDO_8L(r14l, r14), - DEFINE_GPR_PSEUDO_8L(r15l, r15), - - // i387 Floating point registers. EH_frame, DWARF, Generic, Process Plugin - DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ + #reg, alt, sizeof(((GPR *) NULL)->reg), \ + GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##reg##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { \ + #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ + {kind1, kind2, kind3, kind4, \ + lldb_##name##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FP_ST(reg, i) \ + { \ + #reg #i, NULL, FP_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_FP_MM(reg, i) \ + { \ + #reg #i, NULL, sizeof(uint64_t), \ + LLVM_EXTENSION FPR_OFFSET( \ + stmm[i]), eEncodingUint, eFormatHex, \ + {dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_mm##i##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_XMM(reg, i) \ + { \ + #reg #i, NULL, XMM_SIZE, \ + LLVM_EXTENSION FPR_OFFSET( \ + reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg##i##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_YMM(reg, i) \ + { \ + #reg #i, NULL, YMM_SIZE, \ + LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8, \ + {dwarf_##reg##i##h_x86_64, \ + dwarf_##reg##i##h_x86_64, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg##i##_x86_64 }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_DR(reg, i) \ + { \ + #reg #i, NULL, DR_SIZE, \ + DR_OFFSET(i), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM }, \ + NULL, NULL, NULL, 0 \ + } + +#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ + { \ + #reg32, NULL, 4, \ + GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg32##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0 \ + } +#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ + { \ + #reg16, NULL, 2, \ + GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg16##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0 \ + } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ + { \ + #reg8, NULL, 1, \ + GPR_OFFSET(reg64) + 1, eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0 \ + } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ + { \ + #reg8, NULL, 1, \ + GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + lldb_##reg8##_x86_64 }, \ + RegisterContextPOSIX_x86::g_contained_##reg64, \ + RegisterContextPOSIX_x86::g_invalidate_##reg64, NULL, 0 \ + } + +static RegisterInfo g_register_infos_x86_64[] = { + // General purpose registers. EH_Frame, DWARF, + // Generic, Process Plugin + DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, + LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, + LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, + LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, + LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, + LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, + LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, + LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, + LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, + LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + DEFINE_GPR_PSEUDO_32(eax, rax), DEFINE_GPR_PSEUDO_32(ebx, rbx), + DEFINE_GPR_PSEUDO_32(ecx, rcx), DEFINE_GPR_PSEUDO_32(edx, rdx), + DEFINE_GPR_PSEUDO_32(edi, rdi), DEFINE_GPR_PSEUDO_32(esi, rsi), + DEFINE_GPR_PSEUDO_32(ebp, rbp), DEFINE_GPR_PSEUDO_32(esp, rsp), + DEFINE_GPR_PSEUDO_32(r8d, r8), DEFINE_GPR_PSEUDO_32(r9d, r9), + DEFINE_GPR_PSEUDO_32(r10d, r10), DEFINE_GPR_PSEUDO_32(r11d, r11), + DEFINE_GPR_PSEUDO_32(r12d, r12), DEFINE_GPR_PSEUDO_32(r13d, r13), + DEFINE_GPR_PSEUDO_32(r14d, r14), DEFINE_GPR_PSEUDO_32(r15d, r15), + DEFINE_GPR_PSEUDO_16(ax, rax), DEFINE_GPR_PSEUDO_16(bx, rbx), + DEFINE_GPR_PSEUDO_16(cx, rcx), DEFINE_GPR_PSEUDO_16(dx, rdx), + DEFINE_GPR_PSEUDO_16(di, rdi), DEFINE_GPR_PSEUDO_16(si, rsi), + DEFINE_GPR_PSEUDO_16(bp, rbp), DEFINE_GPR_PSEUDO_16(sp, rsp), + DEFINE_GPR_PSEUDO_16(r8w, r8), DEFINE_GPR_PSEUDO_16(r9w, r9), + DEFINE_GPR_PSEUDO_16(r10w, r10), DEFINE_GPR_PSEUDO_16(r11w, r11), + DEFINE_GPR_PSEUDO_16(r12w, r12), DEFINE_GPR_PSEUDO_16(r13w, r13), + DEFINE_GPR_PSEUDO_16(r14w, r14), DEFINE_GPR_PSEUDO_16(r15w, r15), + DEFINE_GPR_PSEUDO_8H(ah, rax), DEFINE_GPR_PSEUDO_8H(bh, rbx), + DEFINE_GPR_PSEUDO_8H(ch, rcx), DEFINE_GPR_PSEUDO_8H(dh, rdx), + DEFINE_GPR_PSEUDO_8L(al, rax), DEFINE_GPR_PSEUDO_8L(bl, rbx), + DEFINE_GPR_PSEUDO_8L(cl, rcx), DEFINE_GPR_PSEUDO_8L(dl, rdx), + DEFINE_GPR_PSEUDO_8L(dil, rdi), DEFINE_GPR_PSEUDO_8L(sil, rsi), + DEFINE_GPR_PSEUDO_8L(bpl, rbp), DEFINE_GPR_PSEUDO_8L(spl, rsp), + DEFINE_GPR_PSEUDO_8L(r8l, r8), DEFINE_GPR_PSEUDO_8L(r9l, r9), + DEFINE_GPR_PSEUDO_8L(r10l, r10), DEFINE_GPR_PSEUDO_8L(r11l, r11), + DEFINE_GPR_PSEUDO_8L(r12l, r12), DEFINE_GPR_PSEUDO_8L(r13l, r13), + DEFINE_GPR_PSEUDO_8L(r14l, r14), DEFINE_GPR_PSEUDO_8L(r15l, r15), + + // i387 Floating point registers. EH_frame, + // DWARF, Generic, Process Plugin + DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), // FP registers. - DEFINE_FP_ST(st, 0), - DEFINE_FP_ST(st, 1), - DEFINE_FP_ST(st, 2), - DEFINE_FP_ST(st, 3), - DEFINE_FP_ST(st, 4), - DEFINE_FP_ST(st, 5), - DEFINE_FP_ST(st, 6), - DEFINE_FP_ST(st, 7), - DEFINE_FP_MM(mm, 0), - DEFINE_FP_MM(mm, 1), - DEFINE_FP_MM(mm, 2), - DEFINE_FP_MM(mm, 3), - DEFINE_FP_MM(mm, 4), - DEFINE_FP_MM(mm, 5), - DEFINE_FP_MM(mm, 6), + DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7), DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), DEFINE_FP_MM(mm, 2), DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), DEFINE_FP_MM(mm, 5), DEFINE_FP_MM(mm, 6), DEFINE_FP_MM(mm, 7), // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), DEFINE_XMM(xmm, 10), DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), DEFINE_XMM(xmm, 13), DEFINE_XMM(xmm, 14), DEFINE_XMM(xmm, 15), // Copy of YMM registers assembled from xmm and ymmh - DEFINE_YMM(ymm, 0), - DEFINE_YMM(ymm, 1), - DEFINE_YMM(ymm, 2), - DEFINE_YMM(ymm, 3), - DEFINE_YMM(ymm, 4), - DEFINE_YMM(ymm, 5), - DEFINE_YMM(ymm, 6), - DEFINE_YMM(ymm, 7), - DEFINE_YMM(ymm, 8), - DEFINE_YMM(ymm, 9), - DEFINE_YMM(ymm, 10), - DEFINE_YMM(ymm, 11), - DEFINE_YMM(ymm, 12), - DEFINE_YMM(ymm, 13), - DEFINE_YMM(ymm, 14), + DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), DEFINE_YMM(ymm, 8), + DEFINE_YMM(ymm, 9), DEFINE_YMM(ymm, 10), DEFINE_YMM(ymm, 11), + DEFINE_YMM(ymm, 12), DEFINE_YMM(ymm, 13), DEFINE_YMM(ymm, 14), DEFINE_YMM(ymm, 15), // Debug registers for lldb internal use - DEFINE_DR(dr, 0), - DEFINE_DR(dr, 1), - DEFINE_DR(dr, 2), - DEFINE_DR(dr, 3), - DEFINE_DR(dr, 4), - DEFINE_DR(dr, 5), - DEFINE_DR(dr, 6), - DEFINE_DR(dr, 7) -}; - -static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64, - "g_register_infos_x86_64 has wrong number of register infos"); + DEFINE_DR(dr, 0), DEFINE_DR(dr, 1), DEFINE_DR(dr, 2), DEFINE_DR(dr, 3), + DEFINE_DR(dr, 4), DEFINE_DR(dr, 5), DEFINE_DR(dr, 6), DEFINE_DR(dr, 7)}; + +static_assert((sizeof(g_register_infos_x86_64) / + sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64, + "g_register_infos_x86_64 has wrong number of register infos"); #undef FPR_SIZE #undef FP_SIZE @@ -284,130 +315,131 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[ #ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS -#define UPDATE_GPR_INFO(reg, reg64) \ -do { \ - g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \ -} while(false); - -#define UPDATE_GPR_INFO_8H(reg, reg64) \ -do { \ - g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \ -} while(false); - -#define UPDATE_FPR_INFO(reg, reg64) \ -do { \ - g_register_infos[lldb_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \ -} while(false); - -#define UPDATE_FP_INFO(reg, i) \ -do { \ - g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \ -} while(false); - -#define UPDATE_XMM_INFO(reg, i) \ -do { \ - g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \ -} while(false); - -#define UPDATE_YMM_INFO(reg, i) \ -do { \ - g_register_infos[lldb_##reg##i##_i386].byte_offset = YMM_OFFSET(i); \ -} while(false); - -#define UPDATE_DR_INFO(reg_index) \ -do { \ - g_register_infos[lldb_dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \ -} while(false); - - // Update the register offsets - UPDATE_GPR_INFO(eax, rax); - UPDATE_GPR_INFO(ebx, rbx); - UPDATE_GPR_INFO(ecx, rcx); - UPDATE_GPR_INFO(edx, rdx); - UPDATE_GPR_INFO(edi, rdi); - UPDATE_GPR_INFO(esi, rsi); - UPDATE_GPR_INFO(ebp, rbp); - UPDATE_GPR_INFO(esp, rsp); - UPDATE_GPR_INFO(eip, rip); - UPDATE_GPR_INFO(eflags, rflags); - UPDATE_GPR_INFO(cs, cs); - UPDATE_GPR_INFO(fs, fs); - UPDATE_GPR_INFO(gs, gs); - UPDATE_GPR_INFO(ss, ss); - UPDATE_GPR_INFO(ds, ds); - UPDATE_GPR_INFO(es, es); - - UPDATE_GPR_INFO(ax, rax); - UPDATE_GPR_INFO(bx, rbx); - UPDATE_GPR_INFO(cx, rcx); - UPDATE_GPR_INFO(dx, rdx); - UPDATE_GPR_INFO(di, rdi); - UPDATE_GPR_INFO(si, rsi); - UPDATE_GPR_INFO(bp, rbp); - UPDATE_GPR_INFO(sp, rsp); - UPDATE_GPR_INFO_8H(ah, rax); - UPDATE_GPR_INFO_8H(bh, rbx); - UPDATE_GPR_INFO_8H(ch, rcx); - UPDATE_GPR_INFO_8H(dh, rdx); - UPDATE_GPR_INFO(al, rax); - UPDATE_GPR_INFO(bl, rbx); - UPDATE_GPR_INFO(cl, rcx); - UPDATE_GPR_INFO(dl, rdx); - - UPDATE_FPR_INFO(fctrl, fctrl); - UPDATE_FPR_INFO(fstat, fstat); - UPDATE_FPR_INFO(ftag, ftag); - UPDATE_FPR_INFO(fop, fop); - UPDATE_FPR_INFO(fiseg, ptr.i386_.fiseg); - UPDATE_FPR_INFO(fioff, ptr.i386_.fioff); - UPDATE_FPR_INFO(fooff, ptr.i386_.fooff); - UPDATE_FPR_INFO(foseg, ptr.i386_.foseg); - UPDATE_FPR_INFO(mxcsr, mxcsr); - UPDATE_FPR_INFO(mxcsrmask, mxcsrmask); - - UPDATE_FP_INFO(st, 0); - UPDATE_FP_INFO(st, 1); - UPDATE_FP_INFO(st, 2); - UPDATE_FP_INFO(st, 3); - UPDATE_FP_INFO(st, 4); - UPDATE_FP_INFO(st, 5); - UPDATE_FP_INFO(st, 6); - UPDATE_FP_INFO(st, 7); - UPDATE_FP_INFO(mm, 0); - UPDATE_FP_INFO(mm, 1); - UPDATE_FP_INFO(mm, 2); - UPDATE_FP_INFO(mm, 3); - UPDATE_FP_INFO(mm, 4); - UPDATE_FP_INFO(mm, 5); - UPDATE_FP_INFO(mm, 6); - UPDATE_FP_INFO(mm, 7); - - UPDATE_XMM_INFO(xmm, 0); - UPDATE_XMM_INFO(xmm, 1); - UPDATE_XMM_INFO(xmm, 2); - UPDATE_XMM_INFO(xmm, 3); - UPDATE_XMM_INFO(xmm, 4); - UPDATE_XMM_INFO(xmm, 5); - UPDATE_XMM_INFO(xmm, 6); - UPDATE_XMM_INFO(xmm, 7); - - UPDATE_YMM_INFO(ymm, 0); - UPDATE_YMM_INFO(ymm, 1); - UPDATE_YMM_INFO(ymm, 2); - UPDATE_YMM_INFO(ymm, 3); - UPDATE_YMM_INFO(ymm, 4); - UPDATE_YMM_INFO(ymm, 5); - UPDATE_YMM_INFO(ymm, 6); - UPDATE_YMM_INFO(ymm, 7); - - UPDATE_DR_INFO(0); - UPDATE_DR_INFO(1); - UPDATE_DR_INFO(2); - UPDATE_DR_INFO(3); - UPDATE_DR_INFO(4); - UPDATE_DR_INFO(5); - UPDATE_DR_INFO(6); - UPDATE_DR_INFO(7); +#define UPDATE_GPR_INFO(reg, reg64) \ + do { \ + g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \ + } while (false); + +#define UPDATE_GPR_INFO_8H(reg, reg64) \ + do { \ + g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \ + } while (false); + +#define UPDATE_FPR_INFO(reg, reg64) \ + do { \ + g_register_infos[lldb_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \ + } while (false); + +#define UPDATE_FP_INFO(reg, i) \ + do { \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \ + } while (false); + +#define UPDATE_XMM_INFO(reg, i) \ + do { \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \ + } while (false); + +#define UPDATE_YMM_INFO(reg, i) \ + do { \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = YMM_OFFSET(i); \ + } while (false); + +#define UPDATE_DR_INFO(reg_index) \ + do { \ + g_register_infos[lldb_dr##reg_index##_i386].byte_offset = \ + DR_OFFSET(reg_index); \ + } while (false); + +// Update the register offsets +UPDATE_GPR_INFO(eax, rax); +UPDATE_GPR_INFO(ebx, rbx); +UPDATE_GPR_INFO(ecx, rcx); +UPDATE_GPR_INFO(edx, rdx); +UPDATE_GPR_INFO(edi, rdi); +UPDATE_GPR_INFO(esi, rsi); +UPDATE_GPR_INFO(ebp, rbp); +UPDATE_GPR_INFO(esp, rsp); +UPDATE_GPR_INFO(eip, rip); +UPDATE_GPR_INFO(eflags, rflags); +UPDATE_GPR_INFO(cs, cs); +UPDATE_GPR_INFO(fs, fs); +UPDATE_GPR_INFO(gs, gs); +UPDATE_GPR_INFO(ss, ss); +UPDATE_GPR_INFO(ds, ds); +UPDATE_GPR_INFO(es, es); + +UPDATE_GPR_INFO(ax, rax); +UPDATE_GPR_INFO(bx, rbx); +UPDATE_GPR_INFO(cx, rcx); +UPDATE_GPR_INFO(dx, rdx); +UPDATE_GPR_INFO(di, rdi); +UPDATE_GPR_INFO(si, rsi); +UPDATE_GPR_INFO(bp, rbp); +UPDATE_GPR_INFO(sp, rsp); +UPDATE_GPR_INFO_8H(ah, rax); +UPDATE_GPR_INFO_8H(bh, rbx); +UPDATE_GPR_INFO_8H(ch, rcx); +UPDATE_GPR_INFO_8H(dh, rdx); +UPDATE_GPR_INFO(al, rax); +UPDATE_GPR_INFO(bl, rbx); +UPDATE_GPR_INFO(cl, rcx); +UPDATE_GPR_INFO(dl, rdx); + +UPDATE_FPR_INFO(fctrl, fctrl); +UPDATE_FPR_INFO(fstat, fstat); +UPDATE_FPR_INFO(ftag, ftag); +UPDATE_FPR_INFO(fop, fop); +UPDATE_FPR_INFO(fiseg, ptr.i386_.fiseg); +UPDATE_FPR_INFO(fioff, ptr.i386_.fioff); +UPDATE_FPR_INFO(fooff, ptr.i386_.fooff); +UPDATE_FPR_INFO(foseg, ptr.i386_.foseg); +UPDATE_FPR_INFO(mxcsr, mxcsr); +UPDATE_FPR_INFO(mxcsrmask, mxcsrmask); + +UPDATE_FP_INFO(st, 0); +UPDATE_FP_INFO(st, 1); +UPDATE_FP_INFO(st, 2); +UPDATE_FP_INFO(st, 3); +UPDATE_FP_INFO(st, 4); +UPDATE_FP_INFO(st, 5); +UPDATE_FP_INFO(st, 6); +UPDATE_FP_INFO(st, 7); +UPDATE_FP_INFO(mm, 0); +UPDATE_FP_INFO(mm, 1); +UPDATE_FP_INFO(mm, 2); +UPDATE_FP_INFO(mm, 3); +UPDATE_FP_INFO(mm, 4); +UPDATE_FP_INFO(mm, 5); +UPDATE_FP_INFO(mm, 6); +UPDATE_FP_INFO(mm, 7); + +UPDATE_XMM_INFO(xmm, 0); +UPDATE_XMM_INFO(xmm, 1); +UPDATE_XMM_INFO(xmm, 2); +UPDATE_XMM_INFO(xmm, 3); +UPDATE_XMM_INFO(xmm, 4); +UPDATE_XMM_INFO(xmm, 5); +UPDATE_XMM_INFO(xmm, 6); +UPDATE_XMM_INFO(xmm, 7); + +UPDATE_YMM_INFO(ymm, 0); +UPDATE_YMM_INFO(ymm, 1); +UPDATE_YMM_INFO(ymm, 2); +UPDATE_YMM_INFO(ymm, 3); +UPDATE_YMM_INFO(ymm, 4); +UPDATE_YMM_INFO(ymm, 5); +UPDATE_YMM_INFO(ymm, 6); +UPDATE_YMM_INFO(ymm, 7); + +UPDATE_DR_INFO(0); +UPDATE_DR_INFO(1); +UPDATE_DR_INFO(2); +UPDATE_DR_INFO(3); +UPDATE_DR_INFO(4); +UPDATE_DR_INFO(5); +UPDATE_DR_INFO(6); +UPDATE_DR_INFO(7); #undef UPDATE_GPR_INFO #undef UPDATE_GPR_INFO_8H diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index 6331e81f637..2afed11f5dc 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -28,509 +28,557 @@ using namespace lldb; using namespace lldb_private; - -const char * -StopInfoMachException::GetDescription () -{ - if (m_description.empty() && m_value != 0) - { - ExecutionContext exe_ctx (m_thread_wp.lock()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; - - const char *exc_desc = NULL; - const char *code_label = "code"; - const char *code_desc = NULL; - const char *subcode_label = "subcode"; - const char *subcode_desc = NULL; - switch (m_value) - { - case 1: // EXC_BAD_ACCESS - exc_desc = "EXC_BAD_ACCESS"; - subcode_label = "address"; - switch (cpu) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) - { - case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break; - } - break; - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) - { - case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; - case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) - { - case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; - case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; - case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; - } - break; - - default: - break; - } - break; - - case 2: // EXC_BAD_INSTRUCTION - exc_desc = "EXC_BAD_INSTRUCTION"; - switch (cpu) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (m_exc_code == 1) - code_desc = "EXC_I386_INVOP"; - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) - { - case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; - case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; - case 3: code_desc = "EXC_PPC_PRIVINST"; break; - case 4: code_desc = "EXC_PPC_PRIVREG"; break; - case 5: code_desc = "EXC_PPC_TRACE"; break; - case 6: code_desc = "EXC_PPC_PERFMON"; break; - } - break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (m_exc_code == 1) - code_desc = "EXC_ARM_UNDEFINED"; - break; - - default: - break; - } - break; - - case 3: // EXC_ARITHMETIC - exc_desc = "EXC_ARITHMETIC"; - switch (cpu) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) - { - case 1: code_desc = "EXC_I386_DIV"; break; - case 2: code_desc = "EXC_I386_INTO"; break; - case 3: code_desc = "EXC_I386_NOEXT"; break; - case 4: code_desc = "EXC_I386_EXTOVR"; break; - case 5: code_desc = "EXC_I386_EXTERR"; break; - case 6: code_desc = "EXC_I386_EMERR"; break; - case 7: code_desc = "EXC_I386_BOUND"; break; - case 8: code_desc = "EXC_I386_SSEEXTERR"; break; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) - { - case 1: code_desc = "EXC_PPC_OVERFLOW"; break; - case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; - case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; - case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; - case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; - case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; - case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; - } - break; - - default: - break; - } - break; - - case 4: // EXC_EMULATION - exc_desc = "EXC_EMULATION"; - break; - - - case 5: // EXC_SOFTWARE - exc_desc = "EXC_SOFTWARE"; - if (m_exc_code == 0x10003) - { - subcode_desc = "EXC_SOFT_SIGNAL"; - subcode_label = "signo"; - } - break; - - case 6: // EXC_BREAKPOINT - { - exc_desc = "EXC_BREAKPOINT"; - switch (cpu) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) - { - case 1: code_desc = "EXC_I386_SGL"; break; - case 2: code_desc = "EXC_I386_BPT"; break; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) - { - case 1: code_desc = "EXC_PPC_BREAKPOINT"; break; - } - break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) - { - case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; - case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; - case 1: code_desc = "EXC_ARM_BREAKPOINT"; break; - // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT - case 0: code_desc = "EXC_ARM_BREAKPOINT"; break; - } - break; - - default: - break; - } - } - break; +const char *StopInfoMachException::GetDescription() { + if (m_description.empty() && m_value != 0) { + ExecutionContext exe_ctx(m_thread_wp.lock()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + const char *exc_desc = NULL; + const char *code_label = "code"; + const char *code_desc = NULL; + const char *subcode_label = "subcode"; + const char *subcode_desc = NULL; + switch (m_value) { + case 1: // EXC_BAD_ACCESS + exc_desc = "EXC_BAD_ACCESS"; + subcode_label = "address"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 0xd: + code_desc = "EXC_I386_GPFLT"; + m_exc_data_count = 1; + break; + } + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; + break; + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; + break; + } + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_PPC_VM_PROT_READ"; + break; + case 0x102: + code_desc = "EXC_PPC_BADSPACE"; + break; + case 0x103: + code_desc = "EXC_PPC_UNALIGNED"; + break; + } + break; + + default: + break; + } + break; + + case 2: // EXC_BAD_INSTRUCTION + exc_desc = "EXC_BAD_INSTRUCTION"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (m_exc_code == 1) + code_desc = "EXC_I386_INVOP"; + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_PPC_INVALID_SYSCALL"; + break; + case 2: + code_desc = "EXC_PPC_UNIPL_INST"; + break; + case 3: + code_desc = "EXC_PPC_PRIVINST"; + break; + case 4: + code_desc = "EXC_PPC_PRIVREG"; + break; + case 5: + code_desc = "EXC_PPC_TRACE"; + break; + case 6: + code_desc = "EXC_PPC_PERFMON"; + break; + } + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (m_exc_code == 1) + code_desc = "EXC_ARM_UNDEFINED"; + break; + + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + exc_desc = "EXC_ARITHMETIC"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_DIV"; + break; + case 2: + code_desc = "EXC_I386_INTO"; + break; + case 3: + code_desc = "EXC_I386_NOEXT"; + break; + case 4: + code_desc = "EXC_I386_EXTOVR"; + break; + case 5: + code_desc = "EXC_I386_EXTERR"; + break; + case 6: + code_desc = "EXC_I386_EMERR"; + break; case 7: - exc_desc = "EXC_SYSCALL"; - break; - + code_desc = "EXC_I386_BOUND"; + break; case 8: - exc_desc = "EXC_MACH_SYSCALL"; - break; - - case 9: - exc_desc = "EXC_RPC_ALERT"; - break; - - case 10: - exc_desc = "EXC_CRASH"; - break; - case 11: - exc_desc = "EXC_RESOURCE"; - break; - case 12: - exc_desc = "EXC_GUARD"; - break; + code_desc = "EXC_I386_SSEEXTERR"; + break; + } + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_PPC_OVERFLOW"; + break; + case 2: + code_desc = "EXC_PPC_ZERO_DIVIDE"; + break; + case 3: + code_desc = "EXC_PPC_FLT_INEXACT"; + break; + case 4: + code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; + break; + case 5: + code_desc = "EXC_PPC_FLT_UNDERFLOW"; + break; + case 6: + code_desc = "EXC_PPC_FLT_OVERFLOW"; + break; + case 7: + code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; + break; + } + break; + + default: + break; + } + break; + + case 4: // EXC_EMULATION + exc_desc = "EXC_EMULATION"; + break; + + case 5: // EXC_SOFTWARE + exc_desc = "EXC_SOFTWARE"; + if (m_exc_code == 0x10003) { + subcode_desc = "EXC_SOFT_SIGNAL"; + subcode_label = "signo"; + } + break; + + case 6: // EXC_BREAKPOINT + { + exc_desc = "EXC_BREAKPOINT"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_SGL"; + break; + case 2: + code_desc = "EXC_I386_BPT"; + break; + } + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_PPC_BREAKPOINT"; + break; } - - StreamString strm; + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; + break; + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; + break; + case 1: + code_desc = "EXC_ARM_BREAKPOINT"; + break; + // FIXME temporary workaround, exc_code 0 does not really mean + // EXC_ARM_BREAKPOINT + case 0: + code_desc = "EXC_ARM_BREAKPOINT"; + break; + } + break; + + default: + break; + } + } break; + + case 7: + exc_desc = "EXC_SYSCALL"; + break; + + case 8: + exc_desc = "EXC_MACH_SYSCALL"; + break; + + case 9: + exc_desc = "EXC_RPC_ALERT"; + break; + + case 10: + exc_desc = "EXC_CRASH"; + break; + case 11: + exc_desc = "EXC_RESOURCE"; + break; + case 12: + exc_desc = "EXC_GUARD"; + break; + } - if (exc_desc) - strm.PutCString(exc_desc); - else - strm.Printf("EXC_??? (%" PRIu64 ")", m_value); + StreamString strm; - if (m_exc_data_count >= 1) - { - if (code_desc) - strm.Printf(" (%s=%s", code_label, code_desc); - else - strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); - } + if (exc_desc) + strm.PutCString(exc_desc); + else + strm.Printf("EXC_??? (%" PRIu64 ")", m_value); - if (m_exc_data_count >= 2) - { - if (subcode_desc) - strm.Printf(", %s=%s", subcode_label, subcode_desc); - else - strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); - } - - if (m_exc_data_count > 0) - strm.PutChar(')'); - - m_description.swap (strm.GetString()); + if (m_exc_data_count >= 1) { + if (code_desc) + strm.Printf(" (%s=%s", code_label, code_desc); + else + strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); } - return m_description.c_str(); -} + if (m_exc_data_count >= 2) { + if (subcode_desc) + strm.Printf(", %s=%s", subcode_label, subcode_desc); + else + strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); + } + if (m_exc_data_count > 0) + strm.PutChar(')'); + m_description.swap(strm.GetString()); + } + return m_description.c_str(); +} +StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( + Thread &thread, uint32_t exc_type, uint32_t exc_data_count, + uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, + bool pc_already_adjusted, bool adjust_pc_if_needed) { + if (exc_type != 0) { + uint32_t pc_decrement = 0; + ExecutionContext exe_ctx(thread.shared_from_this()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + switch (exc_type) { + case 1: // EXC_BAD_ACCESS + break; + + case 2: // EXC_BAD_INSTRUCTION + switch (cpu) { + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + switch (exc_code) { + case 1: // EXC_PPC_INVALID_SYSCALL + case 2: // EXC_PPC_UNIPL_INST + case 3: // EXC_PPC_PRIVINST + case 4: // EXC_PPC_PRIVREG + break; + case 5: // EXC_PPC_TRACE + return StopInfo::CreateStopReasonToTrace(thread); + case 6: // EXC_PPC_PERFMON + break; + } + break; + + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + case 4: // EXC_EMULATION + break; + + case 5: // EXC_SOFTWARE + if (exc_code == 0x10003) // EXC_SOFT_SIGNAL + { + if (exc_sub_code == 5) { + // On MacOSX, a SIGTRAP can signify that a process has called + // exec, so we should check with our dynamic loader to verify. + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); + if (dynamic_loader && dynamic_loader->ProcessDidExec()) { + // The program was re-exec'ed + return StopInfo::CreateStopReasonWithExec(thread); + } + // if (!process_did_exec) + // { + // // We have a SIGTRAP, make sure we + // didn't exec by checking + // // for the PC being at + // "_dyld_start"... + // lldb::StackFrameSP frame_sp + // (thread.GetStackFrameAtIndex(0)); + // if (frame_sp) + // { + // const Symbol *symbol = + // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; + // if (symbol) + // { + // if (symbol->GetName() == + // ConstString("_dyld_start")) + // process_did_exec = true; + // } + // } + // } + } + } + return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); + } + break; -StopInfoSP -StopInfoMachException::CreateStopReasonWithMachException -( - Thread &thread, - uint32_t exc_type, - uint32_t exc_data_count, - uint64_t exc_code, - uint64_t exc_sub_code, - uint64_t exc_sub_sub_code, - bool pc_already_adjusted, - bool adjust_pc_if_needed -) -{ - if (exc_type != 0) + case 6: // EXC_BREAKPOINT { - uint32_t pc_decrement = 0; - ExecutionContext exe_ctx (thread.shared_from_this()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; - - switch (exc_type) + bool is_actual_breakpoint = false; + bool is_trace_if_actual_breakpoint_missing = false; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (exc_code == 1) // EXC_I386_SGL { - case 1: // EXC_BAD_ACCESS - break; - - case 2: // EXC_BAD_INSTRUCTION - switch (cpu) - { - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (exc_code) - { - case 1: // EXC_PPC_INVALID_SYSCALL - case 2: // EXC_PPC_UNIPL_INST - case 3: // EXC_PPC_PRIVINST - case 4: // EXC_PPC_PRIVREG - break; - case 5: // EXC_PPC_TRACE - return StopInfo::CreateStopReasonToTrace (thread); - case 6: // EXC_PPC_PERFMON - break; - } - break; - - default: - break; + if (!exc_sub_code) { + // This looks like a plain trap. + // Have to check if there is a breakpoint here as well. When you + // single-step onto a trap, + // the single step stops you not to trap. Since we also do that + // check below, let's just use + // that logic. + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } else { + + // It's a watchpoint, then. + // The exc_sub_code indicates the data break address. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. + // Set the hardware index if that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); } - break; - - case 3: // EXC_ARITHMETIC - case 4: // EXC_EMULATION - break; - - case 5: // EXC_SOFTWARE - if (exc_code == 0x10003) // EXC_SOFT_SIGNAL - { - if (exc_sub_code == 5) - { - // On MacOSX, a SIGTRAP can signify that a process has called - // exec, so we should check with our dynamic loader to verify. - ProcessSP process_sp (thread.GetProcess()); - if (process_sp) - { - DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); - if (dynamic_loader && dynamic_loader->ProcessDidExec()) - { - // The program was re-exec'ed - return StopInfo::CreateStopReasonWithExec (thread); - } -// if (!process_did_exec) -// { -// // We have a SIGTRAP, make sure we didn't exec by checking -// // for the PC being at "_dyld_start"... -// lldb::StackFrameSP frame_sp (thread.GetStackFrameAtIndex(0)); -// if (frame_sp) -// { -// const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; -// if (symbol) -// { -// if (symbol->GetName() == ConstString("_dyld_start")) -// process_did_exec = true; -// } -// } -// } - } - } - return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code); - } - break; - - case 6: // EXC_BREAKPOINT - { - bool is_actual_breakpoint = false; - bool is_trace_if_actual_breakpoint_missing = false; - switch (cpu) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (exc_code == 1) // EXC_I386_SGL - { - if (!exc_sub_code) - { - // This looks like a plain trap. - // Have to check if there is a breakpoint here as well. When you single-step onto a trap, - // the single step stops you not to trap. Since we also do that check below, let's just use - // that logic. - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - else - { - - // It's a watchpoint, then. - // The exc_sub_code indicates the data break address. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) - { - // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data. - // Set the hardware index if that's the case. - if (exc_data_count >=3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); - } - } - } - else if (exc_code == 2 || // EXC_I386_BPT - exc_code == 3) // EXC_I386_BPTFLT - { - // KDP returns EXC_I386_BPTFLT for trace breakpoints - if (exc_code == 3) - is_trace_if_actual_breakpoint_missing = true; - - is_actual_breakpoint = true; - if (!pc_already_adjusted) - pc_decrement = 1; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT - break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled - // data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) - { - // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data. - // Set the hardware index if that's the case. - if (exc_data_count >=3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); - } - else - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - } - else if (exc_code == 1) // EXC_ARM_BREAKPOINT - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel is currently returning this so accept it as indicating a breakpoint until the kernel is fixed - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - break; - - case llvm::Triple::aarch64: - { - if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT - { - // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 is set - is_actual_breakpoint = false; - is_trace_if_actual_breakpoint_missing = true; - } - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled - // data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) - { - // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data. - // Set the hardware index if that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); - } - // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS - if (thread.GetTemporaryResumeState() == eStateStepping) - return StopInfo::CreateStopReasonToTrace(thread); - } - // It looks like exc_sub_code has the 4 bytes of the instruction that triggered the - // exception, i.e. our breakpoint opcode - is_actual_breakpoint = exc_code == 1; - break; - } - - default: - break; - } - - if (is_actual_breakpoint) - { - RegisterContextSP reg_ctx_sp (thread.GetRegisterContext()); - addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; - - ProcessSP process_sp (thread.CalculateProcess()); - - lldb::BreakpointSiteSP bp_site_sp; - if (process_sp) - bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp && bp_site_sp->IsEnabled()) - { - // Update the PC if we were asked to do so, but only do - // so if we find a breakpoint that we know about cause - // this could be a trap instruction in the code - if (pc_decrement > 0 && adjust_pc_if_needed) - reg_ctx_sp->SetPC (pc); - - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - // If we have an operating system plug-in, we might have set a thread specific breakpoint using the - // operating system thread ID, so we can't make any assumptions about the thread ID so we must always - // report the breakpoint regardless of the thread. - if (bp_site_sp->ValidForThisThread (&thread) || thread.GetProcess()->GetOperatingSystem () != NULL) - return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); - else if (is_trace_if_actual_breakpoint_missing) - return StopInfo::CreateStopReasonToTrace (thread); - else - return StopInfoSP(); - } - - // Don't call this a trace if we weren't single stepping this thread. - if (is_trace_if_actual_breakpoint_missing && thread.GetTemporaryResumeState() == eStateStepping) - { - return StopInfo::CreateStopReasonToTrace (thread); - } - } - } - break; + } + } else if (exc_code == 2 || // EXC_I386_BPT + exc_code == 3) // EXC_I386_BPTFLT + { + // KDP returns EXC_I386_BPTFLT for trace breakpoints + if (exc_code == 3) + is_trace_if_actual_breakpoint_missing = true; - case 7: // EXC_SYSCALL - case 8: // EXC_MACH_SYSCALL - case 9: // EXC_RPC_ALERT - case 10: // EXC_CRASH - break; + is_actual_breakpoint = true; + if (!pc_already_adjusted) + pc_decrement = 1; } - - return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled + // data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. + // Set the hardware index if that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); + } else { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } + } else if (exc_code == 1) // EXC_ARM_BREAKPOINT + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel + // is currently returning this so accept it as + // indicating a breakpoint until the kernel is + // fixed + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } + break; + + case llvm::Triple::aarch64: { + if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT + { + // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 + // is set + is_actual_breakpoint = false; + is_trace_if_actual_breakpoint_missing = true; + } + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled + // data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. + // Set the hardware index if that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); + } + // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as + // EXC_BAD_ACCESS + if (thread.GetTemporaryResumeState() == eStateStepping) + return StopInfo::CreateStopReasonToTrace(thread); + } + // It looks like exc_sub_code has the 4 bytes of the instruction that + // triggered the + // exception, i.e. our breakpoint opcode + is_actual_breakpoint = exc_code == 1; + break; + } + + default: + break; + } + + if (is_actual_breakpoint) { + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; + + ProcessSP process_sp(thread.CalculateProcess()); + + lldb::BreakpointSiteSP bp_site_sp; + if (process_sp) + bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp && bp_site_sp->IsEnabled()) { + // Update the PC if we were asked to do so, but only do + // so if we find a breakpoint that we know about cause + // this could be a trap instruction in the code + if (pc_decrement > 0 && adjust_pc_if_needed) + reg_ctx_sp->SetPC(pc); + + // If the breakpoint is for this thread, then we'll report the hit, + // but if it is for another thread, + // we can just report no reason. We don't need to worry about + // stepping over the breakpoint here, that + // will be taken care of when the thread resumes and notices that + // there's a breakpoint under the pc. + // If we have an operating system plug-in, we might have set a thread + // specific breakpoint using the + // operating system thread ID, so we can't make any assumptions about + // the thread ID so we must always + // report the breakpoint regardless of the thread. + if (bp_site_sp->ValidForThisThread(&thread) || + thread.GetProcess()->GetOperatingSystem() != NULL) + return StopInfo::CreateStopReasonWithBreakpointSiteID( + thread, bp_site_sp->GetID()); + else if (is_trace_if_actual_breakpoint_missing) + return StopInfo::CreateStopReasonToTrace(thread); + else + return StopInfoSP(); + } + + // Don't call this a trace if we weren't single stepping this thread. + if (is_trace_if_actual_breakpoint_missing && + thread.GetTemporaryResumeState() == eStateStepping) { + return StopInfo::CreateStopReasonToTrace(thread); + } + } + } break; + + case 7: // EXC_SYSCALL + case 8: // EXC_MACH_SYSCALL + case 9: // EXC_RPC_ALERT + case 10: // EXC_CRASH + break; } - return StopInfoSP(); + + return StopInfoSP(new StopInfoMachException( + thread, exc_type, exc_data_count, exc_code, exc_sub_code)); + } + return StopInfoSP(); } diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h index 25e05ecc1ec..94516454105 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h @@ -20,52 +20,37 @@ namespace lldb_private { -class StopInfoMachException : public StopInfo -{ +class StopInfoMachException : public StopInfo { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - StopInfoMachException (Thread &thread, - uint32_t exc_type, - uint32_t exc_data_count, - uint64_t exc_code, - uint64_t exc_subcode) : - StopInfo (thread, exc_type), - m_exc_data_count (exc_data_count), - m_exc_code (exc_code), - m_exc_subcode (exc_subcode) - { - } - - ~StopInfoMachException() override = default; - - lldb::StopReason - GetStopReason() const override - { - return lldb::eStopReasonException; - } - - const char * - GetDescription() override; - - // Since some mach exceptions will be reported as breakpoints, signals, - // or trace, we use this static accessor which will translate the mach - // exception into the correct StopInfo. - static lldb::StopInfoSP - CreateStopReasonWithMachException (Thread &thread, - uint32_t exc_type, - uint32_t exc_data_count, - uint64_t exc_code, - uint64_t exc_sub_code, - uint64_t exc_sub_sub_code, - bool pc_already_adjusted = true, - bool adjust_pc_if_needed = false); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StopInfoMachException(Thread &thread, uint32_t exc_type, + uint32_t exc_data_count, uint64_t exc_code, + uint64_t exc_subcode) + : StopInfo(thread, exc_type), m_exc_data_count(exc_data_count), + m_exc_code(exc_code), m_exc_subcode(exc_subcode) {} + + ~StopInfoMachException() override = default; + + lldb::StopReason GetStopReason() const override { + return lldb::eStopReasonException; + } + + const char *GetDescription() override; + + // Since some mach exceptions will be reported as breakpoints, signals, + // or trace, we use this static accessor which will translate the mach + // exception into the correct StopInfo. + static lldb::StopInfoSP CreateStopReasonWithMachException( + Thread &thread, uint32_t exc_type, uint32_t exc_data_count, + uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, + bool pc_already_adjusted = true, bool adjust_pc_if_needed = false); protected: - uint32_t m_exc_data_count; - uint64_t m_exc_code; - uint64_t m_exc_subcode; + uint32_t m_exc_data_count; + uint64_t m_exc_code; + uint64_t m_exc_subcode; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 6a7aa626baf..b3cac1c854d 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -1,4 +1,5 @@ -//===-- ThreadMemory.cpp ----------------------------------------------*- C++ -*-===// +//===-- ThreadMemory.cpp ----------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -8,133 +9,97 @@ //===----------------------------------------------------------------------===// #include "Plugins/Process/Utility/ThreadMemory.h" +#include "Plugins/Process/Utility/RegisterContextThreadMemory.h" #include "lldb/Target/OperatingSystem.h" -#include "lldb/Target/RegisterContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Unwind.h" -#include "Plugins/Process/Utility/RegisterContextThreadMemory.h" using namespace lldb; using namespace lldb_private; -ThreadMemory::ThreadMemory (Process &process, - tid_t tid, - const ValueObjectSP &thread_info_valobj_sp) : - Thread (process, tid), - m_backing_thread_sp (), - m_thread_info_valobj_sp (thread_info_valobj_sp), - m_name(), - m_queue() -{ -} - +ThreadMemory::ThreadMemory(Process &process, tid_t tid, + const ValueObjectSP &thread_info_valobj_sp) + : Thread(process, tid), m_backing_thread_sp(), + m_thread_info_valobj_sp(thread_info_valobj_sp), m_name(), m_queue() {} -ThreadMemory::ThreadMemory (Process &process, - lldb::tid_t tid, - const char *name, - const char *queue, - lldb::addr_t register_data_addr) : - Thread (process, tid), - m_backing_thread_sp (), - m_thread_info_valobj_sp (), - m_name(), - m_queue(), - m_register_data_addr (register_data_addr) -{ - if (name) - m_name = name; - if (queue) - m_queue = queue; +ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, const char *name, + const char *queue, lldb::addr_t register_data_addr) + : Thread(process, tid), m_backing_thread_sp(), m_thread_info_valobj_sp(), + m_name(), m_queue(), m_register_data_addr(register_data_addr) { + if (name) + m_name = name; + if (queue) + m_queue = queue; } +ThreadMemory::~ThreadMemory() { DestroyThread(); } -ThreadMemory::~ThreadMemory() -{ - DestroyThread(); +void ThreadMemory::WillResume(StateType resume_state) { + if (m_backing_thread_sp) + m_backing_thread_sp->WillResume(resume_state); } -void -ThreadMemory::WillResume (StateType resume_state) -{ - if (m_backing_thread_sp) - m_backing_thread_sp->WillResume(resume_state); +void ThreadMemory::ClearStackFrames() { + if (m_backing_thread_sp) + m_backing_thread_sp->ClearStackFrames(); + Thread::ClearStackFrames(); } -void -ThreadMemory::ClearStackFrames () -{ - if (m_backing_thread_sp) - m_backing_thread_sp->ClearStackFrames(); - Thread::ClearStackFrames(); +RegisterContextSP ThreadMemory::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp.reset( + new RegisterContextThreadMemory(*this, m_register_data_addr)); + return m_reg_context_sp; } RegisterContextSP -ThreadMemory::GetRegisterContext () -{ - if (!m_reg_context_sp) - m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr)); - return m_reg_context_sp; -} +ThreadMemory::CreateRegisterContextForFrame(StackFrame *frame) { + RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; -RegisterContextSP -ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame) -{ - RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex (); - - if (concrete_frame_idx == 0) - { - reg_ctx_sp = GetRegisterContext (); - } - else - { - Unwind *unwinder = GetUnwinder (); - if (unwinder) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame); - } - return reg_ctx_sp; + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + reg_ctx_sp = GetRegisterContext(); + } else { + Unwind *unwinder = GetUnwinder(); + if (unwinder) + reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; } -bool -ThreadMemory::CalculateStopInfo () -{ - if (m_backing_thread_sp) - { - lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo()); - if (backing_stop_info_sp && backing_stop_info_sp->IsValidForOperatingSystemThread(*this)) - { - backing_stop_info_sp->SetThread (shared_from_this()); - SetStopInfo (backing_stop_info_sp); - return true; - } +bool ThreadMemory::CalculateStopInfo() { + if (m_backing_thread_sp) { + lldb::StopInfoSP backing_stop_info_sp( + m_backing_thread_sp->GetPrivateStopInfo()); + if (backing_stop_info_sp && + backing_stop_info_sp->IsValidForOperatingSystemThread(*this)) { + backing_stop_info_sp->SetThread(shared_from_this()); + SetStopInfo(backing_stop_info_sp); + return true; } - else - { - ProcessSP process_sp (GetProcess()); + } else { + ProcessSP process_sp(GetProcess()); - if (process_sp) - { - OperatingSystem *os = process_sp->GetOperatingSystem (); - if (os) - { - SetStopInfo (os->CreateThreadStopReason (this)); - return true; - } - } + if (process_sp) { + OperatingSystem *os = process_sp->GetOperatingSystem(); + if (os) { + SetStopInfo(os->CreateThreadStopReason(this)); + return true; + } } - return false; + } + return false; } -void -ThreadMemory::RefreshStateAfterStop() -{ - if (m_backing_thread_sp) - return m_backing_thread_sp->RefreshStateAfterStop(); - - if (m_reg_context_sp) - m_reg_context_sp->InvalidateAllRegisters(); +void ThreadMemory::RefreshStateAfterStop() { + if (m_backing_thread_sp) + return m_backing_thread_sp->RefreshStateAfterStop(); + + if (m_reg_context_sp) + m_reg_context_sp->InvalidateAllRegisters(); } diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index 1e7cbfa4481..095544d244b 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -18,129 +18,94 @@ // Project includes #include "lldb/Target/Thread.h" -class ThreadMemory : - public lldb_private::Thread -{ +class ThreadMemory : public lldb_private::Thread { public: - ThreadMemory (lldb_private::Process &process, - lldb::tid_t tid, - const lldb::ValueObjectSP &thread_info_valobj_sp); - - ThreadMemory (lldb_private::Process &process, - lldb::tid_t tid, - const char *name, - const char *queue, - lldb::addr_t register_data_addr); - - ~ThreadMemory() override; - - lldb::RegisterContextSP - GetRegisterContext() override; - - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - - bool - CalculateStopInfo() override; - - const char * - GetInfo() override - { - if (m_backing_thread_sp) - m_backing_thread_sp->GetInfo(); - return nullptr; - } - - const char * - GetName() override - { - if (!m_name.empty()) - return m_name.c_str(); - if (m_backing_thread_sp) - m_backing_thread_sp->GetName(); - return nullptr; - } - - const char * - GetQueueName() override - { - if (!m_queue.empty()) - return m_queue.c_str(); - if (m_backing_thread_sp) - m_backing_thread_sp->GetQueueName(); - return nullptr; - } - - void - WillResume(lldb::StateType resume_state) override; - - void - DidResume() override - { - if (m_backing_thread_sp) - m_backing_thread_sp->DidResume(); - } - - lldb::user_id_t - GetProtocolID() const override - { - if (m_backing_thread_sp) - return m_backing_thread_sp->GetProtocolID(); - return Thread::GetProtocolID(); - } - - void - RefreshStateAfterStop() override; - - lldb::ValueObjectSP & - GetValueObject () - { - return m_thread_info_valobj_sp; - } - - void - ClearStackFrames() override; - - void - ClearBackingThread() override - { - m_backing_thread_sp.reset(); - } - - bool - SetBackingThread(const lldb::ThreadSP &thread_sp) override - { - //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID()); - m_backing_thread_sp = thread_sp; - return (bool)thread_sp; - } - - lldb::ThreadSP - GetBackingThread() const override - { - return m_backing_thread_sp; - } + ThreadMemory(lldb_private::Process &process, lldb::tid_t tid, + const lldb::ValueObjectSP &thread_info_valobj_sp); + + ThreadMemory(lldb_private::Process &process, lldb::tid_t tid, + const char *name, const char *queue, + lldb::addr_t register_data_addr); + + ~ThreadMemory() override; + + lldb::RegisterContextSP GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + + bool CalculateStopInfo() override; + + const char *GetInfo() override { + if (m_backing_thread_sp) + m_backing_thread_sp->GetInfo(); + return nullptr; + } + + const char *GetName() override { + if (!m_name.empty()) + return m_name.c_str(); + if (m_backing_thread_sp) + m_backing_thread_sp->GetName(); + return nullptr; + } + + const char *GetQueueName() override { + if (!m_queue.empty()) + return m_queue.c_str(); + if (m_backing_thread_sp) + m_backing_thread_sp->GetQueueName(); + return nullptr; + } + + void WillResume(lldb::StateType resume_state) override; + + void DidResume() override { + if (m_backing_thread_sp) + m_backing_thread_sp->DidResume(); + } + + lldb::user_id_t GetProtocolID() const override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetProtocolID(); + return Thread::GetProtocolID(); + } + + void RefreshStateAfterStop() override; + + lldb::ValueObjectSP &GetValueObject() { return m_thread_info_valobj_sp; } + + void ClearStackFrames() override; + + void ClearBackingThread() override { m_backing_thread_sp.reset(); } + + bool SetBackingThread(const lldb::ThreadSP &thread_sp) override { + // printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), + // thread_sp->GetID()); + m_backing_thread_sp = thread_sp; + return (bool)thread_sp; + } + + lldb::ThreadSP GetBackingThread() const override { + return m_backing_thread_sp; + } protected: - bool - IsOperatingSystemPluginThread() const override - { - return true; - } - - // If this memory thread is actually represented by a thread from the - // lldb_private::Process subclass, then fill in the thread here and - // all APIs will be routed through this thread object. If m_backing_thread_sp - // is empty, then this thread is simply in memory with no representation - // through the process plug-in. - lldb::ThreadSP m_backing_thread_sp; - lldb::ValueObjectSP m_thread_info_valobj_sp; - std::string m_name; - std::string m_queue; - lldb::addr_t m_register_data_addr; + bool IsOperatingSystemPluginThread() const override { return true; } + + // If this memory thread is actually represented by a thread from the + // lldb_private::Process subclass, then fill in the thread here and + // all APIs will be routed through this thread object. If m_backing_thread_sp + // is empty, then this thread is simply in memory with no representation + // through the process plug-in. + lldb::ThreadSP m_backing_thread_sp; + lldb::ValueObjectSP m_thread_info_valobj_sp; + std::string m_name; + std::string m_queue; + lldb::addr_t m_register_data_addr; private: - DISALLOW_COPY_AND_ASSIGN (ThreadMemory); + DISALLOW_COPY_AND_ASSIGN(ThreadMemory); }; #endif // liblldb_ThreadMemory_h_ diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index 9be09c478a0..775920a28c8 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -7,529 +7,533 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Module.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/ABI.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/Target.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" -#include "UnwindLLDB.h" #include "RegisterContextLLDB.h" +#include "UnwindLLDB.h" using namespace lldb; using namespace lldb_private; -UnwindLLDB::UnwindLLDB (Thread &thread) : - Unwind (thread), - m_frames(), - m_unwind_complete(false), - m_user_supplied_trap_handler_functions() -{ - ProcessSP process_sp(thread.GetProcess()); - if (process_sp) - { - Args args; - process_sp->GetTarget().GetUserSpecifiedTrapHandlerNames (args); - size_t count = args.GetArgumentCount(); - for (size_t i = 0; i < count; i++) - { - const char *func_name = args.GetArgumentAtIndex(i); - m_user_supplied_trap_handler_functions.push_back (ConstString (func_name)); - } +UnwindLLDB::UnwindLLDB(Thread &thread) + : Unwind(thread), m_frames(), m_unwind_complete(false), + m_user_supplied_trap_handler_functions() { + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + Args args; + process_sp->GetTarget().GetUserSpecifiedTrapHandlerNames(args); + size_t count = args.GetArgumentCount(); + for (size_t i = 0; i < count; i++) { + const char *func_name = args.GetArgumentAtIndex(i); + m_user_supplied_trap_handler_functions.push_back(ConstString(func_name)); } + } } -uint32_t -UnwindLLDB::DoGetFrameCount() -{ - if (!m_unwind_complete) - { +uint32_t UnwindLLDB::DoGetFrameCount() { + if (!m_unwind_complete) { //#define DEBUG_FRAME_SPEED 1 #if DEBUG_FRAME_SPEED #define FRAME_COUNT 10000 - TimeValue time_value (TimeValue::Now()); + TimeValue time_value(TimeValue::Now()); #endif - if (!AddFirstFrame ()) - return 0; + if (!AddFirstFrame()) + return 0; - ProcessSP process_sp (m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ProcessSP process_sp(m_thread.GetProcess()); + ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - while (AddOneMoreFrame (abi)) - { + while (AddOneMoreFrame(abi)) { #if DEBUG_FRAME_SPEED - if ((m_frames.size() % FRAME_COUNT) == 0) - { - TimeValue now(TimeValue::Now()); - uint64_t delta_t = now - time_value; - printf ("%u frames in %" PRIu64 ".%09llu ms (%g frames/sec)\n", - FRAME_COUNT, - delta_t / TimeValue::NanoSecPerSec, - delta_t % TimeValue::NanoSecPerSec, - (float)FRAME_COUNT / ((float)delta_t / (float)TimeValue::NanoSecPerSec)); - time_value = now; - } + if ((m_frames.size() % FRAME_COUNT) == 0) { + TimeValue now(TimeValue::Now()); + uint64_t delta_t = now - time_value; + printf("%u frames in %" PRIu64 ".%09llu ms (%g frames/sec)\n", + FRAME_COUNT, delta_t / TimeValue::NanoSecPerSec, + delta_t % TimeValue::NanoSecPerSec, + (float)FRAME_COUNT / + ((float)delta_t / (float)TimeValue::NanoSecPerSec)); + time_value = now; + } #endif - } } - return m_frames.size (); + } + return m_frames.size(); } -bool -UnwindLLDB::AddFirstFrame () -{ - if (m_frames.size() > 0) - return true; - - ProcessSP process_sp (m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; +bool UnwindLLDB::AddFirstFrame() { + if (m_frames.size() > 0) + return true; - // First, set up the 0th (initial) frame - CursorSP first_cursor_sp(new Cursor ()); - RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread, - RegisterContextLLDBSP(), - first_cursor_sp->sctx, - 0, *this)); - if (reg_ctx_sp.get() == NULL) - goto unwind_done; - - if (!reg_ctx_sp->IsValid()) - goto unwind_done; + ProcessSP process_sp(m_thread.GetProcess()); + ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - if (!reg_ctx_sp->GetCFA (first_cursor_sp->cfa)) - goto unwind_done; + // First, set up the 0th (initial) frame + CursorSP first_cursor_sp(new Cursor()); + RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB( + m_thread, RegisterContextLLDBSP(), first_cursor_sp->sctx, 0, *this)); + if (reg_ctx_sp.get() == NULL) + goto unwind_done; - if (!reg_ctx_sp->ReadPC (first_cursor_sp->start_pc)) - goto unwind_done; + if (!reg_ctx_sp->IsValid()) + goto unwind_done; - // Everything checks out, so release the auto pointer value and let the - // cursor own it in its shared pointer - first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; - m_frames.push_back (first_cursor_sp); + if (!reg_ctx_sp->GetCFA(first_cursor_sp->cfa)) + goto unwind_done; - // Update the Full Unwind Plan for this frame if not valid - UpdateUnwindPlanForFirstFrameIfInvalid(abi); + if (!reg_ctx_sp->ReadPC(first_cursor_sp->start_pc)) + goto unwind_done; - return true; + // Everything checks out, so release the auto pointer value and let the + // cursor own it in its shared pointer + first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; + m_frames.push_back(first_cursor_sp); + + // Update the Full Unwind Plan for this frame if not valid + UpdateUnwindPlanForFirstFrameIfInvalid(abi); + + return true; unwind_done: - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID()); - } - m_unwind_complete = true; - return false; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + log->Printf("th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); + } + m_unwind_complete = true; + return false; } -UnwindLLDB::CursorSP -UnwindLLDB::GetOneMoreFrame (ABI* abi) -{ - assert (m_frames.size() != 0 && "Get one more frame called with empty frame list"); - - // If we've already gotten to the end of the stack, don't bother to try again... - if (m_unwind_complete) - return nullptr; - - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - - CursorSP prev_frame = m_frames.back(); - uint32_t cur_idx = m_frames.size(); - - CursorSP cursor_sp(new Cursor ()); - RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB (m_thread, - prev_frame->reg_ctx_lldb_sp, - cursor_sp->sctx, - cur_idx, - *this)); - - // We want to detect an unwind that cycles erroneously and stop backtracing. - // Don't want this maximum unwind limit to be too low -- if you have a backtrace - // with an "infinitely recursing" bug, it will crash when the stack blows out - // and the first 35,000 frames are uninteresting - it's the top most 5 frames that - // you actually care about. So you can't just cap the unwind at 10,000 or something. - // Realistically anything over around 200,000 is going to blow out the stack space. - // If we're still unwinding at that point, we're probably never going to finish. - if (cur_idx > 300000) - { - if (log) - log->Printf ("%*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); +UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { + assert(m_frames.size() != 0 && + "Get one more frame called with empty frame list"); + + // If we've already gotten to the end of the stack, don't bother to try + // again... + if (m_unwind_complete) + return nullptr; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + + CursorSP prev_frame = m_frames.back(); + uint32_t cur_idx = m_frames.size(); + + CursorSP cursor_sp(new Cursor()); + RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB( + m_thread, prev_frame->reg_ctx_lldb_sp, cursor_sp->sctx, cur_idx, *this)); + + // We want to detect an unwind that cycles erroneously and stop backtracing. + // Don't want this maximum unwind limit to be too low -- if you have a + // backtrace + // with an "infinitely recursing" bug, it will crash when the stack blows out + // and the first 35,000 frames are uninteresting - it's the top most 5 frames + // that + // you actually care about. So you can't just cap the unwind at 10,000 or + // something. + // Realistically anything over around 200,000 is going to blow out the stack + // space. + // If we're still unwinding at that point, we're probably never going to + // finish. + if (cur_idx > 300000) { + if (log) + log->Printf("%*sFrame %d unwound too many frames, assuming unwind has " + "gone astray, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + + if (reg_ctx_sp.get() == NULL) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to + // that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. + // Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) return nullptr; - } - - if (reg_ctx_sp.get() == NULL) - { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); - } - if (log) - log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); - return nullptr; + return GetOneMoreFrame(abi); } - if (!reg_ctx_sp->IsValid()) - { - // We failed to get a valid RegisterContext. - // See if the regctx below this on the stack has a fallback unwind plan it can use. - // Subsequent calls to TryFallbackUnwindPlan() will return false. - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); - } - - if (log) - log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + if (log) + log->Printf("%*sFrame %d did not get a RegisterContext, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + + if (!reg_ctx_sp->IsValid()) { + // We failed to get a valid RegisterContext. + // See if the regctx below this on the stack has a fallback unwind plan it + // can use. + // Subsequent calls to TryFallbackUnwindPlan() will return false. + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. + // Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) return nullptr; + + return GetOneMoreFrame(abi); } - if (!reg_ctx_sp->GetCFA (cursor_sp->cfa)) - { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); - } - if (log) - log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + if (log) + log->Printf("%*sFrame %d invalid RegisterContext for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + if (!reg_ctx_sp->GetCFA(cursor_sp->cfa)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to + // that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. + // Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) return nullptr; + + return GetOneMoreFrame(abi); } - if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) - { - // On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not have - // its (constructed) CFA aligned correctly -- don't do the abi alignment check for - // these. - if (reg_ctx_sp->IsTrapHandlerFrame() == false) - { - // See if we can find a fallback unwind plan for THIS frame. It may be - // that the UnwindPlan we're using for THIS frame was bad and gave us a - // bad CFA. - // If that's not it, then see if we can change the UnwindPlan for the frame - // below us ("NEXT") -- see if using that other UnwindPlan gets us a better - // unwind state. - if (reg_ctx_sp->TryFallbackUnwindPlan() == false - || reg_ctx_sp->GetCFA (cursor_sp->cfa) == false - || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) - { - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); - } - - if (log) - log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); - return nullptr; - } - else - { - if (log) - log->Printf("%*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); - } - } - } - if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc)) - { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); + + if (log) + log->Printf( + "%*sFrame %d did not get CFA for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) { + // On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not + // have + // its (constructed) CFA aligned correctly -- don't do the abi alignment + // check for + // these. + if (reg_ctx_sp->IsTrapHandlerFrame() == false) { + // See if we can find a fallback unwind plan for THIS frame. It may be + // that the UnwindPlan we're using for THIS frame was bad and gave us a + // bad CFA. + // If that's not it, then see if we can change the UnwindPlan for the + // frame + // below us ("NEXT") -- see if using that other UnwindPlan gets us a + // better + // unwind state. + if (reg_ctx_sp->TryFallbackUnwindPlan() == false || + reg_ctx_sp->GetCFA(cursor_sp->cfa) == false || + abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) { + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be + // updated. Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + + return GetOneMoreFrame(abi); } if (log) - log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + log->Printf("%*sFrame %d did not get a valid CFA for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; - } - if (abi && !abi->CodeAddressIsValid (cursor_sp->start_pc)) - { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. - if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of - // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. - if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) - return nullptr; - - return GetOneMoreFrame (abi); - } - + } else { if (log) - log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + log->Printf("%*sFrame %d had a bad CFA value but we switched the " + "UnwindPlan being used and got one that looks more " + "realistic.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + } + } + } + if (!reg_ctx_sp->ReadPC(cursor_sp->start_pc)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to + // that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. + // Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) return nullptr; + + return GetOneMoreFrame(abi); } - // Infinite loop where the current cursor is the same as the previous one... - if (prev_frame->start_pc == cursor_sp->start_pc && prev_frame->cfa == cursor_sp->cfa) - { - if (log) - log->Printf ("th%d pc of this frame is the same as the previous frame and CFAs for both frames are identical -- stopping unwind", m_thread.GetIndexID()); + + if (log) + log->Printf( + "%*sFrame %d did not get PC for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to + // that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // TryFallbackUnwindPlan for prev_frame succeeded and updated + // reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. + // Hence updating it. + if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) return nullptr; + + return GetOneMoreFrame(abi); } - cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; - return cursor_sp; + if (log) + log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + return nullptr; + } + // Infinite loop where the current cursor is the same as the previous one... + if (prev_frame->start_pc == cursor_sp->start_pc && + prev_frame->cfa == cursor_sp->cfa) { + if (log) + log->Printf("th%d pc of this frame is the same as the previous frame and " + "CFAs for both frames are identical -- stopping unwind", + m_thread.GetIndexID()); + return nullptr; + } + + cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; + return cursor_sp; } -void -UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi) -{ - // This function is called for First Frame only. - assert (m_frames.size() == 1 && "No. of cursor frames are not 1"); - - bool old_m_unwind_complete = m_unwind_complete; - CursorSP old_m_candidate_frame = m_candidate_frame; - - // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan - // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also - // update the cfa of Frame 0 (if required). - AddOneMoreFrame(abi); - - // Remove all the frames added by above function as the purpose of - // using above function was just to check whether Unwinder of Frame 0 - // works or not. - for(uint32_t i=1; i<m_frames.size(); i++) - m_frames.pop_back(); - - // Restore status after calling AddOneMoreFrame - m_unwind_complete = old_m_unwind_complete; - m_candidate_frame = old_m_candidate_frame; - return; -} +void UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi) { + // This function is called for First Frame only. + assert(m_frames.size() == 1 && "No. of cursor frames are not 1"); + bool old_m_unwind_complete = m_unwind_complete; + CursorSP old_m_candidate_frame = m_candidate_frame; -bool -UnwindLLDB::AddOneMoreFrame (ABI *abi) -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan + // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also + // update the cfa of Frame 0 (if required). + AddOneMoreFrame(abi); - // Frame zero is a little different - if (m_frames.empty()) - return false; + // Remove all the frames added by above function as the purpose of + // using above function was just to check whether Unwinder of Frame 0 + // works or not. + for (uint32_t i = 1; i < m_frames.size(); i++) + m_frames.pop_back(); - // If we've already gotten to the end of the stack, don't bother to try again... - if (m_unwind_complete) - return false; + // Restore status after calling AddOneMoreFrame + m_unwind_complete = old_m_unwind_complete; + m_candidate_frame = old_m_candidate_frame; + return; +} - CursorSP new_frame = m_candidate_frame; - if (new_frame == nullptr) - new_frame = GetOneMoreFrame(abi); +bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); - if (new_frame == nullptr) - { - if (log) - log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID()); - m_unwind_complete = true; - return false; - } + // Frame zero is a little different + if (m_frames.empty()) + return false; - m_frames.push_back(new_frame); + // If we've already gotten to the end of the stack, don't bother to try + // again... + if (m_unwind_complete) + return false; - // If we can get one more frame further then accept that we get back a correct frame. - m_candidate_frame = GetOneMoreFrame(abi); - if (m_candidate_frame) - return true; - - // We can't go further from the frame returned by GetOneMore frame. Lets try to get a - // different frame with using the fallback unwind plan. - if (!m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) - { - // We don't have a valid fallback unwind plan. Accept the frame as it is. This is a - // valid situation when we are at the bottom of the stack. - return true; - } + CursorSP new_frame = m_candidate_frame; + if (new_frame == nullptr) + new_frame = GetOneMoreFrame(abi); - // Remove the possibly incorrect frame from the frame list and try to add a different one with - // the newly selected fallback unwind plan. - m_frames.pop_back(); - CursorSP new_frame_v2 = GetOneMoreFrame(abi); - if (new_frame_v2 == nullptr) - { - // We haven't got a new frame from the fallback unwind plan. Accept the frame from the - // original unwind plan. This is a valid situation when we are at the bottom of the stack. - m_frames.push_back(new_frame); - return true; - } + if (new_frame == nullptr) { + if (log) + log->Printf("th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); + m_unwind_complete = true; + return false; + } - // Push the new frame to the list and try to continue from this frame. If we can get a new frame - // then accept it as the correct one. - m_frames.push_back(new_frame_v2); - m_candidate_frame = GetOneMoreFrame(abi); - if (m_candidate_frame) - { - // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2]. - // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that. - // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan - // call above. However, cfa field still needs to be updated. Hence updating it here and then returning. - if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa))) - return false; - return true; - } + m_frames.push_back(new_frame); - // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind - // plan is usually more reliable then the fallback one. - m_frames.pop_back(); + // If we can get one more frame further then accept that we get back a correct + // frame. + m_candidate_frame = GetOneMoreFrame(abi); + if (m_candidate_frame) + return true; + + // We can't go further from the frame returned by GetOneMore frame. Lets try + // to get a + // different frame with using the fallback unwind plan. + if (!m_frames[m_frames.size() - 2] + ->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { + // We don't have a valid fallback unwind plan. Accept the frame as it is. + // This is a + // valid situation when we are at the bottom of the stack. + return true; + } + + // Remove the possibly incorrect frame from the frame list and try to add a + // different one with + // the newly selected fallback unwind plan. + m_frames.pop_back(); + CursorSP new_frame_v2 = GetOneMoreFrame(abi); + if (new_frame_v2 == nullptr) { + // We haven't got a new frame from the fallback unwind plan. Accept the + // frame from the + // original unwind plan. This is a valid situation when we are at the bottom + // of the stack. m_frames.push_back(new_frame); return true; + } + + // Push the new frame to the list and try to continue from this frame. If we + // can get a new frame + // then accept it as the correct one. + m_frames.push_back(new_frame_v2); + m_candidate_frame = GetOneMoreFrame(abi); + if (m_candidate_frame) { + // If control reached here then TryFallbackUnwindPlan had succeeded for + // Cursor::m_frames[m_frames.size() - 2]. + // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - + // 1] and a frame after that. + // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was + // already updated during TryFallbackUnwindPlan + // call above. However, cfa field still needs to be updated. Hence updating + // it here and then returning. + if (!(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA( + m_frames[m_frames.size() - 2]->cfa))) + return false; + return true; + } + + // The new frame hasn't helped in unwinding. Fall back to the original one as + // the default unwind + // plan is usually more reliable then the fallback one. + m_frames.pop_back(); + m_frames.push_back(new_frame); + return true; } -bool -UnwindLLDB::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc) -{ - if (m_frames.size() == 0) - { - if (!AddFirstFrame()) - return false; - } +bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { + if (m_frames.size() == 0) { + if (!AddFirstFrame()) + return false; + } - ProcessSP process_sp (m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ProcessSP process_sp(m_thread.GetProcess()); + ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - while (idx >= m_frames.size() && AddOneMoreFrame (abi)) - ; + while (idx >= m_frames.size() && AddOneMoreFrame(abi)) + ; - if (idx < m_frames.size ()) - { - cfa = m_frames[idx]->cfa; - pc = m_frames[idx]->start_pc; - return true; - } - return false; + if (idx < m_frames.size()) { + cfa = m_frames[idx]->cfa; + pc = m_frames[idx]->start_pc; + return true; + } + return false; } lldb::RegisterContextSP -UnwindLLDB::DoCreateRegisterContextForFrame (StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t idx = frame->GetConcreteFrameIndex (); - - if (idx == 0) - { - return m_thread.GetRegisterContext(); - } - - if (m_frames.size() == 0) - { - if (!AddFirstFrame()) - return reg_ctx_sp; - } - - ProcessSP process_sp (m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - - while (idx >= m_frames.size()) - { - if (!AddOneMoreFrame (abi)) - break; - } - - const uint32_t num_frames = m_frames.size(); - if (idx < num_frames) - { - Cursor *frame_cursor = m_frames[idx].get(); - reg_ctx_sp = frame_cursor->reg_ctx_lldb_sp; - } - return reg_ctx_sp; +UnwindLLDB::DoCreateRegisterContextForFrame(StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t idx = frame->GetConcreteFrameIndex(); + + if (idx == 0) { + return m_thread.GetRegisterContext(); + } + + if (m_frames.size() == 0) { + if (!AddFirstFrame()) + return reg_ctx_sp; + } + + ProcessSP process_sp(m_thread.GetProcess()); + ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + + while (idx >= m_frames.size()) { + if (!AddOneMoreFrame(abi)) + break; + } + + const uint32_t num_frames = m_frames.size(); + if (idx < num_frames) { + Cursor *frame_cursor = m_frames[idx].get(); + reg_ctx_sp = frame_cursor->reg_ctx_lldb_sp; + } + return reg_ctx_sp; } UnwindLLDB::RegisterContextLLDBSP -UnwindLLDB::GetRegisterContextForFrameNum (uint32_t frame_num) -{ - RegisterContextLLDBSP reg_ctx_sp; - if (frame_num < m_frames.size()) - reg_ctx_sp = m_frames[frame_num]->reg_ctx_lldb_sp; - return reg_ctx_sp; +UnwindLLDB::GetRegisterContextForFrameNum(uint32_t frame_num) { + RegisterContextLLDBSP reg_ctx_sp; + if (frame_num < m_frames.size()) + reg_ctx_sp = m_frames[frame_num]->reg_ctx_lldb_sp; + return reg_ctx_sp; } -bool -UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_reg) -{ - int64_t frame_num = starting_frame_num; - if (static_cast<size_t>(frame_num) >= m_frames.size()) - return false; - - // Never interrogate more than one level while looking for the saved pc value. If the value - // isn't saved by frame_num, none of the frames lower on the stack will have a useful value. - if (pc_reg) - { - UnwindLLDB::RegisterSearchResult result; - result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc); - if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound) - return true; - else - return false; - } - while (frame_num >= 0) - { - UnwindLLDB::RegisterSearchResult result; - result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc); - - // We descended down to the live register context aka stack frame 0 and are reading the value - // out of a live register. - if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound - && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext) - { - return true; - } +bool UnwindLLDB::SearchForSavedLocationForRegister( + uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, + uint32_t starting_frame_num, bool pc_reg) { + int64_t frame_num = starting_frame_num; + if (static_cast<size_t>(frame_num) >= m_frames.size()) + return false; - // If we have unwind instructions saying that register N is saved in register M in the middle of - // the stack (and N can equal M here, meaning the register was not used in this function), then - // change the register number we're looking for to M and keep looking for a concrete location - // down the stack, or an actual value from a live RegisterContext at frame 0. - if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound - && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInRegister - && frame_num > 0) - { - result = UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - lldb_regnum = regloc.location.register_number; - } + // Never interrogate more than one level while looking for the saved pc value. + // If the value + // isn't saved by frame_num, none of the frames lower on the stack will have a + // useful value. + if (pc_reg) { + UnwindLLDB::RegisterSearchResult result; + result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister( + lldb_regnum, regloc); + if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound) + return true; + else + return false; + } + while (frame_num >= 0) { + UnwindLLDB::RegisterSearchResult result; + result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister( + lldb_regnum, regloc); + + // We descended down to the live register context aka stack frame 0 and are + // reading the value + // out of a live register. + if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound && + regloc.type == + UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext) { + return true; + } - if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound) - return true; - if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile) - return false; - frame_num--; + // If we have unwind instructions saying that register N is saved in + // register M in the middle of + // the stack (and N can equal M here, meaning the register was not used in + // this function), then + // change the register number we're looking for to M and keep looking for a + // concrete location + // down the stack, or an actual value from a live RegisterContext at frame + // 0. + if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound && + regloc.type == UnwindLLDB::RegisterLocation::eRegisterInRegister && + frame_num > 0) { + result = UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + lldb_regnum = regloc.location.register_number; } - return false; + + if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound) + return true; + if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile) + return false; + frame_num--; + } + return false; } diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h index d3c07078759..b9323032180 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h @@ -16,148 +16,150 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Unwind.h" +#include "lldb/lldb-public.h" namespace lldb_private { class RegisterContextLLDB; -class UnwindLLDB : public lldb_private::Unwind -{ -public: - UnwindLLDB (lldb_private::Thread &thread); +class UnwindLLDB : public lldb_private::Unwind { +public: + UnwindLLDB(lldb_private::Thread &thread); - ~UnwindLLDB() override = default; + ~UnwindLLDB() override = default; - enum RegisterSearchResult - { - eRegisterFound = 0, - eRegisterNotFound, - eRegisterIsVolatile - }; + enum RegisterSearchResult { + eRegisterFound = 0, + eRegisterNotFound, + eRegisterIsVolatile + }; protected: - friend class lldb_private::RegisterContextLLDB; - - struct RegisterLocation { - enum RegisterLocationTypes - { - eRegisterNotSaved = 0, // register was not preserved by callee. If volatile reg, is unavailable - eRegisterSavedAtMemoryLocation, // register is saved at a specific word of target mem (target_memory_location) - eRegisterInRegister, // register is available in a (possible other) register (register_number) - eRegisterSavedAtHostMemoryLocation, // register is saved at a word in lldb's address space - eRegisterValueInferred, // register val was computed (and is in inferred_value) - eRegisterInLiveRegisterContext // register value is in a live (stack frame #0) register - }; - int type; - union - { - lldb::addr_t target_memory_location; - uint32_t register_number; // in eRegisterKindLLDB register numbering system - void* host_memory_location; - uint64_t inferred_value; // eRegisterValueInferred - e.g. stack pointer == cfa + offset - } location; + friend class lldb_private::RegisterContextLLDB; + + struct RegisterLocation { + enum RegisterLocationTypes { + eRegisterNotSaved = 0, // register was not preserved by callee. If + // volatile reg, is unavailable + eRegisterSavedAtMemoryLocation, // register is saved at a specific word of + // target mem (target_memory_location) + eRegisterInRegister, // register is available in a (possible other) + // register (register_number) + eRegisterSavedAtHostMemoryLocation, // register is saved at a word in + // lldb's address space + eRegisterValueInferred, // register val was computed (and is in + // inferred_value) + eRegisterInLiveRegisterContext // register value is in a live (stack frame + // #0) register }; + int type; + union { + lldb::addr_t target_memory_location; + uint32_t + register_number; // in eRegisterKindLLDB register numbering system + void *host_memory_location; + uint64_t inferred_value; // eRegisterValueInferred - e.g. stack pointer == + // cfa + offset + } location; + }; + + void DoClear() override { + m_frames.clear(); + m_candidate_frame.reset(); + m_unwind_complete = false; + } + + uint32_t DoGetFrameCount() override; + + bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &start_pc) override; + + lldb::RegisterContextSP + DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + + typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP; + + // Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame + // 1's RegisterContextLLDB) + // The RegisterContext for frame_num must already exist or this returns an + // empty shared pointer. + RegisterContextLLDBSP GetRegisterContextForFrameNum(uint32_t frame_num); + + // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the + // first one that + // has a saved location for this reg. + bool SearchForSavedLocationForRegister( + uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, + uint32_t starting_frame_num, bool pc_register); + + //------------------------------------------------------------------ + /// Provide the list of user-specified trap handler functions + /// + /// The Platform is one source of trap handler function names; that + /// may be augmented via a setting. The setting needs to be converted + /// into an array of ConstStrings before it can be used - we only want + /// to do that once per thread so it's here in the UnwindLLDB object. + /// + /// @return + /// Vector of ConstStrings of trap handler function names. May be + /// empty. + //------------------------------------------------------------------ + const std::vector<ConstString> &GetUserSpecifiedTrapHandlerFunctionNames() { + return m_user_supplied_trap_handler_functions; + } - void - DoClear() override - { - m_frames.clear(); - m_candidate_frame.reset(); - m_unwind_complete = false; - } - - uint32_t - DoGetFrameCount() override; - - bool - DoGetFrameInfoAtIndex(uint32_t frame_idx, - lldb::addr_t& cfa, - lldb::addr_t& start_pc) override; - - lldb::RegisterContextSP - DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - - typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP; - - // Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame 1's RegisterContextLLDB) - // The RegisterContext for frame_num must already exist or this returns an empty shared pointer. +private: + struct Cursor { + lldb::addr_t start_pc; // The start address of the function/symbol for this + // frame - current pc if unknown + lldb::addr_t cfa; // The canonical frame address for this stack frame + lldb_private::SymbolContext sctx; // A symbol context we'll contribute to & + // provide to the StackFrame creation RegisterContextLLDBSP - GetRegisterContextForFrameNum (uint32_t frame_num); - - // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that - // has a saved location for this reg. - bool - SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_register); - - - //------------------------------------------------------------------ - /// Provide the list of user-specified trap handler functions - /// - /// The Platform is one source of trap handler function names; that - /// may be augmented via a setting. The setting needs to be converted - /// into an array of ConstStrings before it can be used - we only want - /// to do that once per thread so it's here in the UnwindLLDB object. - /// - /// @return - /// Vector of ConstStrings of trap handler function names. May be - /// empty. - //------------------------------------------------------------------ - const std::vector<ConstString> & - GetUserSpecifiedTrapHandlerFunctionNames () - { - return m_user_supplied_trap_handler_functions; - } + reg_ctx_lldb_sp; // These are all RegisterContextLLDB's -private: - struct Cursor - { - lldb::addr_t start_pc; // The start address of the function/symbol for this frame - current pc if unknown - lldb::addr_t cfa; // The canonical frame address for this stack frame - lldb_private::SymbolContext sctx; // A symbol context we'll contribute to & provide to the StackFrame creation - RegisterContextLLDBSP reg_ctx_lldb_sp; // These are all RegisterContextLLDB's - - Cursor () : start_pc (LLDB_INVALID_ADDRESS), cfa (LLDB_INVALID_ADDRESS), sctx(), reg_ctx_lldb_sp() { } - private: - DISALLOW_COPY_AND_ASSIGN (Cursor); - }; + Cursor() + : start_pc(LLDB_INVALID_ADDRESS), cfa(LLDB_INVALID_ADDRESS), sctx(), + reg_ctx_lldb_sp() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Cursor); + }; + + typedef std::shared_ptr<Cursor> CursorSP; + std::vector<CursorSP> m_frames; + CursorSP m_candidate_frame; + bool m_unwind_complete; // If this is true, we've enumerated all the frames in + // the stack, and m_frames.size() is the + // number of frames, etc. Otherwise we've only gone as far as directly asked, + // and m_frames.size() + // is how far we've currently gone. + + std::vector<ConstString> m_user_supplied_trap_handler_functions; + + //----------------------------------------------------------------- + // Check if Full UnwindPlan of First frame is valid or not. + // If not then try Fallback UnwindPlan of the frame. If Fallback + // UnwindPlan succeeds then update the Full UnwindPlan with the + // Fallback UnwindPlan. + //----------------------------------------------------------------- + void UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi); + + CursorSP GetOneMoreFrame(ABI *abi); + + bool AddOneMoreFrame(ABI *abi); + + bool AddFirstFrame(); - typedef std::shared_ptr<Cursor> CursorSP; - std::vector<CursorSP> m_frames; - CursorSP m_candidate_frame; - bool m_unwind_complete; // If this is true, we've enumerated all the frames in the stack, and m_frames.size() is the - // number of frames, etc. Otherwise we've only gone as far as directly asked, and m_frames.size() - // is how far we've currently gone. - - std::vector<ConstString> m_user_supplied_trap_handler_functions; - - //----------------------------------------------------------------- - // Check if Full UnwindPlan of First frame is valid or not. - // If not then try Fallback UnwindPlan of the frame. If Fallback - // UnwindPlan succeeds then update the Full UnwindPlan with the - // Fallback UnwindPlan. - //----------------------------------------------------------------- - void - UpdateUnwindPlanForFirstFrameIfInvalid (ABI* abi); - - CursorSP - GetOneMoreFrame (ABI* abi); - - bool - AddOneMoreFrame (ABI *abi); - - bool - AddFirstFrame (); - - //------------------------------------------------------------------ - // For UnwindLLDB only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (UnwindLLDB); + //------------------------------------------------------------------ + // For UnwindLLDB only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(UnwindLLDB); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index d011314b096..e2691be603e 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -13,8 +13,8 @@ // Project includes #include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/Function.h" -#include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -25,251 +25,230 @@ using namespace lldb; using namespace lldb_private; -UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) : - Unwind (thread), - m_cursors() -{ -} - -uint32_t -UnwindMacOSXFrameBackchain::DoGetFrameCount() -{ - if (m_cursors.empty()) - { - ExecutionContext exe_ctx (m_thread.shared_from_this()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - const ArchSpec& target_arch = target->GetArchitecture (); - // Frame zero should always be supplied by the thread... - exe_ctx.SetFrameSP (m_thread.GetStackFrameAtIndex (0)); - - if (target_arch.GetAddressByteSize() == 8) - GetStackFrameData_x86_64 (exe_ctx); - else - GetStackFrameData_i386 (exe_ctx); - } +UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain(Thread &thread) + : Unwind(thread), m_cursors() {} + +uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() { + if (m_cursors.empty()) { + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + const ArchSpec &target_arch = target->GetArchitecture(); + // Frame zero should always be supplied by the thread... + exe_ctx.SetFrameSP(m_thread.GetStackFrameAtIndex(0)); + + if (target_arch.GetAddressByteSize() == 8) + GetStackFrameData_x86_64(exe_ctx); + else + GetStackFrameData_i386(exe_ctx); } - return m_cursors.size(); + } + return m_cursors.size(); } -bool -UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc) -{ - const uint32_t frame_count = GetFrameCount(); - if (idx < frame_count) - { - if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS) - return false; - if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS) - return false; - - pc = m_cursors[idx].pc; - cfa = m_cursors[idx].fp; - - return true; - } - return false; +bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx, + addr_t &cfa, + addr_t &pc) { + const uint32_t frame_count = GetFrameCount(); + if (idx < frame_count) { + if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS) + return false; + if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS) + return false; + + pc = m_cursors[idx].pc; + cfa = m_cursors[idx].fp; + + return true; + } + return false; } - + lldb::RegisterContextSP -UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame (StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_idx = frame->GetConcreteFrameIndex (); - const uint32_t frame_count = GetFrameCount(); - if (concrete_idx < frame_count) - reg_ctx_sp.reset (new RegisterContextMacOSXFrameBackchain (m_thread, concrete_idx, m_cursors[concrete_idx])); - return reg_ctx_sp; +UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame(StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_idx = frame->GetConcreteFrameIndex(); + const uint32_t frame_count = GetFrameCount(); + if (concrete_idx < frame_count) + reg_ctx_sp.reset(new RegisterContextMacOSXFrameBackchain( + m_thread, concrete_idx, m_cursors[concrete_idx])); + return reg_ctx_sp; } -size_t -UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx) -{ - m_cursors.clear(); - - StackFrame *first_frame = exe_ctx.GetFramePtr(); - - Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) - return 0; - - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - - struct Frame_i386 - { - uint32_t fp; - uint32_t pc; - }; - - RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); - assert (reg_ctx); - - Cursor cursor; - cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS); - cursor.fp = reg_ctx->GetFP (0); - - Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) }; - - m_cursors.push_back(cursor); - - const size_t k_frame_size = sizeof(frame); - Error error; - while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) - { - // Read both the FP and PC (8 bytes) - if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size) - break; - if (frame.pc >= 0x1000) - { - cursor.pc = frame.pc; - cursor.fp = frame.fp; - m_cursors.push_back (cursor); - } +size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( + const ExecutionContext &exe_ctx) { + m_cursors.clear(); + + StackFrame *first_frame = exe_ctx.GetFramePtr(); + + Process *process = exe_ctx.GetProcessPtr(); + if (process == NULL) + return 0; + + std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; + + struct Frame_i386 { + uint32_t fp; + uint32_t pc; + }; + + RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); + assert(reg_ctx); + + Cursor cursor; + cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS); + cursor.fp = reg_ctx->GetFP(0); + + Frame_i386 frame = {static_cast<uint32_t>(cursor.fp), + static_cast<uint32_t>(cursor.pc)}; + + m_cursors.push_back(cursor); + + const size_t k_frame_size = sizeof(frame); + Error error; + while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) { + // Read both the FP and PC (8 bytes) + if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) != + k_frame_size) + break; + if (frame.pc >= 0x1000) { + cursor.pc = frame.pc; + cursor.fp = frame.fp; + m_cursors.push_back(cursor); } - if (!m_cursors.empty()) - { - lldb::addr_t first_frame_pc = m_cursors.front().pc; - if (first_frame_pc != LLDB_INVALID_ADDRESS) - { - const uint32_t resolve_scope = eSymbolContextModule | - eSymbolContextCompUnit | - eSymbolContextFunction | - eSymbolContextSymbol; - - SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = NULL; - AddressRange range; - if (first_frame_sc.function) - addr_range_ptr = &first_frame_sc.function->GetAddressRange(); - else if (first_frame_sc.symbol) - { - range.GetBaseAddress() = first_frame_sc.symbol->GetAddress(); - range.SetByteSize (first_frame_sc.symbol->GetByteSize()); - addr_range_ptr = ⦥ - } - - if (addr_range_ptr) - { - if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress()) - { - // We are at the first instruction, so we can recover the - // previous PC by dereferencing the SP - lldb::addr_t first_frame_sp = reg_ctx->GetSP (0); - // Read the real second frame return address into frame.pc - if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc)) - { - cursor.fp = m_cursors.front().fp; - cursor.pc = frame.pc; // Set the new second frame PC - - // Insert the second frame - m_cursors.insert(m_cursors.begin()+1, cursor); - - m_cursors.front().fp = first_frame_sp; - } - } - } + } + if (!m_cursors.empty()) { + lldb::addr_t first_frame_pc = m_cursors.front().pc; + if (first_frame_pc != LLDB_INVALID_ADDRESS) { + const uint32_t resolve_scope = + eSymbolContextModule | eSymbolContextCompUnit | + eSymbolContextFunction | eSymbolContextSymbol; + + SymbolContext first_frame_sc( + first_frame->GetSymbolContext(resolve_scope)); + const AddressRange *addr_range_ptr = NULL; + AddressRange range; + if (first_frame_sc.function) + addr_range_ptr = &first_frame_sc.function->GetAddressRange(); + else if (first_frame_sc.symbol) { + range.GetBaseAddress() = first_frame_sc.symbol->GetAddress(); + range.SetByteSize(first_frame_sc.symbol->GetByteSize()); + addr_range_ptr = ⦥ + } + + if (addr_range_ptr) { + if (first_frame->GetFrameCodeAddress() == + addr_range_ptr->GetBaseAddress()) { + // We are at the first instruction, so we can recover the + // previous PC by dereferencing the SP + lldb::addr_t first_frame_sp = reg_ctx->GetSP(0); + // Read the real second frame return address into frame.pc + if (first_frame_sp && + process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc), + error) == sizeof(frame.pc)) { + cursor.fp = m_cursors.front().fp; + cursor.pc = frame.pc; // Set the new second frame PC + + // Insert the second frame + m_cursors.insert(m_cursors.begin() + 1, cursor); + + m_cursors.front().fp = first_frame_sp; + } } + } } -// uint32_t i=0; -// printf(" PC FP\n"); -// printf(" ------------------ ------------------ \n"); -// for (i=0; i<m_cursors.size(); ++i) -// { -// printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp); -// } - return m_cursors.size(); + } + // uint32_t i=0; + // printf(" PC FP\n"); + // printf(" ------------------ ------------------ \n"); + // for (i=0; i<m_cursors.size(); ++i) + // { + // printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, + // m_cursors[i].pc, m_cursors[i].fp); + // } + return m_cursors.size(); } +size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( + const ExecutionContext &exe_ctx) { + m_cursors.clear(); -size_t -UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (const ExecutionContext &exe_ctx) -{ - m_cursors.clear(); - - Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) - return 0; - - StackFrame *first_frame = exe_ctx.GetFramePtr(); - - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - - struct Frame_x86_64 - { - uint64_t fp; - uint64_t pc; - }; - - RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); - assert (reg_ctx); - - Cursor cursor; - cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS); - cursor.fp = reg_ctx->GetFP (0); - - Frame_x86_64 frame = { cursor.fp, cursor.pc }; - - m_cursors.push_back(cursor); - Error error; - const size_t k_frame_size = sizeof(frame); - while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) - { - // Read both the FP and PC (16 bytes) - if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size) - break; - - if (frame.pc >= 0x1000) - { - cursor.pc = frame.pc; - cursor.fp = frame.fp; - m_cursors.push_back (cursor); - } + Process *process = exe_ctx.GetProcessPtr(); + if (process == NULL) + return 0; + + StackFrame *first_frame = exe_ctx.GetFramePtr(); + + std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; + + struct Frame_x86_64 { + uint64_t fp; + uint64_t pc; + }; + + RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); + assert(reg_ctx); + + Cursor cursor; + cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS); + cursor.fp = reg_ctx->GetFP(0); + + Frame_x86_64 frame = {cursor.fp, cursor.pc}; + + m_cursors.push_back(cursor); + Error error; + const size_t k_frame_size = sizeof(frame); + while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) { + // Read both the FP and PC (16 bytes) + if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) != + k_frame_size) + break; + + if (frame.pc >= 0x1000) { + cursor.pc = frame.pc; + cursor.fp = frame.fp; + m_cursors.push_back(cursor); } - if (!m_cursors.empty()) - { - lldb::addr_t first_frame_pc = m_cursors.front().pc; - if (first_frame_pc != LLDB_INVALID_ADDRESS) - { - const uint32_t resolve_scope = eSymbolContextModule | - eSymbolContextCompUnit | - eSymbolContextFunction | - eSymbolContextSymbol; - - SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = NULL; - AddressRange range; - if (first_frame_sc.function) - addr_range_ptr = &first_frame_sc.function->GetAddressRange(); - else if (first_frame_sc.symbol) - { - range.GetBaseAddress() = first_frame_sc.symbol->GetAddress(); - range.SetByteSize (first_frame_sc.symbol->GetByteSize()); - addr_range_ptr = ⦥ - } - - if (addr_range_ptr) - { - if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress()) - { - // We are at the first instruction, so we can recover the - // previous PC by dereferencing the SP - lldb::addr_t first_frame_sp = reg_ctx->GetSP (0); - // Read the real second frame return address into frame.pc - if (process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc)) - { - cursor.fp = m_cursors.front().fp; - cursor.pc = frame.pc; // Set the new second frame PC - - // Insert the second frame - m_cursors.insert(m_cursors.begin()+1, cursor); - - m_cursors.front().fp = first_frame_sp; - } - } - } + } + if (!m_cursors.empty()) { + lldb::addr_t first_frame_pc = m_cursors.front().pc; + if (first_frame_pc != LLDB_INVALID_ADDRESS) { + const uint32_t resolve_scope = + eSymbolContextModule | eSymbolContextCompUnit | + eSymbolContextFunction | eSymbolContextSymbol; + + SymbolContext first_frame_sc( + first_frame->GetSymbolContext(resolve_scope)); + const AddressRange *addr_range_ptr = NULL; + AddressRange range; + if (first_frame_sc.function) + addr_range_ptr = &first_frame_sc.function->GetAddressRange(); + else if (first_frame_sc.symbol) { + range.GetBaseAddress() = first_frame_sc.symbol->GetAddress(); + range.SetByteSize(first_frame_sc.symbol->GetByteSize()); + addr_range_ptr = ⦥ + } + + if (addr_range_ptr) { + if (first_frame->GetFrameCodeAddress() == + addr_range_ptr->GetBaseAddress()) { + // We are at the first instruction, so we can recover the + // previous PC by dereferencing the SP + lldb::addr_t first_frame_sp = reg_ctx->GetSP(0); + // Read the real second frame return address into frame.pc + if (process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc), + error) == sizeof(frame.pc)) { + cursor.fp = m_cursors.front().fp; + cursor.pc = frame.pc; // Set the new second frame PC + + // Insert the second frame + m_cursors.insert(m_cursors.begin() + 1, cursor); + + m_cursors.front().fp = first_frame_sp; + } } + } } - return m_cursors.size(); + } + return m_cursors.size(); } - diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h index f195514ed1b..328117a306e 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h @@ -16,55 +16,45 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/Unwind.h" +#include "lldb/lldb-private.h" -class UnwindMacOSXFrameBackchain : public lldb_private::Unwind -{ -public: - UnwindMacOSXFrameBackchain (lldb_private::Thread &thread); +class UnwindMacOSXFrameBackchain : public lldb_private::Unwind { +public: + UnwindMacOSXFrameBackchain(lldb_private::Thread &thread); - ~UnwindMacOSXFrameBackchain() override = default; + ~UnwindMacOSXFrameBackchain() override = default; protected: - void - DoClear() override - { - m_cursors.clear(); - } - - uint32_t - DoGetFrameCount() override; - - bool - DoGetFrameInfoAtIndex(uint32_t frame_idx, - lldb::addr_t& cfa, - lldb::addr_t& pc) override; - - lldb::RegisterContextSP - DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - - friend class RegisterContextMacOSXFrameBackchain; - - struct Cursor - { - lldb::addr_t pc; // Program counter - lldb::addr_t fp; // Frame pointer for us with backchain - }; + void DoClear() override { m_cursors.clear(); } + + uint32_t DoGetFrameCount() override; + + bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &pc) override; + + lldb::RegisterContextSP + DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + + friend class RegisterContextMacOSXFrameBackchain; + + struct Cursor { + lldb::addr_t pc; // Program counter + lldb::addr_t fp; // Frame pointer for us with backchain + }; private: - std::vector<Cursor> m_cursors; + std::vector<Cursor> m_cursors; - size_t - GetStackFrameData_i386 (const lldb_private::ExecutionContext &exe_ctx); + size_t GetStackFrameData_i386(const lldb_private::ExecutionContext &exe_ctx); - size_t - GetStackFrameData_x86_64 (const lldb_private::ExecutionContext &exe_ctx); + size_t + GetStackFrameData_x86_64(const lldb_private::ExecutionContext &exe_ctx); - //------------------------------------------------------------------ - // For UnwindMacOSXFrameBackchain only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain); + //------------------------------------------------------------------ + // For UnwindMacOSXFrameBackchain only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(UnwindMacOSXFrameBackchain); }; #endif // lldb_UnwindMacOSXFrameBackchain_h_ diff --git a/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h index 4d82c10a78e..49473bb885f 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h @@ -10,192 +10,193 @@ #ifndef lldb_arm_register_enums_h #define lldb_arm_register_enums_h -namespace lldb_private -{ - // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - //--------------------------------------------------------------------------- - // Internal codes for all ARM registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_arm = 0, - gpr_r0_arm = k_first_gpr_arm, - gpr_r1_arm, - gpr_r2_arm, - gpr_r3_arm, - gpr_r4_arm, - gpr_r5_arm, - gpr_r6_arm, - gpr_r7_arm, - gpr_r8_arm, - gpr_r9_arm, - gpr_r10_arm, - gpr_r11_arm, - gpr_r12_arm, - gpr_r13_arm, gpr_sp_arm = gpr_r13_arm, - gpr_r14_arm, gpr_lr_arm = gpr_r14_arm, - gpr_r15_arm, gpr_pc_arm = gpr_r15_arm, - gpr_cpsr_arm, +//--------------------------------------------------------------------------- +// Internal codes for all ARM registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_arm = 0, + gpr_r0_arm = k_first_gpr_arm, + gpr_r1_arm, + gpr_r2_arm, + gpr_r3_arm, + gpr_r4_arm, + gpr_r5_arm, + gpr_r6_arm, + gpr_r7_arm, + gpr_r8_arm, + gpr_r9_arm, + gpr_r10_arm, + gpr_r11_arm, + gpr_r12_arm, + gpr_r13_arm, + gpr_sp_arm = gpr_r13_arm, + gpr_r14_arm, + gpr_lr_arm = gpr_r14_arm, + gpr_r15_arm, + gpr_pc_arm = gpr_r15_arm, + gpr_cpsr_arm, - k_last_gpr_arm = gpr_cpsr_arm, + k_last_gpr_arm = gpr_cpsr_arm, - k_first_fpr_arm, - fpu_s0_arm = k_first_fpr_arm, - fpu_s1_arm, - fpu_s2_arm, - fpu_s3_arm, - fpu_s4_arm, - fpu_s5_arm, - fpu_s6_arm, - fpu_s7_arm, - fpu_s8_arm, - fpu_s9_arm, - fpu_s10_arm, - fpu_s11_arm, - fpu_s12_arm, - fpu_s13_arm, - fpu_s14_arm, - fpu_s15_arm, - fpu_s16_arm, - fpu_s17_arm, - fpu_s18_arm, - fpu_s19_arm, - fpu_s20_arm, - fpu_s21_arm, - fpu_s22_arm, - fpu_s23_arm, - fpu_s24_arm, - fpu_s25_arm, - fpu_s26_arm, - fpu_s27_arm, - fpu_s28_arm, - fpu_s29_arm, - fpu_s30_arm, - fpu_s31_arm, - fpu_fpscr_arm, - fpu_d0_arm, - fpu_d1_arm, - fpu_d2_arm, - fpu_d3_arm, - fpu_d4_arm, - fpu_d5_arm, - fpu_d6_arm, - fpu_d7_arm, - fpu_d8_arm, - fpu_d9_arm, - fpu_d10_arm, - fpu_d11_arm, - fpu_d12_arm, - fpu_d13_arm, - fpu_d14_arm, - fpu_d15_arm, - fpu_d16_arm, - fpu_d17_arm, - fpu_d18_arm, - fpu_d19_arm, - fpu_d20_arm, - fpu_d21_arm, - fpu_d22_arm, - fpu_d23_arm, - fpu_d24_arm, - fpu_d25_arm, - fpu_d26_arm, - fpu_d27_arm, - fpu_d28_arm, - fpu_d29_arm, - fpu_d30_arm, - fpu_d31_arm, - fpu_q0_arm, - fpu_q1_arm, - fpu_q2_arm, - fpu_q3_arm, - fpu_q4_arm, - fpu_q5_arm, - fpu_q6_arm, - fpu_q7_arm, - fpu_q8_arm, - fpu_q9_arm, - fpu_q10_arm, - fpu_q11_arm, - fpu_q12_arm, - fpu_q13_arm, - fpu_q14_arm, - fpu_q15_arm, - k_last_fpr_arm = fpu_q15_arm, - exc_exception_arm, - exc_fsr_arm, - exc_far_arm, + k_first_fpr_arm, + fpu_s0_arm = k_first_fpr_arm, + fpu_s1_arm, + fpu_s2_arm, + fpu_s3_arm, + fpu_s4_arm, + fpu_s5_arm, + fpu_s6_arm, + fpu_s7_arm, + fpu_s8_arm, + fpu_s9_arm, + fpu_s10_arm, + fpu_s11_arm, + fpu_s12_arm, + fpu_s13_arm, + fpu_s14_arm, + fpu_s15_arm, + fpu_s16_arm, + fpu_s17_arm, + fpu_s18_arm, + fpu_s19_arm, + fpu_s20_arm, + fpu_s21_arm, + fpu_s22_arm, + fpu_s23_arm, + fpu_s24_arm, + fpu_s25_arm, + fpu_s26_arm, + fpu_s27_arm, + fpu_s28_arm, + fpu_s29_arm, + fpu_s30_arm, + fpu_s31_arm, + fpu_fpscr_arm, + fpu_d0_arm, + fpu_d1_arm, + fpu_d2_arm, + fpu_d3_arm, + fpu_d4_arm, + fpu_d5_arm, + fpu_d6_arm, + fpu_d7_arm, + fpu_d8_arm, + fpu_d9_arm, + fpu_d10_arm, + fpu_d11_arm, + fpu_d12_arm, + fpu_d13_arm, + fpu_d14_arm, + fpu_d15_arm, + fpu_d16_arm, + fpu_d17_arm, + fpu_d18_arm, + fpu_d19_arm, + fpu_d20_arm, + fpu_d21_arm, + fpu_d22_arm, + fpu_d23_arm, + fpu_d24_arm, + fpu_d25_arm, + fpu_d26_arm, + fpu_d27_arm, + fpu_d28_arm, + fpu_d29_arm, + fpu_d30_arm, + fpu_d31_arm, + fpu_q0_arm, + fpu_q1_arm, + fpu_q2_arm, + fpu_q3_arm, + fpu_q4_arm, + fpu_q5_arm, + fpu_q6_arm, + fpu_q7_arm, + fpu_q8_arm, + fpu_q9_arm, + fpu_q10_arm, + fpu_q11_arm, + fpu_q12_arm, + fpu_q13_arm, + fpu_q14_arm, + fpu_q15_arm, + k_last_fpr_arm = fpu_q15_arm, + exc_exception_arm, + exc_fsr_arm, + exc_far_arm, - dbg_bvr0_arm, - dbg_bvr1_arm, - dbg_bvr2_arm, - dbg_bvr3_arm, - dbg_bvr4_arm, - dbg_bvr5_arm, - dbg_bvr6_arm, - dbg_bvr7_arm, - dbg_bvr8_arm, - dbg_bvr9_arm, - dbg_bvr10_arm, - dbg_bvr11_arm, - dbg_bvr12_arm, - dbg_bvr13_arm, - dbg_bvr14_arm, - dbg_bvr15_arm, - dbg_bcr0_arm, - dbg_bcr1_arm, - dbg_bcr2_arm, - dbg_bcr3_arm, - dbg_bcr4_arm, - dbg_bcr5_arm, - dbg_bcr6_arm, - dbg_bcr7_arm, - dbg_bcr8_arm, - dbg_bcr9_arm, - dbg_bcr10_arm, - dbg_bcr11_arm, - dbg_bcr12_arm, - dbg_bcr13_arm, - dbg_bcr14_arm, - dbg_bcr15_arm, - dbg_wvr0_arm, - dbg_wvr1_arm, - dbg_wvr2_arm, - dbg_wvr3_arm, - dbg_wvr4_arm, - dbg_wvr5_arm, - dbg_wvr6_arm, - dbg_wvr7_arm, - dbg_wvr8_arm, - dbg_wvr9_arm, - dbg_wvr10_arm, - dbg_wvr11_arm, - dbg_wvr12_arm, - dbg_wvr13_arm, - dbg_wvr14_arm, - dbg_wvr15_arm, - dbg_wcr0_arm, - dbg_wcr1_arm, - dbg_wcr2_arm, - dbg_wcr3_arm, - dbg_wcr4_arm, - dbg_wcr5_arm, - dbg_wcr6_arm, - dbg_wcr7_arm, - dbg_wcr8_arm, - dbg_wcr9_arm, - dbg_wcr10_arm, - dbg_wcr11_arm, - dbg_wcr12_arm, - dbg_wcr13_arm, - dbg_wcr14_arm, - dbg_wcr15_arm, + dbg_bvr0_arm, + dbg_bvr1_arm, + dbg_bvr2_arm, + dbg_bvr3_arm, + dbg_bvr4_arm, + dbg_bvr5_arm, + dbg_bvr6_arm, + dbg_bvr7_arm, + dbg_bvr8_arm, + dbg_bvr9_arm, + dbg_bvr10_arm, + dbg_bvr11_arm, + dbg_bvr12_arm, + dbg_bvr13_arm, + dbg_bvr14_arm, + dbg_bvr15_arm, + dbg_bcr0_arm, + dbg_bcr1_arm, + dbg_bcr2_arm, + dbg_bcr3_arm, + dbg_bcr4_arm, + dbg_bcr5_arm, + dbg_bcr6_arm, + dbg_bcr7_arm, + dbg_bcr8_arm, + dbg_bcr9_arm, + dbg_bcr10_arm, + dbg_bcr11_arm, + dbg_bcr12_arm, + dbg_bcr13_arm, + dbg_bcr14_arm, + dbg_bcr15_arm, + dbg_wvr0_arm, + dbg_wvr1_arm, + dbg_wvr2_arm, + dbg_wvr3_arm, + dbg_wvr4_arm, + dbg_wvr5_arm, + dbg_wvr6_arm, + dbg_wvr7_arm, + dbg_wvr8_arm, + dbg_wvr9_arm, + dbg_wvr10_arm, + dbg_wvr11_arm, + dbg_wvr12_arm, + dbg_wvr13_arm, + dbg_wvr14_arm, + dbg_wvr15_arm, + dbg_wcr0_arm, + dbg_wcr1_arm, + dbg_wcr2_arm, + dbg_wcr3_arm, + dbg_wcr4_arm, + dbg_wcr5_arm, + dbg_wcr6_arm, + dbg_wcr7_arm, + dbg_wcr8_arm, + dbg_wcr9_arm, + dbg_wcr10_arm, + dbg_wcr11_arm, + dbg_wcr12_arm, + dbg_wcr13_arm, + dbg_wcr14_arm, + dbg_wcr15_arm, - k_num_registers_arm, - k_num_gpr_registers_arm = k_last_gpr_arm - k_first_gpr_arm + 1, - k_num_fpr_registers_arm = k_last_fpr_arm - k_first_fpr_arm + 1 - }; + k_num_registers_arm, + k_num_gpr_registers_arm = k_last_gpr_arm - k_first_gpr_arm + 1, + k_num_fpr_registers_arm = k_last_fpr_arm - k_first_fpr_arm + 1 +}; } #endif // #ifndef lldb_arm64_register_enums_h diff --git a/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h index a0c0db0f278..425a49ab2b0 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h @@ -10,163 +10,161 @@ #ifndef lldb_arm64_register_enums_h #define lldb_arm64_register_enums_h -namespace lldb_private -{ - // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - //--------------------------------------------------------------------------- - // Internal codes for all ARM64 registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_arm64, - gpr_x0_arm64 = k_first_gpr_arm64, - gpr_x1_arm64, - gpr_x2_arm64, - gpr_x3_arm64, - gpr_x4_arm64, - gpr_x5_arm64, - gpr_x6_arm64, - gpr_x7_arm64, - gpr_x8_arm64, - gpr_x9_arm64, - gpr_x10_arm64, - gpr_x11_arm64, - gpr_x12_arm64, - gpr_x13_arm64, - gpr_x14_arm64, - gpr_x15_arm64, - gpr_x16_arm64, - gpr_x17_arm64, - gpr_x18_arm64, - gpr_x19_arm64, - gpr_x20_arm64, - gpr_x21_arm64, - gpr_x22_arm64, - gpr_x23_arm64, - gpr_x24_arm64, - gpr_x25_arm64, - gpr_x26_arm64, - gpr_x27_arm64, - gpr_x28_arm64, - gpr_fp_arm64, - gpr_lr_arm64, - gpr_sp_arm64, - gpr_pc_arm64, - gpr_cpsr_arm64, +//--------------------------------------------------------------------------- +// Internal codes for all ARM64 registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_arm64, + gpr_x0_arm64 = k_first_gpr_arm64, + gpr_x1_arm64, + gpr_x2_arm64, + gpr_x3_arm64, + gpr_x4_arm64, + gpr_x5_arm64, + gpr_x6_arm64, + gpr_x7_arm64, + gpr_x8_arm64, + gpr_x9_arm64, + gpr_x10_arm64, + gpr_x11_arm64, + gpr_x12_arm64, + gpr_x13_arm64, + gpr_x14_arm64, + gpr_x15_arm64, + gpr_x16_arm64, + gpr_x17_arm64, + gpr_x18_arm64, + gpr_x19_arm64, + gpr_x20_arm64, + gpr_x21_arm64, + gpr_x22_arm64, + gpr_x23_arm64, + gpr_x24_arm64, + gpr_x25_arm64, + gpr_x26_arm64, + gpr_x27_arm64, + gpr_x28_arm64, + gpr_fp_arm64, + gpr_lr_arm64, + gpr_sp_arm64, + gpr_pc_arm64, + gpr_cpsr_arm64, - k_last_gpr_arm64 = gpr_cpsr_arm64, + k_last_gpr_arm64 = gpr_cpsr_arm64, - k_first_fpr_arm64, - fpu_v0_arm64 = k_first_fpr_arm64, - fpu_v1_arm64, - fpu_v2_arm64, - fpu_v3_arm64, - fpu_v4_arm64, - fpu_v5_arm64, - fpu_v6_arm64, - fpu_v7_arm64, - fpu_v8_arm64, - fpu_v9_arm64, - fpu_v10_arm64, - fpu_v11_arm64, - fpu_v12_arm64, - fpu_v13_arm64, - fpu_v14_arm64, - fpu_v15_arm64, - fpu_v16_arm64, - fpu_v17_arm64, - fpu_v18_arm64, - fpu_v19_arm64, - fpu_v20_arm64, - fpu_v21_arm64, - fpu_v22_arm64, - fpu_v23_arm64, - fpu_v24_arm64, - fpu_v25_arm64, - fpu_v26_arm64, - fpu_v27_arm64, - fpu_v28_arm64, - fpu_v29_arm64, - fpu_v30_arm64, - fpu_v31_arm64, - fpu_fpsr_arm64, - fpu_fpcr_arm64, - k_last_fpr_arm64 = fpu_fpcr_arm64, + k_first_fpr_arm64, + fpu_v0_arm64 = k_first_fpr_arm64, + fpu_v1_arm64, + fpu_v2_arm64, + fpu_v3_arm64, + fpu_v4_arm64, + fpu_v5_arm64, + fpu_v6_arm64, + fpu_v7_arm64, + fpu_v8_arm64, + fpu_v9_arm64, + fpu_v10_arm64, + fpu_v11_arm64, + fpu_v12_arm64, + fpu_v13_arm64, + fpu_v14_arm64, + fpu_v15_arm64, + fpu_v16_arm64, + fpu_v17_arm64, + fpu_v18_arm64, + fpu_v19_arm64, + fpu_v20_arm64, + fpu_v21_arm64, + fpu_v22_arm64, + fpu_v23_arm64, + fpu_v24_arm64, + fpu_v25_arm64, + fpu_v26_arm64, + fpu_v27_arm64, + fpu_v28_arm64, + fpu_v29_arm64, + fpu_v30_arm64, + fpu_v31_arm64, + fpu_fpsr_arm64, + fpu_fpcr_arm64, + k_last_fpr_arm64 = fpu_fpcr_arm64, - exc_far_arm64, - exc_esr_arm64, - exc_exception_arm64, + exc_far_arm64, + exc_esr_arm64, + exc_exception_arm64, - dbg_bvr0_arm64, - dbg_bvr1_arm64, - dbg_bvr2_arm64, - dbg_bvr3_arm64, - dbg_bvr4_arm64, - dbg_bvr5_arm64, - dbg_bvr6_arm64, - dbg_bvr7_arm64, - dbg_bvr8_arm64, - dbg_bvr9_arm64, - dbg_bvr10_arm64, - dbg_bvr11_arm64, - dbg_bvr12_arm64, - dbg_bvr13_arm64, - dbg_bvr14_arm64, - dbg_bvr15_arm64, - dbg_bcr0_arm64, - dbg_bcr1_arm64, - dbg_bcr2_arm64, - dbg_bcr3_arm64, - dbg_bcr4_arm64, - dbg_bcr5_arm64, - dbg_bcr6_arm64, - dbg_bcr7_arm64, - dbg_bcr8_arm64, - dbg_bcr9_arm64, - dbg_bcr10_arm64, - dbg_bcr11_arm64, - dbg_bcr12_arm64, - dbg_bcr13_arm64, - dbg_bcr14_arm64, - dbg_bcr15_arm64, - dbg_wvr0_arm64, - dbg_wvr1_arm64, - dbg_wvr2_arm64, - dbg_wvr3_arm64, - dbg_wvr4_arm64, - dbg_wvr5_arm64, - dbg_wvr6_arm64, - dbg_wvr7_arm64, - dbg_wvr8_arm64, - dbg_wvr9_arm64, - dbg_wvr10_arm64, - dbg_wvr11_arm64, - dbg_wvr12_arm64, - dbg_wvr13_arm64, - dbg_wvr14_arm64, - dbg_wvr15_arm64, - dbg_wcr0_arm64, - dbg_wcr1_arm64, - dbg_wcr2_arm64, - dbg_wcr3_arm64, - dbg_wcr4_arm64, - dbg_wcr5_arm64, - dbg_wcr6_arm64, - dbg_wcr7_arm64, - dbg_wcr8_arm64, - dbg_wcr9_arm64, - dbg_wcr10_arm64, - dbg_wcr11_arm64, - dbg_wcr12_arm64, - dbg_wcr13_arm64, - dbg_wcr14_arm64, - dbg_wcr15_arm64, + dbg_bvr0_arm64, + dbg_bvr1_arm64, + dbg_bvr2_arm64, + dbg_bvr3_arm64, + dbg_bvr4_arm64, + dbg_bvr5_arm64, + dbg_bvr6_arm64, + dbg_bvr7_arm64, + dbg_bvr8_arm64, + dbg_bvr9_arm64, + dbg_bvr10_arm64, + dbg_bvr11_arm64, + dbg_bvr12_arm64, + dbg_bvr13_arm64, + dbg_bvr14_arm64, + dbg_bvr15_arm64, + dbg_bcr0_arm64, + dbg_bcr1_arm64, + dbg_bcr2_arm64, + dbg_bcr3_arm64, + dbg_bcr4_arm64, + dbg_bcr5_arm64, + dbg_bcr6_arm64, + dbg_bcr7_arm64, + dbg_bcr8_arm64, + dbg_bcr9_arm64, + dbg_bcr10_arm64, + dbg_bcr11_arm64, + dbg_bcr12_arm64, + dbg_bcr13_arm64, + dbg_bcr14_arm64, + dbg_bcr15_arm64, + dbg_wvr0_arm64, + dbg_wvr1_arm64, + dbg_wvr2_arm64, + dbg_wvr3_arm64, + dbg_wvr4_arm64, + dbg_wvr5_arm64, + dbg_wvr6_arm64, + dbg_wvr7_arm64, + dbg_wvr8_arm64, + dbg_wvr9_arm64, + dbg_wvr10_arm64, + dbg_wvr11_arm64, + dbg_wvr12_arm64, + dbg_wvr13_arm64, + dbg_wvr14_arm64, + dbg_wvr15_arm64, + dbg_wcr0_arm64, + dbg_wcr1_arm64, + dbg_wcr2_arm64, + dbg_wcr3_arm64, + dbg_wcr4_arm64, + dbg_wcr5_arm64, + dbg_wcr6_arm64, + dbg_wcr7_arm64, + dbg_wcr8_arm64, + dbg_wcr9_arm64, + dbg_wcr10_arm64, + dbg_wcr11_arm64, + dbg_wcr12_arm64, + dbg_wcr13_arm64, + dbg_wcr14_arm64, + dbg_wcr15_arm64, - k_num_registers_arm64, - k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1, - k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1 - }; + k_num_registers_arm64, + k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1, + k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1 +}; } #endif // #ifndef lldb_arm64_register_enums_h diff --git a/lldb/source/Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h index 69dc9efac32..4db52854232 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h @@ -1,4 +1,5 @@ -//===-- lldb-mips-frebsd-register-enums.h -------------------------------*- C++ -*-===// +//===-- lldb-mips-frebsd-register-enums.h -------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,61 +11,59 @@ #ifndef lldb_mips_freebsd_register_enums_h #define lldb_mips_freebsd_register_enums_h -namespace lldb_private -{ - // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - //--------------------------------------------------------------------------- - // Internal codes for all mips registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_mips64, - gpr_zero_mips64 = k_first_gpr_mips64, - gpr_r1_mips64, - gpr_r2_mips64, - gpr_r3_mips64, - gpr_r4_mips64, - gpr_r5_mips64, - gpr_r6_mips64, - gpr_r7_mips64, - gpr_r8_mips64, - gpr_r9_mips64, - gpr_r10_mips64, - gpr_r11_mips64, - gpr_r12_mips64, - gpr_r13_mips64, - gpr_r14_mips64, - gpr_r15_mips64, - gpr_r16_mips64, - gpr_r17_mips64, - gpr_r18_mips64, - gpr_r19_mips64, - gpr_r20_mips64, - gpr_r21_mips64, - gpr_r22_mips64, - gpr_r23_mips64, - gpr_r24_mips64, - gpr_r25_mips64, - gpr_r26_mips64, - gpr_r27_mips64, - gpr_gp_mips64, - gpr_sp_mips64, - gpr_r30_mips64, - gpr_ra_mips64, - gpr_sr_mips64, - gpr_mullo_mips64, - gpr_mulhi_mips64, - gpr_badvaddr_mips64, - gpr_cause_mips64, - gpr_pc_mips64, - gpr_ic_mips64, - gpr_dummy_mips64, - k_last_gpr_mips64 = gpr_dummy_mips64, +//--------------------------------------------------------------------------- +// Internal codes for all mips registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_mips64, + gpr_zero_mips64 = k_first_gpr_mips64, + gpr_r1_mips64, + gpr_r2_mips64, + gpr_r3_mips64, + gpr_r4_mips64, + gpr_r5_mips64, + gpr_r6_mips64, + gpr_r7_mips64, + gpr_r8_mips64, + gpr_r9_mips64, + gpr_r10_mips64, + gpr_r11_mips64, + gpr_r12_mips64, + gpr_r13_mips64, + gpr_r14_mips64, + gpr_r15_mips64, + gpr_r16_mips64, + gpr_r17_mips64, + gpr_r18_mips64, + gpr_r19_mips64, + gpr_r20_mips64, + gpr_r21_mips64, + gpr_r22_mips64, + gpr_r23_mips64, + gpr_r24_mips64, + gpr_r25_mips64, + gpr_r26_mips64, + gpr_r27_mips64, + gpr_gp_mips64, + gpr_sp_mips64, + gpr_r30_mips64, + gpr_ra_mips64, + gpr_sr_mips64, + gpr_mullo_mips64, + gpr_mulhi_mips64, + gpr_badvaddr_mips64, + gpr_cause_mips64, + gpr_pc_mips64, + gpr_ic_mips64, + gpr_dummy_mips64, + k_last_gpr_mips64 = gpr_dummy_mips64, - k_num_registers_mips64, + k_num_registers_mips64, - k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1 - }; + k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1 +}; } #endif // #ifndef lldb_mips_freebsd_register_enums_h diff --git a/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h index 6c00025edfd..2875695fb4d 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h @@ -1,4 +1,5 @@ -//===-- lldb-mips-linux-register-enums.h -------------------------------*- C++ -*-===// +//===-- lldb-mips-linux-register-enums.h -------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,276 +11,277 @@ #ifndef lldb_mips_linux_register_enums_h #define lldb_mips_linux_register_enums_h -namespace lldb_private -{ - // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - //--------------------------------------------------------------------------- - // Internal codes for all mips registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_mips, - gpr_zero_mips = k_first_gpr_mips, - gpr_r1_mips, - gpr_r2_mips, - gpr_r3_mips, - gpr_r4_mips, - gpr_r5_mips, - gpr_r6_mips, - gpr_r7_mips, - gpr_r8_mips, - gpr_r9_mips, - gpr_r10_mips, - gpr_r11_mips, - gpr_r12_mips, - gpr_r13_mips, - gpr_r14_mips, - gpr_r15_mips, - gpr_r16_mips, - gpr_r17_mips, - gpr_r18_mips, - gpr_r19_mips, - gpr_r20_mips, - gpr_r21_mips, - gpr_r22_mips, - gpr_r23_mips, - gpr_r24_mips, - gpr_r25_mips, - gpr_r26_mips, - gpr_r27_mips, - gpr_gp_mips, - gpr_sp_mips, - gpr_r30_mips, - gpr_ra_mips, - gpr_sr_mips, - gpr_mullo_mips, - gpr_mulhi_mips, - gpr_badvaddr_mips, - gpr_cause_mips, - gpr_pc_mips, - gpr_config5_mips, +//--------------------------------------------------------------------------- +// Internal codes for all mips registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_mips, + gpr_zero_mips = k_first_gpr_mips, + gpr_r1_mips, + gpr_r2_mips, + gpr_r3_mips, + gpr_r4_mips, + gpr_r5_mips, + gpr_r6_mips, + gpr_r7_mips, + gpr_r8_mips, + gpr_r9_mips, + gpr_r10_mips, + gpr_r11_mips, + gpr_r12_mips, + gpr_r13_mips, + gpr_r14_mips, + gpr_r15_mips, + gpr_r16_mips, + gpr_r17_mips, + gpr_r18_mips, + gpr_r19_mips, + gpr_r20_mips, + gpr_r21_mips, + gpr_r22_mips, + gpr_r23_mips, + gpr_r24_mips, + gpr_r25_mips, + gpr_r26_mips, + gpr_r27_mips, + gpr_gp_mips, + gpr_sp_mips, + gpr_r30_mips, + gpr_ra_mips, + gpr_sr_mips, + gpr_mullo_mips, + gpr_mulhi_mips, + gpr_badvaddr_mips, + gpr_cause_mips, + gpr_pc_mips, + gpr_config5_mips, - k_last_gpr_mips = gpr_config5_mips, + k_last_gpr_mips = gpr_config5_mips, - k_first_fpr_mips, - fpr_f0_mips = k_first_fpr_mips, - fpr_f1_mips, - fpr_f2_mips, - fpr_f3_mips, - fpr_f4_mips, - fpr_f5_mips, - fpr_f6_mips, - fpr_f7_mips, - fpr_f8_mips, - fpr_f9_mips, - fpr_f10_mips, - fpr_f11_mips, - fpr_f12_mips, - fpr_f13_mips, - fpr_f14_mips, - fpr_f15_mips, - fpr_f16_mips, - fpr_f17_mips, - fpr_f18_mips, - fpr_f19_mips, - fpr_f20_mips, - fpr_f21_mips, - fpr_f22_mips, - fpr_f23_mips, - fpr_f24_mips, - fpr_f25_mips, - fpr_f26_mips, - fpr_f27_mips, - fpr_f28_mips, - fpr_f29_mips, - fpr_f30_mips, - fpr_f31_mips, - fpr_fcsr_mips, - fpr_fir_mips, - fpr_config5_mips, - k_last_fpr_mips = fpr_config5_mips, + k_first_fpr_mips, + fpr_f0_mips = k_first_fpr_mips, + fpr_f1_mips, + fpr_f2_mips, + fpr_f3_mips, + fpr_f4_mips, + fpr_f5_mips, + fpr_f6_mips, + fpr_f7_mips, + fpr_f8_mips, + fpr_f9_mips, + fpr_f10_mips, + fpr_f11_mips, + fpr_f12_mips, + fpr_f13_mips, + fpr_f14_mips, + fpr_f15_mips, + fpr_f16_mips, + fpr_f17_mips, + fpr_f18_mips, + fpr_f19_mips, + fpr_f20_mips, + fpr_f21_mips, + fpr_f22_mips, + fpr_f23_mips, + fpr_f24_mips, + fpr_f25_mips, + fpr_f26_mips, + fpr_f27_mips, + fpr_f28_mips, + fpr_f29_mips, + fpr_f30_mips, + fpr_f31_mips, + fpr_fcsr_mips, + fpr_fir_mips, + fpr_config5_mips, + k_last_fpr_mips = fpr_config5_mips, - k_first_msa_mips, - msa_w0_mips = k_first_msa_mips, - msa_w1_mips, - msa_w2_mips, - msa_w3_mips, - msa_w4_mips, - msa_w5_mips, - msa_w6_mips, - msa_w7_mips, - msa_w8_mips, - msa_w9_mips, - msa_w10_mips, - msa_w11_mips, - msa_w12_mips, - msa_w13_mips, - msa_w14_mips, - msa_w15_mips, - msa_w16_mips, - msa_w17_mips, - msa_w18_mips, - msa_w19_mips, - msa_w20_mips, - msa_w21_mips, - msa_w22_mips, - msa_w23_mips, - msa_w24_mips, - msa_w25_mips, - msa_w26_mips, - msa_w27_mips, - msa_w28_mips, - msa_w29_mips, - msa_w30_mips, - msa_w31_mips, - msa_fcsr_mips, - msa_fir_mips, - msa_mcsr_mips, - msa_mir_mips, - msa_config5_mips, - k_last_msa_mips = msa_config5_mips, + k_first_msa_mips, + msa_w0_mips = k_first_msa_mips, + msa_w1_mips, + msa_w2_mips, + msa_w3_mips, + msa_w4_mips, + msa_w5_mips, + msa_w6_mips, + msa_w7_mips, + msa_w8_mips, + msa_w9_mips, + msa_w10_mips, + msa_w11_mips, + msa_w12_mips, + msa_w13_mips, + msa_w14_mips, + msa_w15_mips, + msa_w16_mips, + msa_w17_mips, + msa_w18_mips, + msa_w19_mips, + msa_w20_mips, + msa_w21_mips, + msa_w22_mips, + msa_w23_mips, + msa_w24_mips, + msa_w25_mips, + msa_w26_mips, + msa_w27_mips, + msa_w28_mips, + msa_w29_mips, + msa_w30_mips, + msa_w31_mips, + msa_fcsr_mips, + msa_fir_mips, + msa_mcsr_mips, + msa_mir_mips, + msa_config5_mips, + k_last_msa_mips = msa_config5_mips, - k_num_registers_mips, + k_num_registers_mips, - k_num_gpr_registers_mips = k_last_gpr_mips - k_first_gpr_mips + 1, - k_num_fpr_registers_mips = k_last_fpr_mips - k_first_fpr_mips + 1, - k_num_msa_registers_mips = k_last_msa_mips - k_first_msa_mips + 1, - k_num_user_registers_mips = k_num_gpr_registers_mips + k_num_fpr_registers_mips + k_num_msa_registers_mips - }; + k_num_gpr_registers_mips = k_last_gpr_mips - k_first_gpr_mips + 1, + k_num_fpr_registers_mips = k_last_fpr_mips - k_first_fpr_mips + 1, + k_num_msa_registers_mips = k_last_msa_mips - k_first_msa_mips + 1, + k_num_user_registers_mips = k_num_gpr_registers_mips + + k_num_fpr_registers_mips + + k_num_msa_registers_mips +}; - //--------------------------------------------------------------------------- - // Internal codes for all mips64 registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_mips64, - gpr_zero_mips64 = k_first_gpr_mips64, - gpr_r1_mips64, - gpr_r2_mips64, - gpr_r3_mips64, - gpr_r4_mips64, - gpr_r5_mips64, - gpr_r6_mips64, - gpr_r7_mips64, - gpr_r8_mips64, - gpr_r9_mips64, - gpr_r10_mips64, - gpr_r11_mips64, - gpr_r12_mips64, - gpr_r13_mips64, - gpr_r14_mips64, - gpr_r15_mips64, - gpr_r16_mips64, - gpr_r17_mips64, - gpr_r18_mips64, - gpr_r19_mips64, - gpr_r20_mips64, - gpr_r21_mips64, - gpr_r22_mips64, - gpr_r23_mips64, - gpr_r24_mips64, - gpr_r25_mips64, - gpr_r26_mips64, - gpr_r27_mips64, - gpr_gp_mips64, - gpr_sp_mips64, - gpr_r30_mips64, - gpr_ra_mips64, - gpr_sr_mips64, - gpr_mullo_mips64, - gpr_mulhi_mips64, - gpr_badvaddr_mips64, - gpr_cause_mips64, - gpr_pc_mips64, - gpr_config5_mips64, - k_last_gpr_mips64 = gpr_config5_mips64, +//--------------------------------------------------------------------------- +// Internal codes for all mips64 registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_mips64, + gpr_zero_mips64 = k_first_gpr_mips64, + gpr_r1_mips64, + gpr_r2_mips64, + gpr_r3_mips64, + gpr_r4_mips64, + gpr_r5_mips64, + gpr_r6_mips64, + gpr_r7_mips64, + gpr_r8_mips64, + gpr_r9_mips64, + gpr_r10_mips64, + gpr_r11_mips64, + gpr_r12_mips64, + gpr_r13_mips64, + gpr_r14_mips64, + gpr_r15_mips64, + gpr_r16_mips64, + gpr_r17_mips64, + gpr_r18_mips64, + gpr_r19_mips64, + gpr_r20_mips64, + gpr_r21_mips64, + gpr_r22_mips64, + gpr_r23_mips64, + gpr_r24_mips64, + gpr_r25_mips64, + gpr_r26_mips64, + gpr_r27_mips64, + gpr_gp_mips64, + gpr_sp_mips64, + gpr_r30_mips64, + gpr_ra_mips64, + gpr_sr_mips64, + gpr_mullo_mips64, + gpr_mulhi_mips64, + gpr_badvaddr_mips64, + gpr_cause_mips64, + gpr_pc_mips64, + gpr_config5_mips64, + k_last_gpr_mips64 = gpr_config5_mips64, - k_first_fpr_mips64, - fpr_f0_mips64 = k_first_fpr_mips64, - fpr_f1_mips64, - fpr_f2_mips64, - fpr_f3_mips64, - fpr_f4_mips64, - fpr_f5_mips64, - fpr_f6_mips64, - fpr_f7_mips64, - fpr_f8_mips64, - fpr_f9_mips64, - fpr_f10_mips64, - fpr_f11_mips64, - fpr_f12_mips64, - fpr_f13_mips64, - fpr_f14_mips64, - fpr_f15_mips64, - fpr_f16_mips64, - fpr_f17_mips64, - fpr_f18_mips64, - fpr_f19_mips64, - fpr_f20_mips64, - fpr_f21_mips64, - fpr_f22_mips64, - fpr_f23_mips64, - fpr_f24_mips64, - fpr_f25_mips64, - fpr_f26_mips64, - fpr_f27_mips64, - fpr_f28_mips64, - fpr_f29_mips64, - fpr_f30_mips64, - fpr_f31_mips64, - fpr_fcsr_mips64, - fpr_fir_mips64, - fpr_config5_mips64, - k_last_fpr_mips64 = fpr_config5_mips64, + k_first_fpr_mips64, + fpr_f0_mips64 = k_first_fpr_mips64, + fpr_f1_mips64, + fpr_f2_mips64, + fpr_f3_mips64, + fpr_f4_mips64, + fpr_f5_mips64, + fpr_f6_mips64, + fpr_f7_mips64, + fpr_f8_mips64, + fpr_f9_mips64, + fpr_f10_mips64, + fpr_f11_mips64, + fpr_f12_mips64, + fpr_f13_mips64, + fpr_f14_mips64, + fpr_f15_mips64, + fpr_f16_mips64, + fpr_f17_mips64, + fpr_f18_mips64, + fpr_f19_mips64, + fpr_f20_mips64, + fpr_f21_mips64, + fpr_f22_mips64, + fpr_f23_mips64, + fpr_f24_mips64, + fpr_f25_mips64, + fpr_f26_mips64, + fpr_f27_mips64, + fpr_f28_mips64, + fpr_f29_mips64, + fpr_f30_mips64, + fpr_f31_mips64, + fpr_fcsr_mips64, + fpr_fir_mips64, + fpr_config5_mips64, + k_last_fpr_mips64 = fpr_config5_mips64, - k_first_msa_mips64, - msa_w0_mips64 = k_first_msa_mips64, - msa_w1_mips64, - msa_w2_mips64, - msa_w3_mips64, - msa_w4_mips64, - msa_w5_mips64, - msa_w6_mips64, - msa_w7_mips64, - msa_w8_mips64, - msa_w9_mips64, - msa_w10_mips64, - msa_w11_mips64, - msa_w12_mips64, - msa_w13_mips64, - msa_w14_mips64, - msa_w15_mips64, - msa_w16_mips64, - msa_w17_mips64, - msa_w18_mips64, - msa_w19_mips64, - msa_w20_mips64, - msa_w21_mips64, - msa_w22_mips64, - msa_w23_mips64, - msa_w24_mips64, - msa_w25_mips64, - msa_w26_mips64, - msa_w27_mips64, - msa_w28_mips64, - msa_w29_mips64, - msa_w30_mips64, - msa_w31_mips64, - msa_fcsr_mips64, - msa_fir_mips64, - msa_mcsr_mips64, - msa_mir_mips64, - msa_config5_mips64, - k_last_msa_mips64 = msa_config5_mips64, + k_first_msa_mips64, + msa_w0_mips64 = k_first_msa_mips64, + msa_w1_mips64, + msa_w2_mips64, + msa_w3_mips64, + msa_w4_mips64, + msa_w5_mips64, + msa_w6_mips64, + msa_w7_mips64, + msa_w8_mips64, + msa_w9_mips64, + msa_w10_mips64, + msa_w11_mips64, + msa_w12_mips64, + msa_w13_mips64, + msa_w14_mips64, + msa_w15_mips64, + msa_w16_mips64, + msa_w17_mips64, + msa_w18_mips64, + msa_w19_mips64, + msa_w20_mips64, + msa_w21_mips64, + msa_w22_mips64, + msa_w23_mips64, + msa_w24_mips64, + msa_w25_mips64, + msa_w26_mips64, + msa_w27_mips64, + msa_w28_mips64, + msa_w29_mips64, + msa_w30_mips64, + msa_w31_mips64, + msa_fcsr_mips64, + msa_fir_mips64, + msa_mcsr_mips64, + msa_mir_mips64, + msa_config5_mips64, + k_last_msa_mips64 = msa_config5_mips64, - k_num_registers_mips64, + k_num_registers_mips64, - k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1, - k_num_fpr_registers_mips64 = k_last_fpr_mips64 - k_first_fpr_mips64 + 1, - k_num_msa_registers_mips64 = k_last_msa_mips64 - k_first_msa_mips64 + 1, - k_num_user_registers_mips64 = k_num_gpr_registers_mips64 + k_num_fpr_registers_mips64 + k_num_msa_registers_mips64 - }; + k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1, + k_num_fpr_registers_mips64 = k_last_fpr_mips64 - k_first_fpr_mips64 + 1, + k_num_msa_registers_mips64 = k_last_msa_mips64 - k_first_msa_mips64 + 1, + k_num_user_registers_mips64 = k_num_gpr_registers_mips64 + + k_num_fpr_registers_mips64 + + k_num_msa_registers_mips64 +}; } #endif // #ifndef lldb_mips_linux_register_enums_h diff --git a/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h index 174daa25e21..65ff92f39bc 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h @@ -10,84 +10,83 @@ #ifndef lldb_s390x_register_enums_h #define lldb_s390x_register_enums_h -namespace lldb_private -{ +namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) //--------------------------------------------------------------------------- // Internal codes for all s390x registers. //--------------------------------------------------------------------------- -enum -{ - k_first_gpr_s390x, - lldb_r0_s390x = k_first_gpr_s390x, - lldb_r1_s390x, - lldb_r2_s390x, - lldb_r3_s390x, - lldb_r4_s390x, - lldb_r5_s390x, - lldb_r6_s390x, - lldb_r7_s390x, - lldb_r8_s390x, - lldb_r9_s390x, - lldb_r10_s390x, - lldb_r11_s390x, - lldb_r12_s390x, - lldb_r13_s390x, - lldb_r14_s390x, - lldb_r15_s390x, - lldb_acr0_s390x, - lldb_acr1_s390x, - lldb_acr2_s390x, - lldb_acr3_s390x, - lldb_acr4_s390x, - lldb_acr5_s390x, - lldb_acr6_s390x, - lldb_acr7_s390x, - lldb_acr8_s390x, - lldb_acr9_s390x, - lldb_acr10_s390x, - lldb_acr11_s390x, - lldb_acr12_s390x, - lldb_acr13_s390x, - lldb_acr14_s390x, - lldb_acr15_s390x, - lldb_pswm_s390x, - lldb_pswa_s390x, - k_last_gpr_s390x = lldb_pswa_s390x, +enum { + k_first_gpr_s390x, + lldb_r0_s390x = k_first_gpr_s390x, + lldb_r1_s390x, + lldb_r2_s390x, + lldb_r3_s390x, + lldb_r4_s390x, + lldb_r5_s390x, + lldb_r6_s390x, + lldb_r7_s390x, + lldb_r8_s390x, + lldb_r9_s390x, + lldb_r10_s390x, + lldb_r11_s390x, + lldb_r12_s390x, + lldb_r13_s390x, + lldb_r14_s390x, + lldb_r15_s390x, + lldb_acr0_s390x, + lldb_acr1_s390x, + lldb_acr2_s390x, + lldb_acr3_s390x, + lldb_acr4_s390x, + lldb_acr5_s390x, + lldb_acr6_s390x, + lldb_acr7_s390x, + lldb_acr8_s390x, + lldb_acr9_s390x, + lldb_acr10_s390x, + lldb_acr11_s390x, + lldb_acr12_s390x, + lldb_acr13_s390x, + lldb_acr14_s390x, + lldb_acr15_s390x, + lldb_pswm_s390x, + lldb_pswa_s390x, + k_last_gpr_s390x = lldb_pswa_s390x, - k_first_fpr_s390x, - lldb_f0_s390x = k_first_fpr_s390x, - lldb_f1_s390x, - lldb_f2_s390x, - lldb_f3_s390x, - lldb_f4_s390x, - lldb_f5_s390x, - lldb_f6_s390x, - lldb_f7_s390x, - lldb_f8_s390x, - lldb_f9_s390x, - lldb_f10_s390x, - lldb_f11_s390x, - lldb_f12_s390x, - lldb_f13_s390x, - lldb_f14_s390x, - lldb_f15_s390x, - lldb_fpc_s390x, - k_last_fpr_s390x = lldb_fpc_s390x, + k_first_fpr_s390x, + lldb_f0_s390x = k_first_fpr_s390x, + lldb_f1_s390x, + lldb_f2_s390x, + lldb_f3_s390x, + lldb_f4_s390x, + lldb_f5_s390x, + lldb_f6_s390x, + lldb_f7_s390x, + lldb_f8_s390x, + lldb_f9_s390x, + lldb_f10_s390x, + lldb_f11_s390x, + lldb_f12_s390x, + lldb_f13_s390x, + lldb_f14_s390x, + lldb_f15_s390x, + lldb_fpc_s390x, + k_last_fpr_s390x = lldb_fpc_s390x, - // These are only available on Linux. - k_first_linux_s390x, - lldb_orig_r2_s390x = k_first_linux_s390x, - lldb_last_break_s390x, - lldb_system_call_s390x, - k_last_linux_s390x = lldb_system_call_s390x, + // These are only available on Linux. + k_first_linux_s390x, + lldb_orig_r2_s390x = k_first_linux_s390x, + lldb_last_break_s390x, + lldb_system_call_s390x, + k_last_linux_s390x = lldb_system_call_s390x, - k_num_registers_s390x, - k_num_gpr_registers_s390x = k_last_gpr_s390x - k_first_gpr_s390x + 1, - k_num_fpr_registers_s390x = k_last_fpr_s390x - k_first_fpr_s390x + 1, - k_num_linux_registers_s390x = k_last_linux_s390x - k_first_linux_s390x + 1, - k_num_user_registers_s390x = k_num_gpr_registers_s390x + k_num_fpr_registers_s390x, + k_num_registers_s390x, + k_num_gpr_registers_s390x = k_last_gpr_s390x - k_first_gpr_s390x + 1, + k_num_fpr_registers_s390x = k_last_fpr_s390x - k_first_fpr_s390x + 1, + k_num_linux_registers_s390x = k_last_linux_s390x - k_first_linux_s390x + 1, + k_num_user_registers_s390x = + k_num_gpr_registers_s390x + k_num_fpr_registers_s390x, }; } diff --git a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h index 63027b4451b..5f71495c302 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -10,286 +10,286 @@ #ifndef lldb_x86_register_enums_h #define lldb_x86_register_enums_h -namespace lldb_private -{ - // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - //--------------------------------------------------------------------------- - // Internal codes for all i386 registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_i386, - lldb_eax_i386 = k_first_gpr_i386, - lldb_ebx_i386, - lldb_ecx_i386, - lldb_edx_i386, - lldb_edi_i386, - lldb_esi_i386, - lldb_ebp_i386, - lldb_esp_i386, - lldb_eip_i386, - lldb_eflags_i386, - lldb_cs_i386, - lldb_fs_i386, - lldb_gs_i386, - lldb_ss_i386, - lldb_ds_i386, - lldb_es_i386, +//--------------------------------------------------------------------------- +// Internal codes for all i386 registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_i386, + lldb_eax_i386 = k_first_gpr_i386, + lldb_ebx_i386, + lldb_ecx_i386, + lldb_edx_i386, + lldb_edi_i386, + lldb_esi_i386, + lldb_ebp_i386, + lldb_esp_i386, + lldb_eip_i386, + lldb_eflags_i386, + lldb_cs_i386, + lldb_fs_i386, + lldb_gs_i386, + lldb_ss_i386, + lldb_ds_i386, + lldb_es_i386, - k_first_alias_i386, - lldb_ax_i386 = k_first_alias_i386, - lldb_bx_i386, - lldb_cx_i386, - lldb_dx_i386, - lldb_di_i386, - lldb_si_i386, - lldb_bp_i386, - lldb_sp_i386, - lldb_ah_i386, - lldb_bh_i386, - lldb_ch_i386, - lldb_dh_i386, - lldb_al_i386, - lldb_bl_i386, - lldb_cl_i386, - lldb_dl_i386, - k_last_alias_i386 = lldb_dl_i386, + k_first_alias_i386, + lldb_ax_i386 = k_first_alias_i386, + lldb_bx_i386, + lldb_cx_i386, + lldb_dx_i386, + lldb_di_i386, + lldb_si_i386, + lldb_bp_i386, + lldb_sp_i386, + lldb_ah_i386, + lldb_bh_i386, + lldb_ch_i386, + lldb_dh_i386, + lldb_al_i386, + lldb_bl_i386, + lldb_cl_i386, + lldb_dl_i386, + k_last_alias_i386 = lldb_dl_i386, - k_last_gpr_i386 = k_last_alias_i386, + k_last_gpr_i386 = k_last_alias_i386, - k_first_fpr_i386, - lldb_fctrl_i386 = k_first_fpr_i386, - lldb_fstat_i386, - lldb_ftag_i386, - lldb_fop_i386, - lldb_fiseg_i386, - lldb_fioff_i386, - lldb_foseg_i386, - lldb_fooff_i386, - lldb_mxcsr_i386, - lldb_mxcsrmask_i386, - lldb_st0_i386, - lldb_st1_i386, - lldb_st2_i386, - lldb_st3_i386, - lldb_st4_i386, - lldb_st5_i386, - lldb_st6_i386, - lldb_st7_i386, - lldb_mm0_i386, - lldb_mm1_i386, - lldb_mm2_i386, - lldb_mm3_i386, - lldb_mm4_i386, - lldb_mm5_i386, - lldb_mm6_i386, - lldb_mm7_i386, - lldb_xmm0_i386, - lldb_xmm1_i386, - lldb_xmm2_i386, - lldb_xmm3_i386, - lldb_xmm4_i386, - lldb_xmm5_i386, - lldb_xmm6_i386, - lldb_xmm7_i386, - k_last_fpr_i386 = lldb_xmm7_i386, + k_first_fpr_i386, + lldb_fctrl_i386 = k_first_fpr_i386, + lldb_fstat_i386, + lldb_ftag_i386, + lldb_fop_i386, + lldb_fiseg_i386, + lldb_fioff_i386, + lldb_foseg_i386, + lldb_fooff_i386, + lldb_mxcsr_i386, + lldb_mxcsrmask_i386, + lldb_st0_i386, + lldb_st1_i386, + lldb_st2_i386, + lldb_st3_i386, + lldb_st4_i386, + lldb_st5_i386, + lldb_st6_i386, + lldb_st7_i386, + lldb_mm0_i386, + lldb_mm1_i386, + lldb_mm2_i386, + lldb_mm3_i386, + lldb_mm4_i386, + lldb_mm5_i386, + lldb_mm6_i386, + lldb_mm7_i386, + lldb_xmm0_i386, + lldb_xmm1_i386, + lldb_xmm2_i386, + lldb_xmm3_i386, + lldb_xmm4_i386, + lldb_xmm5_i386, + lldb_xmm6_i386, + lldb_xmm7_i386, + k_last_fpr_i386 = lldb_xmm7_i386, - k_first_avx_i386, - lldb_ymm0_i386 = k_first_avx_i386, - lldb_ymm1_i386, - lldb_ymm2_i386, - lldb_ymm3_i386, - lldb_ymm4_i386, - lldb_ymm5_i386, - lldb_ymm6_i386, - lldb_ymm7_i386, - k_last_avx_i386 = lldb_ymm7_i386, + k_first_avx_i386, + lldb_ymm0_i386 = k_first_avx_i386, + lldb_ymm1_i386, + lldb_ymm2_i386, + lldb_ymm3_i386, + lldb_ymm4_i386, + lldb_ymm5_i386, + lldb_ymm6_i386, + lldb_ymm7_i386, + k_last_avx_i386 = lldb_ymm7_i386, - lldb_dr0_i386, - lldb_dr1_i386, - lldb_dr2_i386, - lldb_dr3_i386, - lldb_dr4_i386, - lldb_dr5_i386, - lldb_dr6_i386, - lldb_dr7_i386, + lldb_dr0_i386, + lldb_dr1_i386, + lldb_dr2_i386, + lldb_dr3_i386, + lldb_dr4_i386, + lldb_dr5_i386, + lldb_dr6_i386, + lldb_dr7_i386, - k_num_registers_i386, - k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, - k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, - k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1, - k_num_user_registers_i386 = k_num_gpr_registers_i386 + k_num_fpr_registers_i386 + k_num_avx_registers_i386, - }; + k_num_registers_i386, + k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, + k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, + k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1, + k_num_user_registers_i386 = k_num_gpr_registers_i386 + + k_num_fpr_registers_i386 + + k_num_avx_registers_i386, +}; - //--------------------------------------------------------------------------- - // Internal codes for all x86_64 registers. - //--------------------------------------------------------------------------- - enum - { - k_first_gpr_x86_64, - lldb_rax_x86_64 = k_first_gpr_x86_64, - lldb_rbx_x86_64, - lldb_rcx_x86_64, - lldb_rdx_x86_64, - lldb_rdi_x86_64, - lldb_rsi_x86_64, - lldb_rbp_x86_64, - lldb_rsp_x86_64, - lldb_r8_x86_64, - lldb_r9_x86_64, - lldb_r10_x86_64, - lldb_r11_x86_64, - lldb_r12_x86_64, - lldb_r13_x86_64, - lldb_r14_x86_64, - lldb_r15_x86_64, - lldb_rip_x86_64, - lldb_rflags_x86_64, - lldb_cs_x86_64, - lldb_fs_x86_64, - lldb_gs_x86_64, - lldb_ss_x86_64, - lldb_ds_x86_64, - lldb_es_x86_64, +//--------------------------------------------------------------------------- +// Internal codes for all x86_64 registers. +//--------------------------------------------------------------------------- +enum { + k_first_gpr_x86_64, + lldb_rax_x86_64 = k_first_gpr_x86_64, + lldb_rbx_x86_64, + lldb_rcx_x86_64, + lldb_rdx_x86_64, + lldb_rdi_x86_64, + lldb_rsi_x86_64, + lldb_rbp_x86_64, + lldb_rsp_x86_64, + lldb_r8_x86_64, + lldb_r9_x86_64, + lldb_r10_x86_64, + lldb_r11_x86_64, + lldb_r12_x86_64, + lldb_r13_x86_64, + lldb_r14_x86_64, + lldb_r15_x86_64, + lldb_rip_x86_64, + lldb_rflags_x86_64, + lldb_cs_x86_64, + lldb_fs_x86_64, + lldb_gs_x86_64, + lldb_ss_x86_64, + lldb_ds_x86_64, + lldb_es_x86_64, - k_first_alias_x86_64, - lldb_eax_x86_64 = k_first_alias_x86_64, - lldb_ebx_x86_64, - lldb_ecx_x86_64, - lldb_edx_x86_64, - lldb_edi_x86_64, - lldb_esi_x86_64, - lldb_ebp_x86_64, - lldb_esp_x86_64, - lldb_r8d_x86_64, // Low 32 bits of r8 - lldb_r9d_x86_64, // Low 32 bits of r9 - lldb_r10d_x86_64, // Low 32 bits of r10 - lldb_r11d_x86_64, // Low 32 bits of r11 - lldb_r12d_x86_64, // Low 32 bits of r12 - lldb_r13d_x86_64, // Low 32 bits of r13 - lldb_r14d_x86_64, // Low 32 bits of r14 - lldb_r15d_x86_64, // Low 32 bits of r15 - lldb_ax_x86_64, - lldb_bx_x86_64, - lldb_cx_x86_64, - lldb_dx_x86_64, - lldb_di_x86_64, - lldb_si_x86_64, - lldb_bp_x86_64, - lldb_sp_x86_64, - lldb_r8w_x86_64, // Low 16 bits of r8 - lldb_r9w_x86_64, // Low 16 bits of r9 - lldb_r10w_x86_64, // Low 16 bits of r10 - lldb_r11w_x86_64, // Low 16 bits of r11 - lldb_r12w_x86_64, // Low 16 bits of r12 - lldb_r13w_x86_64, // Low 16 bits of r13 - lldb_r14w_x86_64, // Low 16 bits of r14 - lldb_r15w_x86_64, // Low 16 bits of r15 - lldb_ah_x86_64, - lldb_bh_x86_64, - lldb_ch_x86_64, - lldb_dh_x86_64, - lldb_al_x86_64, - lldb_bl_x86_64, - lldb_cl_x86_64, - lldb_dl_x86_64, - lldb_dil_x86_64, - lldb_sil_x86_64, - lldb_bpl_x86_64, - lldb_spl_x86_64, - lldb_r8l_x86_64, // Low 8 bits of r8 - lldb_r9l_x86_64, // Low 8 bits of r9 - lldb_r10l_x86_64, // Low 8 bits of r10 - lldb_r11l_x86_64, // Low 8 bits of r11 - lldb_r12l_x86_64, // Low 8 bits of r12 - lldb_r13l_x86_64, // Low 8 bits of r13 - lldb_r14l_x86_64, // Low 8 bits of r14 - lldb_r15l_x86_64, // Low 8 bits of r15 - k_last_alias_x86_64 = lldb_r15l_x86_64, + k_first_alias_x86_64, + lldb_eax_x86_64 = k_first_alias_x86_64, + lldb_ebx_x86_64, + lldb_ecx_x86_64, + lldb_edx_x86_64, + lldb_edi_x86_64, + lldb_esi_x86_64, + lldb_ebp_x86_64, + lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits of r8 + lldb_r9d_x86_64, // Low 32 bits of r9 + lldb_r10d_x86_64, // Low 32 bits of r10 + lldb_r11d_x86_64, // Low 32 bits of r11 + lldb_r12d_x86_64, // Low 32 bits of r12 + lldb_r13d_x86_64, // Low 32 bits of r13 + lldb_r14d_x86_64, // Low 32 bits of r14 + lldb_r15d_x86_64, // Low 32 bits of r15 + lldb_ax_x86_64, + lldb_bx_x86_64, + lldb_cx_x86_64, + lldb_dx_x86_64, + lldb_di_x86_64, + lldb_si_x86_64, + lldb_bp_x86_64, + lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits of r8 + lldb_r9w_x86_64, // Low 16 bits of r9 + lldb_r10w_x86_64, // Low 16 bits of r10 + lldb_r11w_x86_64, // Low 16 bits of r11 + lldb_r12w_x86_64, // Low 16 bits of r12 + lldb_r13w_x86_64, // Low 16 bits of r13 + lldb_r14w_x86_64, // Low 16 bits of r14 + lldb_r15w_x86_64, // Low 16 bits of r15 + lldb_ah_x86_64, + lldb_bh_x86_64, + lldb_ch_x86_64, + lldb_dh_x86_64, + lldb_al_x86_64, + lldb_bl_x86_64, + lldb_cl_x86_64, + lldb_dl_x86_64, + lldb_dil_x86_64, + lldb_sil_x86_64, + lldb_bpl_x86_64, + lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits of r8 + lldb_r9l_x86_64, // Low 8 bits of r9 + lldb_r10l_x86_64, // Low 8 bits of r10 + lldb_r11l_x86_64, // Low 8 bits of r11 + lldb_r12l_x86_64, // Low 8 bits of r12 + lldb_r13l_x86_64, // Low 8 bits of r13 + lldb_r14l_x86_64, // Low 8 bits of r14 + lldb_r15l_x86_64, // Low 8 bits of r15 + k_last_alias_x86_64 = lldb_r15l_x86_64, - k_last_gpr_x86_64 = k_last_alias_x86_64, + k_last_gpr_x86_64 = k_last_alias_x86_64, - k_first_fpr_x86_64, - lldb_fctrl_x86_64 = k_first_fpr_x86_64, - lldb_fstat_x86_64, - lldb_ftag_x86_64, - lldb_fop_x86_64, - lldb_fiseg_x86_64, - lldb_fioff_x86_64, - lldb_foseg_x86_64, - lldb_fooff_x86_64, - lldb_mxcsr_x86_64, - lldb_mxcsrmask_x86_64, - lldb_st0_x86_64, - lldb_st1_x86_64, - lldb_st2_x86_64, - lldb_st3_x86_64, - lldb_st4_x86_64, - lldb_st5_x86_64, - lldb_st6_x86_64, - lldb_st7_x86_64, - lldb_mm0_x86_64, - lldb_mm1_x86_64, - lldb_mm2_x86_64, - lldb_mm3_x86_64, - lldb_mm4_x86_64, - lldb_mm5_x86_64, - lldb_mm6_x86_64, - lldb_mm7_x86_64, - lldb_xmm0_x86_64, - lldb_xmm1_x86_64, - lldb_xmm2_x86_64, - lldb_xmm3_x86_64, - lldb_xmm4_x86_64, - lldb_xmm5_x86_64, - lldb_xmm6_x86_64, - lldb_xmm7_x86_64, - lldb_xmm8_x86_64, - lldb_xmm9_x86_64, - lldb_xmm10_x86_64, - lldb_xmm11_x86_64, - lldb_xmm12_x86_64, - lldb_xmm13_x86_64, - lldb_xmm14_x86_64, - lldb_xmm15_x86_64, - k_last_fpr_x86_64 = lldb_xmm15_x86_64, + k_first_fpr_x86_64, + lldb_fctrl_x86_64 = k_first_fpr_x86_64, + lldb_fstat_x86_64, + lldb_ftag_x86_64, + lldb_fop_x86_64, + lldb_fiseg_x86_64, + lldb_fioff_x86_64, + lldb_foseg_x86_64, + lldb_fooff_x86_64, + lldb_mxcsr_x86_64, + lldb_mxcsrmask_x86_64, + lldb_st0_x86_64, + lldb_st1_x86_64, + lldb_st2_x86_64, + lldb_st3_x86_64, + lldb_st4_x86_64, + lldb_st5_x86_64, + lldb_st6_x86_64, + lldb_st7_x86_64, + lldb_mm0_x86_64, + lldb_mm1_x86_64, + lldb_mm2_x86_64, + lldb_mm3_x86_64, + lldb_mm4_x86_64, + lldb_mm5_x86_64, + lldb_mm6_x86_64, + lldb_mm7_x86_64, + lldb_xmm0_x86_64, + lldb_xmm1_x86_64, + lldb_xmm2_x86_64, + lldb_xmm3_x86_64, + lldb_xmm4_x86_64, + lldb_xmm5_x86_64, + lldb_xmm6_x86_64, + lldb_xmm7_x86_64, + lldb_xmm8_x86_64, + lldb_xmm9_x86_64, + lldb_xmm10_x86_64, + lldb_xmm11_x86_64, + lldb_xmm12_x86_64, + lldb_xmm13_x86_64, + lldb_xmm14_x86_64, + lldb_xmm15_x86_64, + k_last_fpr_x86_64 = lldb_xmm15_x86_64, - k_first_avx_x86_64, - lldb_ymm0_x86_64 = k_first_avx_x86_64, - lldb_ymm1_x86_64, - lldb_ymm2_x86_64, - lldb_ymm3_x86_64, - lldb_ymm4_x86_64, - lldb_ymm5_x86_64, - lldb_ymm6_x86_64, - lldb_ymm7_x86_64, - lldb_ymm8_x86_64, - lldb_ymm9_x86_64, - lldb_ymm10_x86_64, - lldb_ymm11_x86_64, - lldb_ymm12_x86_64, - lldb_ymm13_x86_64, - lldb_ymm14_x86_64, - lldb_ymm15_x86_64, - k_last_avx_x86_64 = lldb_ymm15_x86_64, + k_first_avx_x86_64, + lldb_ymm0_x86_64 = k_first_avx_x86_64, + lldb_ymm1_x86_64, + lldb_ymm2_x86_64, + lldb_ymm3_x86_64, + lldb_ymm4_x86_64, + lldb_ymm5_x86_64, + lldb_ymm6_x86_64, + lldb_ymm7_x86_64, + lldb_ymm8_x86_64, + lldb_ymm9_x86_64, + lldb_ymm10_x86_64, + lldb_ymm11_x86_64, + lldb_ymm12_x86_64, + lldb_ymm13_x86_64, + lldb_ymm14_x86_64, + lldb_ymm15_x86_64, + k_last_avx_x86_64 = lldb_ymm15_x86_64, - lldb_dr0_x86_64, - lldb_dr1_x86_64, - lldb_dr2_x86_64, - lldb_dr3_x86_64, - lldb_dr4_x86_64, - lldb_dr5_x86_64, - lldb_dr6_x86_64, - lldb_dr7_x86_64, - - k_num_registers_x86_64, - k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, - k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, - k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1, - k_num_user_registers_x86_64 = k_num_gpr_registers_x86_64 + k_num_fpr_registers_x86_64 + k_num_avx_registers_x86_64, - }; + lldb_dr0_x86_64, + lldb_dr1_x86_64, + lldb_dr2_x86_64, + lldb_dr3_x86_64, + lldb_dr4_x86_64, + lldb_dr5_x86_64, + lldb_dr6_x86_64, + lldb_dr7_x86_64, + k_num_registers_x86_64, + k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, + k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, + k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1, + k_num_user_registers_x86_64 = k_num_gpr_registers_x86_64 + + k_num_fpr_registers_x86_64 + + k_num_avx_registers_x86_64, +}; } #endif // #ifndef lldb_x86_register_enums_h diff --git a/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h b/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h index 79dae3fca4e..e99a75e023e 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h +++ b/lldb/source/Plugins/Process/Windows/Common/ExceptionRecord.h @@ -10,15 +10,14 @@ #ifndef liblldb_Plugins_Process_Windows_ExceptionRecord_H_ #define liblldb_Plugins_Process_Windows_ExceptionRecord_H_ -#include "lldb/lldb-forward.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-forward.h" #include <DbgHelp.h> #include <memory> #include <vector> -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- // ExceptionRecord @@ -26,73 +25,55 @@ namespace lldb_private // ExceptionRecord defines an interface which allows implementors to receive // notification of events that happen in a debugged process. //---------------------------------------------------------------------- -class ExceptionRecord -{ - public: - ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) - { - m_code = record.ExceptionCode; - m_continuable = (record.ExceptionFlags == 0); - if (record.ExceptionRecord) - m_next_exception.reset(new ExceptionRecord(*record.ExceptionRecord, thread_id)); - m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress); - m_thread_id = thread_id; - m_arguments.assign(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters); - } +class ExceptionRecord { +public: + ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) { + m_code = record.ExceptionCode; + m_continuable = (record.ExceptionFlags == 0); + if (record.ExceptionRecord) + m_next_exception.reset( + new ExceptionRecord(*record.ExceptionRecord, thread_id)); + m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress); + m_thread_id = thread_id; + m_arguments.assign(record.ExceptionInformation, + record.ExceptionInformation + record.NumberParameters); + } - // MINIDUMP_EXCEPTIONs are almost identical to EXCEPTION_RECORDs. - ExceptionRecord(const MINIDUMP_EXCEPTION &record, lldb::tid_t thread_id) : - m_code(record.ExceptionCode), - m_continuable(record.ExceptionFlags == 0), + // MINIDUMP_EXCEPTIONs are almost identical to EXCEPTION_RECORDs. + ExceptionRecord(const MINIDUMP_EXCEPTION &record, lldb::tid_t thread_id) + : m_code(record.ExceptionCode), m_continuable(record.ExceptionFlags == 0), m_next_exception(nullptr), m_exception_addr(static_cast<lldb::addr_t>(record.ExceptionAddress)), m_thread_id(thread_id), - m_arguments(record.ExceptionInformation, record.ExceptionInformation + record.NumberParameters) - { - // Set up link to nested exception. - if (record.ExceptionRecord) - { - m_next_exception.reset(new ExceptionRecord(*reinterpret_cast<const MINIDUMP_EXCEPTION *>(record.ExceptionRecord), - thread_id)); - } + m_arguments(record.ExceptionInformation, + record.ExceptionInformation + record.NumberParameters) { + // Set up link to nested exception. + if (record.ExceptionRecord) { + m_next_exception.reset(new ExceptionRecord( + *reinterpret_cast<const MINIDUMP_EXCEPTION *>(record.ExceptionRecord), + thread_id)); } + } - virtual ~ExceptionRecord() {} + virtual ~ExceptionRecord() {} - DWORD - GetExceptionCode() const - { - return m_code; - } - bool - IsContinuable() const - { - return m_continuable; - } - const ExceptionRecord * - GetNextException() const - { - return m_next_exception.get(); - } - lldb::addr_t - GetExceptionAddress() const - { - return m_exception_addr; - } + DWORD + GetExceptionCode() const { return m_code; } + bool IsContinuable() const { return m_continuable; } + const ExceptionRecord *GetNextException() const { + return m_next_exception.get(); + } + lldb::addr_t GetExceptionAddress() const { return m_exception_addr; } - lldb::tid_t - GetThreadID() const - { - return m_thread_id; - } + lldb::tid_t GetThreadID() const { return m_thread_id; } - private: - DWORD m_code; - bool m_continuable; - std::shared_ptr<ExceptionRecord> m_next_exception; - lldb::addr_t m_exception_addr; - lldb::tid_t m_thread_id; - std::vector<ULONG_PTR> m_arguments; +private: + DWORD m_code; + bool m_continuable; + std::shared_ptr<ExceptionRecord> m_next_exception; + lldb::addr_t m_exception_addr; + lldb::tid_t m_thread_id; + std::vector<ULONG_PTR> m_arguments; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/NtStructures.h b/lldb/source/Plugins/Process/Windows/Common/NtStructures.h index 6c688d9068d..6826b98c769 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NtStructures.h +++ b/lldb/source/Plugins/Process/Windows/Common/NtStructures.h @@ -15,18 +15,17 @@ // This describes the layout of a TEB (Thread Environment Block) for a 64-bit // process. It's adapted from the 32-bit TEB in winternl.h. Currently, we care // only about the position of the TlsSlots. -struct TEB64 -{ - ULONG64 Reserved1[12]; - ULONG64 ProcessEnvironmentBlock; - ULONG64 Reserved2[399]; - BYTE Reserved3[1952]; - ULONG64 TlsSlots[64]; - BYTE Reserved4[8]; - ULONG64 Reserved5[26]; - ULONG64 ReservedForOle; // Windows 2000 only - ULONG64 Reserved6[4]; - ULONG64 TlsExpansionSlots; +struct TEB64 { + ULONG64 Reserved1[12]; + ULONG64 ProcessEnvironmentBlock; + ULONG64 Reserved2[399]; + BYTE Reserved3[1952]; + ULONG64 TlsSlots[64]; + BYTE Reserved4[8]; + ULONG64 Reserved5[26]; + ULONG64 ReservedForOle; // Windows 2000 only + ULONG64 Reserved6[4]; + ULONG64 TlsExpansionSlots; }; #endif diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 2c3f9fbecf9..62533651d83 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -23,78 +23,63 @@ using namespace lldb; using namespace lldb_private; -namespace lldb_private -{ +namespace lldb_private { //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) - : lldb_private::Process(target_sp, listener_sp) -{ -} +ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp) + : lldb_private::Process(target_sp, listener_sp) {} -ProcessWindows::~ProcessWindows() -{ -} +ProcessWindows::~ProcessWindows() {} -size_t -ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("GetSTDOUT unsupported on Windows"); - return 0; +size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) { + error.SetErrorString("GetSTDOUT unsupported on Windows"); + return 0; } -size_t -ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("GetSTDERR unsupported on Windows"); - return 0; +size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) { + error.SetErrorString("GetSTDERR unsupported on Windows"); + return 0; } -size_t -ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, Error &error) -{ - error.SetErrorString("PutSTDIN unsupported on Windows"); - return 0; +size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, + Error &error) { + error.SetErrorString("PutSTDIN unsupported on Windows"); + return 0; } //------------------------------------------------------------------------------ // ProcessInterface protocol. - -lldb::addr_t -ProcessWindows::GetImageInfoAddress() -{ - Target &target = GetTarget(); - ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(&target); - if (addr.IsValid()) - return addr.GetLoadAddress(&target); - else - return LLDB_INVALID_ADDRESS; +lldb::addr_t ProcessWindows::GetImageInfoAddress() { + Target &target = GetTarget(); + ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(&target); + if (addr.IsValid()) + return addr.GetLoadAddress(&target); + else + return LLDB_INVALID_ADDRESS; } -// The Windows page protection bits are NOT independent masks that can be bitwise-ORed +// The Windows page protection bits are NOT independent masks that can be +// bitwise-ORed // together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE | PAGE_READ). -// To test for an access type, it's necessary to test for any of the bits that provide +// To test for an access type, it's necessary to test for any of the bits that +// provide // that access type. -bool -ProcessWindows::IsPageReadable(uint32_t protect) -{ - return (protect & PAGE_NOACCESS) == 0; +bool ProcessWindows::IsPageReadable(uint32_t protect) { + return (protect & PAGE_NOACCESS) == 0; } -bool -ProcessWindows::IsPageWritable(uint32_t protect) -{ - return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY)) != 0; +bool ProcessWindows::IsPageWritable(uint32_t protect) { + return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | + PAGE_READWRITE | PAGE_WRITECOPY)) != 0; } -bool -ProcessWindows::IsPageExecutable(uint32_t protect) -{ - return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0; +bool ProcessWindows::IsPageExecutable(uint32_t protect) { + return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY)) != 0; } - } diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h index 0ee42e2ae1f..bf96180488c 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h @@ -11,42 +11,38 @@ #define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ // Other libraries and framework includes -#include "lldb/lldb-forward.h" #include "lldb/Core/Error.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { -class ProcessWindows : public lldb_private::Process -{ +class ProcessWindows : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessWindows(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp); + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - ~ProcessWindows(); + ~ProcessWindows(); - size_t GetSTDOUT(char *buf, size_t buf_size, lldb_private::Error &error) override; - size_t GetSTDERR(char *buf, size_t buf_size, lldb_private::Error &error) override; - size_t PutSTDIN(const char *buf, size_t buf_size, lldb_private::Error &error) override; + size_t GetSTDOUT(char *buf, size_t buf_size, + lldb_private::Error &error) override; + size_t GetSTDERR(char *buf, size_t buf_size, + lldb_private::Error &error) override; + size_t PutSTDIN(const char *buf, size_t buf_size, + lldb_private::Error &error) override; - lldb::addr_t GetImageInfoAddress() override; + lldb::addr_t GetImageInfoAddress() override; protected: - // These decode the page protection bits. - static bool - IsPageReadable(uint32_t protect); + // These decode the page protection bits. + static bool IsPageReadable(uint32_t protect); - static bool - IsPageWritable(uint32_t protect); + static bool IsPageWritable(uint32_t protect); - static bool - IsPageExecutable(uint32_t protect); + static bool IsPageExecutable(uint32_t protect); }; - } -#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ +#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp index 47722c5146b..242c1996bdd 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp @@ -18,177 +18,151 @@ using namespace lldb; using namespace lldb_private; - // We want to avoid global constructors where code needs to be run so here we // control access to our static g_log_sp by hiding it in a singleton function // that will construct the static g_log_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = nullptr; +static Log *g_log = nullptr; static llvm::ManagedStatic<std::once_flag> g_once_flag; -void -ProcessWindowsLog::Initialize() -{ - static ConstString g_name("windows"); - - std::call_once(*g_once_flag, [](){ - Log::Callbacks log_callbacks = { - DisableLog, - EnableLog, - ListLogCategories - }; - - Log::RegisterLogChannel(g_name, log_callbacks); - RegisterPluginName(g_name); - }); -} +void ProcessWindowsLog::Initialize() { + static ConstString g_name("windows"); -void -ProcessWindowsLog::Terminate() -{ -} + std::call_once(*g_once_flag, []() { + Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; -Log * -ProcessWindowsLog::GetLog() -{ - return (g_log_enabled) ? g_log : nullptr; + Log::RegisterLogChannel(g_name, log_callbacks); + RegisterPluginName(g_name); + }); } -bool -ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) -{ - Log *log = GetLog(); - if (!log) - return false; +void ProcessWindowsLog::Terminate() {} - uint32_t log_mask = log->GetMask().Get(); - if (req == LogMaskReq::All) - return ((log_mask & mask) == mask); - else - return (log_mask & mask); +Log *ProcessWindowsLog::GetLog() { return (g_log_enabled) ? g_log : nullptr; } + +bool ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) { + Log *log = GetLog(); + if (!log) + return false; + + uint32_t log_mask = log->GetMask().Get(); + if (req == LogMaskReq::All) + return ((log_mask & mask) == mask); + else + return (log_mask & mask); } -static uint32_t -GetFlagBits(const char *arg) -{ - if (::strcasecmp(arg, "all") == 0 ) return WINDOWS_LOG_ALL; - else if (::strcasecmp(arg, "break") == 0 ) return WINDOWS_LOG_BREAKPOINTS; - else if (::strcasecmp(arg, "event") == 0 ) return WINDOWS_LOG_EVENT; - else if (::strcasecmp(arg, "exception") == 0 ) return WINDOWS_LOG_EXCEPTION; - else if (::strcasecmp(arg, "memory") == 0 ) return WINDOWS_LOG_MEMORY; - else if (::strcasecmp(arg, "process") == 0 ) return WINDOWS_LOG_PROCESS; - else if (::strcasecmp(arg, "registers") == 0 ) return WINDOWS_LOG_REGISTERS; - else if (::strcasecmp(arg, "step") == 0 ) return WINDOWS_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0 ) return WINDOWS_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0 ) return WINDOWS_LOG_VERBOSE; - return 0; +static uint32_t GetFlagBits(const char *arg) { + if (::strcasecmp(arg, "all") == 0) + return WINDOWS_LOG_ALL; + else if (::strcasecmp(arg, "break") == 0) + return WINDOWS_LOG_BREAKPOINTS; + else if (::strcasecmp(arg, "event") == 0) + return WINDOWS_LOG_EVENT; + else if (::strcasecmp(arg, "exception") == 0) + return WINDOWS_LOG_EXCEPTION; + else if (::strcasecmp(arg, "memory") == 0) + return WINDOWS_LOG_MEMORY; + else if (::strcasecmp(arg, "process") == 0) + return WINDOWS_LOG_PROCESS; + else if (::strcasecmp(arg, "registers") == 0) + return WINDOWS_LOG_REGISTERS; + else if (::strcasecmp(arg, "step") == 0) + return WINDOWS_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + return WINDOWS_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + return WINDOWS_LOG_VERBOSE; + return 0; } -void -ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) -{ - Log *log (GetLog()); - if (log) - { - uint32_t flag_bits = 0; - - if (args[0] != nullptr) - { - flag_bits = log->GetMask().Get(); - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits &= ~bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - } +void ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) { + Log *log(GetLog()); + if (log) { + uint32_t flag_bits = 0; - log->GetMask().Reset(flag_bits); - if (flag_bits == 0) - { - g_log_enabled = false; - log->SetStream(lldb::StreamSP()); + if (args[0] != nullptr) { + flag_bits = log->GetMask().Get(); + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits &= ~bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); } + } } - return; -} - -Log * -ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); + log->GetMask().Reset(flag_bits); + if (flag_bits == 0) { + g_log_enabled = false; + log->SetStream(lldb::StreamSP()); } + } + return; +} + +Log *ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, + const char **args, Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits = 0; + if (g_log) + flag_bits = g_log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log) - { - bool got_unknown_category = false; - for (; args[0]; args++) - { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) - { - flag_bits |= bits; - } - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } + + if (g_log) { + bool got_unknown_category = false; + for (; args[0]; args++) { + const char *arg = args[0]; + uint32_t bits = GetFlagBits(arg); + + if (bits) { + flag_bits |= bits; + } else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListLogCategories(feedback_strm); } - if (flag_bits == 0) - flag_bits = WINDOWS_LOG_ALL; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - g_log_enabled = true; + } } - return g_log; + if (flag_bits == 0) + flag_bits = WINDOWS_LOG_ALL; + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + g_log_enabled = true; + } + return g_log; } -void -ProcessWindowsLog::ListLogCategories(Stream *strm) -{ - strm->Printf("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " break - log breakpoints\n" - " event - log low level debugger events\n" - " exception - log exception information\n" - " memory - log memory reads and writes\n" - " process - log process events and activities\n" - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n", - ProcessWindowsLog::m_pluginname); +void ProcessWindowsLog::ListLogCategories(Stream *strm) { + strm->Printf("Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " break - log breakpoints\n" + " event - log low level debugger events\n" + " exception - log exception information\n" + " memory - log memory reads and writes\n" + " process - log process events and activities\n" + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n", + ProcessWindowsLog::m_pluginname); } const char *ProcessWindowsLog::m_pluginname = ""; diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h index d798d131fae..cbb99e8d907 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h @@ -12,85 +12,80 @@ #include "lldb/Core/Log.h" -#define WINDOWS_LOG_VERBOSE (1u << 0) -#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations -#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions -#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations -#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls -#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations -#define WINDOWS_LOG_STEP (1u << 5) // Log step operations -#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations -#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events -#define WINDOWS_LOG_ALL (UINT32_MAX) - -enum class LogMaskReq -{ - All, - Any -}; - -class ProcessWindowsLog -{ - static const char *m_pluginname; +#define WINDOWS_LOG_VERBOSE (1u << 0) +#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations +#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions +#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations +#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls +#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations +#define WINDOWS_LOG_STEP (1u << 5) // Log step operations +#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations +#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events +#define WINDOWS_LOG_ALL (UINT32_MAX) + +enum class LogMaskReq { All, Any }; + +class ProcessWindowsLog { + static const char *m_pluginname; public: - // --------------------------------------------------------------------- - // Public Static Methods - // --------------------------------------------------------------------- - static void - Initialize(); - - static void - Terminate(); - - static void - RegisterPluginName(const char *pluginName) - { - m_pluginname = pluginName; - } - - static void - RegisterPluginName(lldb_private::ConstString pluginName) - { - m_pluginname = pluginName.GetCString(); - } - - static bool - TestLogFlags(uint32_t mask, LogMaskReq req); - - static lldb_private::Log * - GetLog(); - - static void - DisableLog(const char **args, lldb_private::Stream *feedback_strm); - - static lldb_private::Log * - EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options, - const char **args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories(lldb_private::Stream *strm); + // --------------------------------------------------------------------- + // Public Static Methods + // --------------------------------------------------------------------- + static void Initialize(); + + static void Terminate(); + + static void RegisterPluginName(const char *pluginName) { + m_pluginname = pluginName; + } + + static void RegisterPluginName(lldb_private::ConstString pluginName) { + m_pluginname = pluginName.GetCString(); + } + + static bool TestLogFlags(uint32_t mask, LogMaskReq req); + + static lldb_private::Log *GetLog(); + + static void DisableLog(const char **args, + lldb_private::Stream *feedback_strm); + + static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, + uint32_t log_options, const char **args, + lldb_private::Stream *feedback_strm); + + static void ListLogCategories(lldb_private::Stream *strm); }; -#define WINLOGF_IF(Flags, Req, Method, ...) \ - { \ - if (ProcessWindowsLog::TestLogFlags(Flags, Req)) \ - { \ - Log *log = ProcessWindowsLog::GetLog(); \ - if (log) \ - log->Method(__VA_ARGS__); \ - } \ - } - -#define WINLOG_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Printf, __VA_ARGS__) -#define WINLOG_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Printf, __VA_ARGS__) -#define WINLOGV_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Verbose, __VA_ARGS__) -#define WINLOGV_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Verbose, __VA_ARGS__) -#define WINLOGD_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Debug, __VA_ARGS__) -#define WINLOGD_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Debug, __VA_ARGS__) -#define WINERR_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Error, __VA_ARGS__) -#define WINERR_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Error, __VA_ARGS__) -#define WINWARN_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Warning, __VA_ARGS__) -#define WINWARN_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Warning, __VA_ARGS__) - -#endif // liblldb_ProcessWindowsLog_h_ +#define WINLOGF_IF(Flags, Req, Method, ...) \ + { \ + if (ProcessWindowsLog::TestLogFlags(Flags, Req)) { \ + Log *log = ProcessWindowsLog::GetLog(); \ + if (log) \ + log->Method(__VA_ARGS__); \ + } \ + } + +#define WINLOG_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Printf, __VA_ARGS__) +#define WINLOG_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Printf, __VA_ARGS__) +#define WINLOGV_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Verbose, __VA_ARGS__) +#define WINLOGV_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Verbose, __VA_ARGS__) +#define WINLOGD_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Debug, __VA_ARGS__) +#define WINLOGD_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Debug, __VA_ARGS__) +#define WINERR_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Error, __VA_ARGS__) +#define WINERR_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Error, __VA_ARGS__) +#define WINWARN_IFANY(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::Any, Warning, __VA_ARGS__) +#define WINWARN_IFALL(Flags, ...) \ + WINLOGF_IF(Flags, LogMaskReq::All, Warning, __VA_ARGS__) + +#endif // liblldb_ProcessWindowsLog_h_ diff --git a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp index d61675f09b1..73bcd4ac38a 100644 --- a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" #include "ProcessWindowsLog.h" #include "RegisterContextWindows.h" @@ -27,129 +27,110 @@ const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows::RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) - , m_context() - , m_context_stale(true) -{ -} +RegisterContextWindows::RegisterContextWindows(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx), m_context(), + m_context_stale(true) {} -RegisterContextWindows::~RegisterContextWindows() -{ -} +RegisterContextWindows::~RegisterContextWindows() {} -void -RegisterContextWindows::InvalidateAllRegisters() -{ - m_context_stale = true; +void RegisterContextWindows::InvalidateAllRegisters() { + m_context_stale = true; } -bool -RegisterContextWindows::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - if (!CacheAllRegisterValues()) - return false; - if (data_sp->GetByteSize() < sizeof(m_context)) - { - data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); - } - memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); - return true; +bool RegisterContextWindows::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + if (!CacheAllRegisterValues()) + return false; + if (data_sp->GetByteSize() < sizeof(m_context)) { + data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); + } + memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); + return true; } -bool -RegisterContextWindows::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - assert(data_sp->GetByteSize() >= sizeof(m_context)); - memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); +bool RegisterContextWindows::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + assert(data_sp->GetByteSize() >= sizeof(m_context)); + memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - if (!::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) - return false; + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + if (!::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), + &m_context)) + return false; - return true; + return true; } -uint32_t -RegisterContextWindows::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) -{ - const uint32_t num_regs = GetRegisterCount(); +uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + const uint32_t num_regs = GetRegisterCount(); - assert(kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); - if (reg_info->kinds[kind] == num) - return reg_idx; - } + if (reg_info->kinds[kind] == num) + return reg_idx; + } - return LLDB_INVALID_REGNUM; + return LLDB_INVALID_REGNUM; } //------------------------------------------------------------------ // Subclasses can these functions if desired //------------------------------------------------------------------ -uint32_t -RegisterContextWindows::NumSupportedHardwareBreakpoints() -{ - // Support for hardware breakpoints not yet implemented. - return 0; +uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() { + // Support for hardware breakpoints not yet implemented. + return 0; } -uint32_t -RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) -{ - return 0; +uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + return 0; } -bool -RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) -{ - return false; +bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) { + return false; } -uint32_t -RegisterContextWindows::NumSupportedHardwareWatchpoints() -{ - // Support for hardware watchpoints not yet implemented. - return 0; +uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() { + // Support for hardware watchpoints not yet implemented. + return 0; } -uint32_t -RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) -{ - return 0; +uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, + size_t size, bool read, + bool write) { + return 0; } -bool -RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; +bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { + return false; } -bool -RegisterContextWindows::HardwareSingleStep(bool enable) -{ - return false; -} +bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } -bool -RegisterContextWindows::CacheAllRegisterValues() -{ - if (!m_context_stale) - return true; - - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - memset(&m_context, 0, sizeof(m_context)); - m_context.ContextFlags = kWinContextFlags; - if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) - { - WINERR_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext failed with error %u while caching register values.", - ::GetLastError()); - return false; - } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext successfully updated the register values.", ::GetLastError()); - m_context_stale = false; +bool RegisterContextWindows::CacheAllRegisterValues() { + if (!m_context_stale) return true; + + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + memset(&m_context, 0, sizeof(m_context)); + m_context.ContextFlags = kWinContextFlags; + if (!::GetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), + &m_context)) { + WINERR_IFALL( + WINDOWS_LOG_REGISTERS, + "GetThreadContext failed with error %u while caching register values.", + ::GetLastError()); + return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, + "GetThreadContext successfully updated the register values.", + ::GetLastError()); + m_context_stale = false; + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h index 66b7a9004ea..bd09295c2f2 100644 --- a/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h @@ -10,57 +10,57 @@ #ifndef liblldb_RegisterContextWindows_H_ #define liblldb_RegisterContextWindows_H_ -#include "lldb/lldb-forward.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows : public lldb_private::RegisterContext -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows : public lldb_private::RegisterContext { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows(); + virtual ~RegisterContextWindows(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - void InvalidateAllRegisters() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + void InvalidateAllRegisters() override; - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; - //------------------------------------------------------------------ - // Subclasses can override these functions if desired - //------------------------------------------------------------------ - uint32_t NumSupportedHardwareBreakpoints() override; + //------------------------------------------------------------------ + // Subclasses can override these functions if desired + //------------------------------------------------------------------ + uint32_t NumSupportedHardwareBreakpoints() override; - uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - uint32_t NumSupportedHardwareWatchpoints() override; + uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, + bool write) override; - bool ClearHardwareWatchpoint(uint32_t hw_index) override; + bool ClearHardwareWatchpoint(uint32_t hw_index) override; - bool HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; - protected: - virtual bool CacheAllRegisterValues(); +protected: + virtual bool CacheAllRegisterValues(); - CONTEXT m_context; - bool m_context_stale; + CONTEXT m_context; + bool m_context_stale; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp index dcb6f0c7243..fe05f3068bb 100644 --- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp @@ -16,83 +16,66 @@ #include "lldb/Host/windows/windows.h" #include "lldb/Target/RegisterContext.h" -#include "TargetThreadWindows.h" #include "ProcessWindows.h" #include "ProcessWindowsLog.h" +#include "TargetThreadWindows.h" #include "UnwindLLDB.h" using namespace lldb; using namespace lldb_private; -TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, const HostThread &thread) - : Thread(process, thread.GetNativeThread().GetThreadId()) - , m_host_thread(thread) -{ -} +TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, + const HostThread &thread) + : Thread(process, thread.GetNativeThread().GetThreadId()), + m_host_thread(thread) {} -TargetThreadWindows::~TargetThreadWindows() -{ - DestroyThread(); -} +TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } -void -TargetThreadWindows::RefreshStateAfterStop() -{ - ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - SetState(eStateStopped); - GetRegisterContext()->InvalidateIfNeeded(false); +void TargetThreadWindows::RefreshStateAfterStop() { + ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); + SetState(eStateStopped); + GetRegisterContext()->InvalidateIfNeeded(false); } -void -TargetThreadWindows::WillResume(lldb::StateType resume_state) -{ -} +void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} -void -TargetThreadWindows::DidStop() -{ -} +void TargetThreadWindows::DidStop() {} -bool -TargetThreadWindows::CalculateStopInfo() -{ - SetStopInfo(m_stop_info_sp); - return true; +bool TargetThreadWindows::CalculateStopInfo() { + SetStopInfo(m_stop_info_sp); + return true; } -Unwind * -TargetThreadWindows::GetUnwinder() -{ - // FIXME: Implement an unwinder based on the Windows unwinder exposed through DIA SDK. - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); +Unwind *TargetThreadWindows::GetUnwinder() { + // FIXME: Implement an unwinder based on the Windows unwinder exposed through + // DIA SDK. + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + return m_unwinder_ap.get(); } -bool -TargetThreadWindows::DoResume() -{ - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return true; +bool TargetThreadWindows::DoResume() { + StateType resume_state = GetTemporaryResumeState(); + StateType current_state = GetState(); + if (resume_state == current_state) + return true; - if (resume_state == eStateStepping) - { - uint32_t flags_index = GetRegisterContext()->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - uint64_t flags_value = GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); - flags_value |= 0x100; // Set the trap flag on the CPU - GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); - } + if (resume_state == eStateStepping) { + uint32_t flags_index = + GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + uint64_t flags_value = + GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); + flags_value |= 0x100; // Set the trap flag on the CPU + GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); + } - if (resume_state == eStateStepping || resume_state == eStateRunning) - { - DWORD previous_suspend_count = 0; - HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); - do - { - previous_suspend_count = ::ResumeThread(thread_handle); - } while (previous_suspend_count > 0); - } - return true; + if (resume_state == eStateStepping || resume_state == eStateRunning) { + DWORD previous_suspend_count = 0; + HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); + do { + previous_suspend_count = ::ResumeThread(thread_handle); + } while (previous_suspend_count > 0); + } + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h index 701b56b6d26..ea6d636dbab 100644 --- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.h @@ -11,39 +11,33 @@ #define liblldb_Plugins_Process_Windows_TargetThreadWindows_H_ //#include "ForwardDecl.h" -#include "lldb/lldb-forward.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; class HostThread; class StackFrame; -class TargetThreadWindows : public lldb_private::Thread -{ - public: - TargetThreadWindows(ProcessWindows &process, const HostThread &thread); - virtual ~TargetThreadWindows(); - - // lldb_private::Thread overrides - void RefreshStateAfterStop() override; - void WillResume(lldb::StateType resume_state) override; - void DidStop() override; - bool CalculateStopInfo() override; - Unwind *GetUnwinder() override; - - bool DoResume(); - - HostThread - GetHostThread() const - { - return m_host_thread; - } - - private: - HostThread m_host_thread; +class TargetThreadWindows : public lldb_private::Thread { +public: + TargetThreadWindows(ProcessWindows &process, const HostThread &thread); + virtual ~TargetThreadWindows(); + + // lldb_private::Thread overrides + void RefreshStateAfterStop() override; + void WillResume(lldb::StateType resume_state) override; + void DidStop() override; + bool CalculateStopInfo() override; + Unwind *GetUnwinder() override; + + bool DoResume(); + + HostThread GetHostThread() const { return m_host_thread; } + +private: + HostThread m_host_thread; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp index 3a9c31a0b77..942b4e97c40 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" -#include "RegisterContext_x86.h" #include "RegisterContextWindows_x64.h" +#include "RegisterContext_x86.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" @@ -26,302 +26,317 @@ using namespace lldb_private; #define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary -namespace -{ +namespace { -// This enum defines the layout of the global RegisterInfo array. This is necessary because -// lldb register sets are defined in terms of indices into the register array. As such, the -// order of RegisterInfos defined in global registers array must match the order defined here. -// When defining the register set layouts, these values can appear in an arbitrary order, and that +// This enum defines the layout of the global RegisterInfo array. This is +// necessary because +// lldb register sets are defined in terms of indices into the register array. +// As such, the +// order of RegisterInfos defined in global registers array must match the order +// defined here. +// When defining the register set layouts, these values can appear in an +// arbitrary order, and that // determines the order that register values are displayed in a dump. -enum RegisterIndex -{ - eRegisterIndexRax, - eRegisterIndexRbx, - eRegisterIndexRcx, - eRegisterIndexRdx, - eRegisterIndexRdi, - eRegisterIndexRsi, - eRegisterIndexR8, - eRegisterIndexR9, - eRegisterIndexR10, - eRegisterIndexR11, - eRegisterIndexR12, - eRegisterIndexR13, - eRegisterIndexR14, - eRegisterIndexR15, - eRegisterIndexRbp, - eRegisterIndexRsp, - eRegisterIndexRip, - eRegisterIndexRflags +enum RegisterIndex { + eRegisterIndexRax, + eRegisterIndexRbx, + eRegisterIndexRcx, + eRegisterIndexRdx, + eRegisterIndexRdi, + eRegisterIndexRsi, + eRegisterIndexR8, + eRegisterIndexR9, + eRegisterIndexR10, + eRegisterIndexR11, + eRegisterIndexR12, + eRegisterIndexR13, + eRegisterIndexR14, + eRegisterIndexR15, + eRegisterIndexRbp, + eRegisterIndexRsp, + eRegisterIndexRip, + eRegisterIndexRflags }; // Array of all register information supported by Windows x86 RegisterInfo g_register_infos[] = { - // Macro auto defines most stuff eh_frame DWARF GENERIC + // Macro auto defines most stuff eh_frame DWARF + // GENERIC // GDB LLDB VALUE REGS INVALIDATE REGS - // ================================ ========================= ====================== ========================= + // ================================ ========================= + // ====================== ========================= // =================== ================= ========== =============== {DEFINE_GPR(rax, nullptr), - {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rax_x86_64}, + {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rax_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rbx, nullptr), - {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, + {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rcx, nullptr), - {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, + {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rdx, nullptr), - {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, + {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rdi, nullptr), - {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, + {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rsi, nullptr), - {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, + {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r8, nullptr), - {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r8_x86_64}, + {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r8_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r9, nullptr), - {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r9_x86_64}, + {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r9_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r10, nullptr), - {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r10_x86_64}, + {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r10_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r11, nullptr), - {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r11_x86_64}, + {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r11_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r12, nullptr), - {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r12_x86_64}, + {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r12_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r13, nullptr), - {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r13_x86_64}, + {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r13_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r14, nullptr), - {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r14_x86_64}, + {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r14_x86_64}, nullptr, nullptr}, {DEFINE_GPR(r15, nullptr), - {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r15_x86_64}, + {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_r15_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rbp, "fp"), - {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, + {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rsp, "sp"), - {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, + {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, nullptr, nullptr}, {DEFINE_GPR(rip, "pc"), - {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_rip_x86_64}, + {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, lldb_rip_x86_64}, nullptr, nullptr}, {DEFINE_GPR_BIN(eflags, "flags"), - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, nullptr, nullptr}, }; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -// Array of lldb register numbers used to define the set of all General Purpose Registers -uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, eRegisterIndexRdx, - eRegisterIndexRdi, eRegisterIndexRsi, eRegisterIndexR8, eRegisterIndexR9, - eRegisterIndexR10, eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, - eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, eRegisterIndexRsp, - eRegisterIndexRip, eRegisterIndexRflags}; +// Array of lldb register numbers used to define the set of all General Purpose +// Registers +uint32_t g_gpr_reg_indices[] = { + eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, + eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi, + eRegisterIndexR8, eRegisterIndexR9, eRegisterIndexR10, + eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, + eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, + eRegisterIndexRsp, eRegisterIndexRip, eRegisterIndexRflags}; RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, + {"General Purpose Registers", "gpr", + llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, }; } //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows_x64::RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) -{ -} +RegisterContextWindows_x64::RegisterContextWindows_x64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows(thread, concrete_frame_idx) {} -RegisterContextWindows_x64::~RegisterContextWindows_x64() -{ -} +RegisterContextWindows_x64::~RegisterContextWindows_x64() {} -size_t -RegisterContextWindows_x64::GetRegisterCount() -{ - return llvm::array_lengthof(g_register_infos); +size_t RegisterContextWindows_x64::GetRegisterCount() { + return llvm::array_lengthof(g_register_infos); } const RegisterInfo * -RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; +RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextWindows_x64::GetRegisterSetCount() -{ - return llvm::array_lengthof(g_register_sets); +size_t RegisterContextWindows_x64::GetRegisterSetCount() { + return llvm::array_lengthof(g_register_sets); } -const RegisterSet * -RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) -{ - return &g_register_sets[reg_set]; +const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) { + return &g_register_sets[reg_set]; } -bool -RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - reg_value.SetUInt64(m_context.Rax); - break; - case lldb_rbx_x86_64: - reg_value.SetUInt64(m_context.Rbx); - break; - case lldb_rcx_x86_64: - reg_value.SetUInt64(m_context.Rcx); - break; - case lldb_rdx_x86_64: - reg_value.SetUInt64(m_context.Rdx); - break; - case lldb_rdi_x86_64: - reg_value.SetUInt64(m_context.Rdi); - break; - case lldb_rsi_x86_64: - reg_value.SetUInt64(m_context.Rsi); - break; - case lldb_r8_x86_64: - reg_value.SetUInt64(m_context.R8); - break; - case lldb_r9_x86_64: - reg_value.SetUInt64(m_context.R9); - break; - case lldb_r10_x86_64: - reg_value.SetUInt64(m_context.R10); - break; - case lldb_r11_x86_64: - reg_value.SetUInt64(m_context.R11); - break; - case lldb_r12_x86_64: - reg_value.SetUInt64(m_context.R12); - break; - case lldb_r13_x86_64: - reg_value.SetUInt64(m_context.R13); - break; - case lldb_r14_x86_64: - reg_value.SetUInt64(m_context.R14); - break; - case lldb_r15_x86_64: - reg_value.SetUInt64(m_context.R15); - break; - case lldb_rbp_x86_64: - reg_value.SetUInt64(m_context.Rbp); - break; - case lldb_rsp_x86_64: - reg_value.SetUInt64(m_context.Rsp); - break; - case lldb_rip_x86_64: - reg_value.SetUInt64(m_context.Rip); - break; - case lldb_rflags_x86_64: - reg_value.SetUInt64(m_context.EFlags); - break; - } - return true; + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + reg_value.SetUInt64(m_context.Rax); + break; + case lldb_rbx_x86_64: + reg_value.SetUInt64(m_context.Rbx); + break; + case lldb_rcx_x86_64: + reg_value.SetUInt64(m_context.Rcx); + break; + case lldb_rdx_x86_64: + reg_value.SetUInt64(m_context.Rdx); + break; + case lldb_rdi_x86_64: + reg_value.SetUInt64(m_context.Rdi); + break; + case lldb_rsi_x86_64: + reg_value.SetUInt64(m_context.Rsi); + break; + case lldb_r8_x86_64: + reg_value.SetUInt64(m_context.R8); + break; + case lldb_r9_x86_64: + reg_value.SetUInt64(m_context.R9); + break; + case lldb_r10_x86_64: + reg_value.SetUInt64(m_context.R10); + break; + case lldb_r11_x86_64: + reg_value.SetUInt64(m_context.R11); + break; + case lldb_r12_x86_64: + reg_value.SetUInt64(m_context.R12); + break; + case lldb_r13_x86_64: + reg_value.SetUInt64(m_context.R13); + break; + case lldb_r14_x86_64: + reg_value.SetUInt64(m_context.R14); + break; + case lldb_r15_x86_64: + reg_value.SetUInt64(m_context.R15); + break; + case lldb_rbp_x86_64: + reg_value.SetUInt64(m_context.Rbp); + break; + case lldb_rsp_x86_64: + reg_value.SetUInt64(m_context.Rsp); + break; + case lldb_rip_x86_64: + reg_value.SetUInt64(m_context.Rip); + break; + case lldb_rflags_x86_64: + reg_value.SetUInt64(m_context.EFlags); + break; + } + return true; } -bool -RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - m_context.Rax = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_context.Rbx = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_context.Rcx = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_context.Rdx = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_context.Rdi = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_context.Rsi = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_context.R8 = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_context.R9 = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_context.R10 = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_context.R11 = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_context.R12 = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_context.R13 = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_context.R14 = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_context.R15 = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_context.Rbp = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_context.Rsp = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_context.Rip = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_context.EFlags = reg_value.GetAsUInt64(); - break; - } + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + m_context.Rax = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_context.Rbx = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_context.Rcx = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_context.Rdx = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_context.Rdi = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_context.Rsi = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_context.R8 = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_context.R9 = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_context.R10 = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_context.R11 = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_context.R12 = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_context.R13 = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_context.R14 = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_context.R15 = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_context.Rbp = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_context.Rsp = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_context.Rip = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_context.EFlags = reg_value.GetAsUInt64(); + break; + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h index e69179d99c6..62cedc8fbab 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h @@ -10,38 +10,38 @@ #ifndef liblldb_RegisterContextWindows_x64_H_ #define liblldb_RegisterContextWindows_x64_H_ -#include "lldb/lldb-forward.h" #include "RegisterContextWindows.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows_x64 : public RegisterContextWindows -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows_x64 : public RegisterContextWindows { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows_x64(); + virtual ~RegisterContextWindows_x64(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + size_t GetRegisterCount() override; - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const RegisterSet *GetRegisterSet(size_t reg_set) override; + const RegisterSet *GetRegisterSet(size_t reg_set) override; - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp index 11733eee7cb..04b6ab317ca 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "ProcessWindowsLog.h" -#include "RegisterContext_x86.h" #include "RegisterContextWindows_x86.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" @@ -26,150 +26,178 @@ using namespace lldb_private; #define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary -namespace -{ +namespace { -// This enum defines the layout of the global RegisterInfo array. This is necessary because -// lldb register sets are defined in terms of indices into the register array. As such, the -// order of RegisterInfos defined in global registers array must match the order defined here. -// When defining the register set layouts, these values can appear in an arbitrary order, and that +// This enum defines the layout of the global RegisterInfo array. This is +// necessary because +// lldb register sets are defined in terms of indices into the register array. +// As such, the +// order of RegisterInfos defined in global registers array must match the order +// defined here. +// When defining the register set layouts, these values can appear in an +// arbitrary order, and that // determines the order that register values are displayed in a dump. -enum RegisterIndex -{ - eRegisterIndexEax, - eRegisterIndexEbx, - eRegisterIndexEcx, - eRegisterIndexEdx, - eRegisterIndexEdi, - eRegisterIndexEsi, - eRegisterIndexEbp, - eRegisterIndexEsp, - eRegisterIndexEip, - eRegisterIndexEflags +enum RegisterIndex { + eRegisterIndexEax, + eRegisterIndexEbx, + eRegisterIndexEcx, + eRegisterIndexEdx, + eRegisterIndexEdi, + eRegisterIndexEsi, + eRegisterIndexEbp, + eRegisterIndexEsp, + eRegisterIndexEip, + eRegisterIndexEflags }; // Array of all register information supported by Windows x86 -RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff eh_frame DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS -// ============================== ======================= =================== ========================= =================== ================= ========== =============== - { DEFINE_GPR(eax, nullptr), { ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_eax_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ebx, nullptr), { ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_ebx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ecx, nullptr), { ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_ecx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(edx, nullptr), { ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_edx_i386 }, nullptr, nullptr}, - { DEFINE_GPR(edi, nullptr), { ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_edi_i386 }, nullptr, nullptr}, - { DEFINE_GPR(esi, nullptr), { ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_esi_i386 }, nullptr, nullptr}, - { DEFINE_GPR(ebp, "fp"), { ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, lldb_ebp_i386 }, nullptr, nullptr}, - { DEFINE_GPR(esp, "sp"), { ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, lldb_esp_i386 }, nullptr, nullptr}, - { DEFINE_GPR(eip, "pc"), { ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_eip_i386 }, nullptr, nullptr}, - { DEFINE_GPR_BIN(eflags, "flags"), { ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_eflags_i386}, nullptr, nullptr}, +RegisterInfo g_register_infos[] = { + // Macro auto defines most stuff eh_frame DWARF + // GENERIC GDB LLDB + // VALUE REGS INVALIDATE REGS + // ============================== ======================= + // =================== ========================= =================== + // ================= ========== =============== + {DEFINE_GPR(eax, nullptr), + {ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_eax_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ebx, nullptr), + {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_ebx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ecx, nullptr), + {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_ecx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(edx, nullptr), + {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_edx_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(edi, nullptr), + {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_edi_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(esi, nullptr), + {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, lldb_esi_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(ebp, "fp"), + {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, + LLDB_INVALID_REGNUM, lldb_ebp_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(esp, "sp"), + {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, + LLDB_INVALID_REGNUM, lldb_esp_i386}, + nullptr, + nullptr}, + {DEFINE_GPR(eip, "pc"), + {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_REGNUM, lldb_eip_i386}, + nullptr, + nullptr}, + {DEFINE_GPR_BIN(eflags, "flags"), + {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, + LLDB_INVALID_REGNUM, lldb_eflags_i386}, + nullptr, + nullptr}, }; static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); -// Array of lldb register numbers used to define the set of all General Purpose Registers -uint32_t g_gpr_reg_indices[] = -{ - eRegisterIndexEax, - eRegisterIndexEbx, - eRegisterIndexEcx, - eRegisterIndexEdx, - eRegisterIndexEdi, - eRegisterIndexEsi, - eRegisterIndexEbp, - eRegisterIndexEsp, - eRegisterIndexEip, - eRegisterIndexEflags -}; +// Array of lldb register numbers used to define the set of all General Purpose +// Registers +uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx, + eRegisterIndexEcx, eRegisterIndexEdx, + eRegisterIndexEdi, eRegisterIndexEsi, + eRegisterIndexEbp, eRegisterIndexEsp, + eRegisterIndexEip, eRegisterIndexEflags}; RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, + {"General Purpose Registers", "gpr", + llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, }; } //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ -RegisterContextWindows_x86::RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) -{ -} +RegisterContextWindows_x86::RegisterContextWindows_x86( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows(thread, concrete_frame_idx) {} -RegisterContextWindows_x86::~RegisterContextWindows_x86() -{ -} +RegisterContextWindows_x86::~RegisterContextWindows_x86() {} -size_t -RegisterContextWindows_x86::GetRegisterCount() -{ - return llvm::array_lengthof(g_register_infos); +size_t RegisterContextWindows_x86::GetRegisterCount() { + return llvm::array_lengthof(g_register_infos); } const RegisterInfo * -RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; +RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } -size_t -RegisterContextWindows_x86::GetRegisterSetCount() -{ - return llvm::array_lengthof(g_register_sets); +size_t RegisterContextWindows_x86::GetRegisterSetCount() { + return llvm::array_lengthof(g_register_sets); } -const RegisterSet * -RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) -{ - return &g_register_sets[reg_set]; +const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) { + return &g_register_sets[reg_set]; } -bool -RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; - - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) - { - case lldb_eax_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); - case lldb_ebx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); - case lldb_ecx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); - case lldb_edx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); - case lldb_edi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); - case lldb_esi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); - case lldb_ebp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); - case lldb_esp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); - case lldb_eip_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); - case lldb_eflags_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value); - default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); - break; - } +bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) return false; + + uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + switch (reg) { + case lldb_eax_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); + case lldb_ebx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); + case lldb_ecx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); + case lldb_edx_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); + case lldb_edi_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); + case lldb_esi_i386: + return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); + case lldb_ebp_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); + case lldb_esp_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); + case lldb_eip_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); + case lldb_eflags_i386: + return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, + reg_value); + default: + WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); + break; + } + return false; } -bool -RegisterContextWindows_x86::ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, - RegisterValue ®_value) const -{ - if ((m_context.ContextFlags & flags_required) != flags_required) - { - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", reg_name); - return false; - } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, reg_name); - reg_value.SetUInt32(value); - return true; +bool RegisterContextWindows_x86::ReadRegisterHelper( + DWORD flags_required, const char *reg_name, DWORD value, + RegisterValue ®_value) const { + if ((m_context.ContextFlags & flags_required) != flags_required) { + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", + reg_name); + return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, + reg_name); + reg_value.SetUInt32(value); + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h index 6c29d54dcae..1e3910b5edd 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h @@ -10,42 +10,40 @@ #ifndef liblldb_RegisterContextWindows_x86_H_ #define liblldb_RegisterContextWindows_x86_H_ -#include "lldb/lldb-forward.h" #include "RegisterContextWindows.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindows_x86 : public RegisterContextWindows -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindows_x86 : public RegisterContextWindows { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindows_x86(); + virtual ~RegisterContextWindows_x86(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + size_t GetRegisterCount() override; - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - size_t GetRegisterSetCount() override; + size_t GetRegisterSetCount() override; - const RegisterSet *GetRegisterSet(size_t reg_set) override; + const RegisterSet *GetRegisterSet(size_t reg_set) override; - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; private: - bool - ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, RegisterValue ®_value) const; + bool ReadRegisterHelper(DWORD flags_required, const char *reg_name, + DWORD value, RegisterValue ®_value) const; }; - } #endif // #ifndef liblldb_RegisterContextWindows_x86_H_ diff --git a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp index 2823474cbd5..4dcd7894e4d 100644 --- a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.cpp @@ -1,4 +1,5 @@ -//===-- DebuggerThread.DebuggerThread --------------------------------------*- C++ -*-===// +//===-- DebuggerThread.DebuggerThread --------------------------------------*- +//C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,8 +22,8 @@ #include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" -#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Process.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" @@ -33,517 +34,518 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -struct DebugLaunchContext -{ - DebugLaunchContext(DebuggerThread *thread, const ProcessLaunchInfo &launch_info) - : m_thread(thread) - , m_launch_info(launch_info) - { - } - DebuggerThread *m_thread; - ProcessLaunchInfo m_launch_info; +namespace { +struct DebugLaunchContext { + DebugLaunchContext(DebuggerThread *thread, + const ProcessLaunchInfo &launch_info) + : m_thread(thread), m_launch_info(launch_info) {} + DebuggerThread *m_thread; + ProcessLaunchInfo m_launch_info; }; -struct DebugAttachContext -{ - DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, const ProcessAttachInfo &attach_info) - : m_thread(thread) - , m_pid(pid) - , m_attach_info(attach_info) - { - } - DebuggerThread *m_thread; - lldb::pid_t m_pid; - ProcessAttachInfo m_attach_info; +struct DebugAttachContext { + DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, + const ProcessAttachInfo &attach_info) + : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} + DebuggerThread *m_thread; + lldb::pid_t m_pid; + ProcessAttachInfo m_attach_info; }; } DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) - : m_debug_delegate(debug_delegate) - , m_image_file(nullptr) - , m_debugging_ended_event(nullptr) - , m_is_shutting_down(false) - , m_pid_to_detach(0) - , m_detached(false) -{ - m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + : m_debug_delegate(debug_delegate), m_image_file(nullptr), + m_debugging_ended_event(nullptr), m_is_shutting_down(false), + m_pid_to_detach(0), m_detached(false) { + m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); } -DebuggerThread::~DebuggerThread() -{ - ::CloseHandle(m_debugging_ended_event); -} +DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } -Error -DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) -{ - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str()); +Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread::DebugLaunch launching '%s'", + launch_info.GetExecutableFile().GetPath().c_str()); - Error error; - DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", - DebuggerThreadLaunchRoutine, context, &error)); + Error error; + DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); + HostThread slave_thread(ThreadLauncher::LaunchThread( + "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, + context, &error)); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DebugLaunch couldn't launch debugger thread. %s", error.AsCString()); - } + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DebugLaunch couldn't launch debugger thread. %s", + error.AsCString()); + } - return error; + return error; } -Error -DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid); - - Error error; - DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); - HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", - DebuggerThreadAttachRoutine, context, &error)); +Error DebuggerThread::DebugAttach(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid, - error.AsCString()); - } + Error error; + DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); + HostThread slave_thread(ThreadLauncher::LaunchThread( + "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, + context, &error)); - return error; -} + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid, + error.AsCString()); + } -lldb::thread_result_t -DebuggerThread::DebuggerThreadLaunchRoutine(void *data) -{ - DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); - lldb::thread_result_t result = context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); - delete context; - return result; + return error; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadAttachRoutine(void *data) -{ - DebugAttachContext *context = static_cast<DebugAttachContext *>(data); - lldb::thread_result_t result = - context->m_thread->DebuggerThreadAttachRoutine(context->m_pid, context->m_attach_info); - delete context; - return result; +lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { + DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); + lldb::thread_result_t result = + context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); + delete context; + return result; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info) -{ - // Grab a shared_ptr reference to this so that we know it won't get deleted until after the - // thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to launch '%s' on background thread.", - launch_info.GetExecutableFile().GetPath().c_str()); - - Error error; - ProcessLauncherWindows launcher; - HostProcess process(launcher.LaunchProcess(launch_info, error)); - // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug - // loop and wait until we get the create process debug notification. Note that if the process - // was created successfully, we can throw away the process handle we got from CreateProcess - // because Windows will give us another (potentially more useful?) handle when it sends us the - // CREATE_PROCESS_DEBUG_EVENT. - if (error.Success()) - DebugLoop(); - else - m_debug_delegate->OnDebuggerError(error, 0); - - return 0; +lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { + DebugAttachContext *context = static_cast<DebugAttachContext *>(data); + lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( + context->m_pid, context->m_attach_info); + delete context; + return result; } -lldb::thread_result_t -DebuggerThread::DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - // Grab a shared_ptr reference to this so that we know it won't get deleted until after the - // thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to process '%u' on background thread.", - (DWORD)pid); - - if (!DebugActiveProcess((DWORD)pid)) - { - Error error(::GetLastError(), eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, 0); - return 0; - } - - // The attach was successful, enter the debug loop. From here on out, this is no different than - // a create process operation, so all the same comments in DebugLaunch should apply from this - // point out. +lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( + const ProcessLaunchInfo &launch_info) { + // Grab a shared_ptr reference to this so that we know it won't get deleted + // until after the + // thread routine has exited. + std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread preparing to launch '%s' on background thread.", + launch_info.GetExecutableFile().GetPath().c_str()); + + Error error; + ProcessLauncherWindows launcher; + HostProcess process(launcher.LaunchProcess(launch_info, error)); + // If we couldn't create the process, notify waiters immediately. Otherwise + // enter the debug + // loop and wait until we get the create process debug notification. Note + // that if the process + // was created successfully, we can throw away the process handle we got from + // CreateProcess + // because Windows will give us another (potentially more useful?) handle when + // it sends us the + // CREATE_PROCESS_DEBUG_EVENT. + if (error.Success()) DebugLoop(); + else + m_debug_delegate->OnDebuggerError(error, 0); - return 0; + return 0; } -Error -DebuggerThread::StopDebugging(bool terminate) -{ - Error error; +lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( + lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + // Grab a shared_ptr reference to this so that we know it won't get deleted + // until after the + // thread routine has exited. + std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - lldb::pid_t pid = m_process.GetProcessId(); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to " + "process '%u' on background thread.", + (DWORD)pid); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging('%s') called (inferior=%I64u).", - (terminate ? "true" : "false"), pid); - - // Set m_is_shutting_down to true if it was false. Return if it was already true. - bool expected = false; - if (!m_is_shutting_down.compare_exchange_strong(expected, true)) - return error; - - // Make a copy of the process, since the termination sequence will reset - // DebuggerThread's internal copy and it needs to remain open for the Wait operation. - HostProcess process_copy = m_process; - lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); - - if (terminate) - { - // Initiate the termination before continuing the exception, so that the next debug - // event we get is the exit process event, and not some other event. - BOOL terminate_suceeded = TerminateProcess(handle, 0); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging called TerminateProcess(0x%p, 0) (inferior=%I64u), success='%s'", - handle, pid, (terminate_suceeded ? "true" : "false")); - } + if (!DebugActiveProcess((DWORD)pid)) { + Error error(::GetLastError(), eErrorTypeWin32); + m_debug_delegate->OnDebuggerError(error, 0); + return 0; + } - // If we're stuck waiting for an exception to continue (e.g. the user is at a breakpoint - // messing around in the debugger), continue it now. But only AFTER calling TerminateProcess - // to make sure that the very next call to WaitForDebugEvent is an exit process event. - if (m_active_exception.get()) - { - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, - "StopDebugging masking active exception"); + // The attach was successful, enter the debug loop. From here on out, this is + // no different than + // a create process operation, so all the same comments in DebugLaunch should + // apply from this + // point out. + DebugLoop(); - ContinueAsyncException(ExceptionResult::MaskException); - } + return 0; +} - if (!terminate) - { - // Indicate that we want to detach. - m_pid_to_detach = GetProcess().GetProcessId(); +Error DebuggerThread::StopDebugging(bool terminate) { + Error error; - // Force a fresh break so that the detach can happen from the debugger thread. - if (!::DebugBreakProcess(GetProcess().GetNativeProcess().GetSystemHandle())) - { - error.SetError(::GetLastError(), eErrorTypeWin32); - } - } + lldb::pid_t pid = m_process.GetProcessId(); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging waiting for detach from process %u to complete.", pid); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging('%s') called (inferior=%I64u).", + (terminate ? "true" : "false"), pid); - DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); - if (wait_result != WAIT_OBJECT_0) - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u", - m_debugging_ended_event, wait_result); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging detach from process %u completed successfully.", pid); - } + // Set m_is_shutting_down to true if it was false. Return if it was already + // true. + bool expected = false; + if (!m_is_shutting_down.compare_exchange_strong(expected, true)) + return error; - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging encountered an error while trying to stop process %u. %s", - pid, error.AsCString()); + // Make a copy of the process, since the termination sequence will reset + // DebuggerThread's internal copy and it needs to remain open for the Wait + // operation. + HostProcess process_copy = m_process; + lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); + + if (terminate) { + // Initiate the termination before continuing the exception, so that the + // next debug + // event we get is the exit process event, and not some other event. + BOOL terminate_suceeded = TerminateProcess(handle, 0); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging called " + "TerminateProcess(0x%p, 0) " + "(inferior=%I64u), success='%s'", + handle, pid, (terminate_suceeded ? "true" : "false")); + } + + // If we're stuck waiting for an exception to continue (e.g. the user is at a + // breakpoint + // messing around in the debugger), continue it now. But only AFTER calling + // TerminateProcess + // to make sure that the very next call to WaitForDebugEvent is an exit + // process event. + if (m_active_exception.get()) { + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, + "StopDebugging masking active exception"); + + ContinueAsyncException(ExceptionResult::MaskException); + } + + if (!terminate) { + // Indicate that we want to detach. + m_pid_to_detach = GetProcess().GetProcessId(); + + // Force a fresh break so that the detach can happen from the debugger + // thread. + if (!::DebugBreakProcess( + GetProcess().GetNativeProcess().GetSystemHandle())) { + error.SetError(::GetLastError(), eErrorTypeWin32); } - return error; + } + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging waiting for detach from process %u to complete.", + pid); + + DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); + if (wait_result != WAIT_OBJECT_0) { + error.SetError(GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u", + m_debugging_ended_event, wait_result); + } else { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging detach from process %u completed successfully.", + pid); + } + + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error " + "while trying to stop process %u. %s", + pid, error.AsCString()); + } + return error; } -void -DebuggerThread::ContinueAsyncException(ExceptionResult result) -{ - if (!m_active_exception.get()) - return; +void DebuggerThread::ContinueAsyncException(ExceptionResult result) { + if (!m_active_exception.get()) + return; - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, - "ContinueAsyncException called for inferior process %I64u, broadcasting.", - m_process.GetProcessId()); + WINLOG_IFANY( + WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, + "ContinueAsyncException called for inferior process %I64u, broadcasting.", + m_process.GetProcessId()); - m_active_exception.reset(); - m_exception_pred.SetValue(result, eBroadcastAlways); + m_active_exception.reset(); + m_exception_pred.SetValue(result, eBroadcastAlways); } -void -DebuggerThread::FreeProcessHandles() -{ - m_process = HostProcess(); - m_main_thread = HostThread(); - if (m_image_file) - { - ::CloseHandle(m_image_file); - m_image_file = nullptr; - } +void DebuggerThread::FreeProcessHandles() { + m_process = HostProcess(); + m_main_thread = HostThread(); + if (m_image_file) { + ::CloseHandle(m_image_file); + m_image_file = nullptr; + } } -void -DebuggerThread::DebugLoop() -{ - DEBUG_EVENT dbe = {0}; - bool should_debug = true; - WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); - while (should_debug) - { - WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); - BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); - if (wait_result) - { - DWORD continue_status = DBG_CONTINUE; - switch (dbe.dwDebugEventCode) - { - case EXCEPTION_DEBUG_EVENT: - { - ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); - - if (status == ExceptionResult::MaskException) - continue_status = DBG_CONTINUE; - else if (status == ExceptionResult::SendToApplication) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - - break; - } - case CREATE_THREAD_DEBUG_EVENT: - continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); - break; - case CREATE_PROCESS_DEBUG_EVENT: - continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); - break; - case EXIT_THREAD_DEBUG_EVENT: - continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); - break; - case EXIT_PROCESS_DEBUG_EVENT: - continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); - should_debug = false; - break; - case LOAD_DLL_DEBUG_EVENT: - continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); - break; - case UNLOAD_DLL_DEBUG_EVENT: - continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); - break; - case OUTPUT_DEBUG_STRING_EVENT: - continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); - break; - case RIP_EVENT: - continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); - if (dbe.u.RipInfo.dwType == SLE_ERROR) - should_debug = false; - break; - } - - WINLOGD_IFALL(WINDOWS_LOG_EVENT, "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.", - dbe.dwProcessId, dbe.dwThreadId, continue_status, ::GetCurrentThreadId()); - - ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); - - if (m_detached) - { - should_debug = false; - } - } - else - { - WINERR_IFALL(WINDOWS_LOG_EVENT, - "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u", - ::GetCurrentThreadId(), ::GetLastError()); - - should_debug = false; - } +void DebuggerThread::DebugLoop() { + DEBUG_EVENT dbe = {0}; + bool should_debug = true; + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); + while (should_debug) { + WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); + BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); + if (wait_result) { + DWORD continue_status = DBG_CONTINUE; + switch (dbe.dwDebugEventCode) { + case EXCEPTION_DEBUG_EVENT: { + ExceptionResult status = + HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); + + if (status == ExceptionResult::MaskException) + continue_status = DBG_CONTINUE; + else if (status == ExceptionResult::SendToApplication) + continue_status = DBG_EXCEPTION_NOT_HANDLED; + + break; + } + case CREATE_THREAD_DEBUG_EVENT: + continue_status = + HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); + break; + case CREATE_PROCESS_DEBUG_EVENT: + continue_status = + HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); + break; + case EXIT_THREAD_DEBUG_EVENT: + continue_status = + HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); + break; + case EXIT_PROCESS_DEBUG_EVENT: + continue_status = + HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); + should_debug = false; + break; + case LOAD_DLL_DEBUG_EVENT: + continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); + break; + case UNLOAD_DLL_DEBUG_EVENT: + continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); + break; + case OUTPUT_DEBUG_STRING_EVENT: + continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); + break; + case RIP_EVENT: + continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); + if (dbe.u.RipInfo.dwType == SLE_ERROR) + should_debug = false; + break; + } + + WINLOGD_IFALL( + WINDOWS_LOG_EVENT, + "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.", + dbe.dwProcessId, dbe.dwThreadId, continue_status, + ::GetCurrentThreadId()); + + ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); + + if (m_detached) { + should_debug = false; + } + } else { + WINERR_IFALL( + WINDOWS_LOG_EVENT, + "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u", + ::GetCurrentThreadId(), ::GetLastError()); + + should_debug = false; } - FreeProcessHandles(); + } + FreeProcessHandles(); - WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); - SetEvent(m_debugging_ended_event); + WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); + SetEvent(m_debugging_ended_event); } ExceptionResult -DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id) -{ - if (m_is_shutting_down) - { - // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic exception that - // we use simply to wake up the DebuggerThread so that we can close out the debug loop. - if (m_pid_to_detach != 0 && info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) - { - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS, - "Breakpoint exception is cue to detach from process 0x%x", - m_pid_to_detach.load()); - ::DebugActiveProcessStop(m_pid_to_detach); - m_detached = true; - } - - // Don't perform any blocking operations while we're shutting down. That will - // cause TerminateProcess -> WaitForSingleObject to time out. - return ExceptionResult::SendToApplication; +DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, + DWORD thread_id) { + if (m_is_shutting_down) { + // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic + // exception that + // we use simply to wake up the DebuggerThread so that we can close out the + // debug loop. + if (m_pid_to_detach != 0 && + info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | + WINDOWS_LOG_PROCESS, + "Breakpoint exception is cue to detach from process 0x%x", + m_pid_to_detach.load()); + ::DebugActiveProcessStop(m_pid_to_detach); + m_detached = true; } - bool first_chance = (info.dwFirstChance != 0); + // Don't perform any blocking operations while we're shutting down. That + // will + // cause TerminateProcess -> WaitForSingleObject to time out. + return ExceptionResult::SendToApplication; + } + + bool first_chance = (info.dwFirstChance != 0); - m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id)); - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, - "HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x", - first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id); + m_active_exception.reset( + new ExceptionRecord(info.ExceptionRecord, thread_id)); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "HandleExceptionEvent encountered %s chance exception 0x%x on " + "thread 0x%x", + first_chance ? "first" : "second", + info.ExceptionRecord.ExceptionCode, thread_id); - ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, - *m_active_exception); - m_exception_pred.SetValue(result, eBroadcastNever); + ExceptionResult result = + m_debug_delegate->OnDebugException(first_chance, *m_active_exception); + m_exception_pred.SetValue(result, eBroadcastNever); - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, - "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger"); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred " + "!= BreakInDebugger"); - m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result); + m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, + result); - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, - "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", - m_exception_pred.GetValue()); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", + m_exception_pred.GetValue()); - return result; + return result; } DWORD -DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u", - thread_id, m_process.GetProcessId()); - HostThread thread(info.hThread); - thread.GetNativeThread().SetOwnsHandle(false); - m_debug_delegate->OnCreateThread(thread); - return DBG_CONTINUE; +DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u", + thread_id, m_process.GetProcessId()); + HostThread thread(info.hThread); + thread.GetNativeThread().SetOwnsHandle(false); + m_debug_delegate->OnCreateThread(thread); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id) -{ - uint32_t process_id = ::GetProcessId(info.hProcess); - - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, "HandleCreateProcessEvent process %u spawned", process_id); - - std::string thread_name; - llvm::raw_string_ostream name_stream(thread_name); - name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; - name_stream.flush(); - ThisThread::SetName(thread_name.c_str()); - - // info.hProcess and info.hThread are closed automatically by Windows when - // EXIT_PROCESS_DEBUG_EVENT is received. - m_process = HostProcess(info.hProcess); - ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); - m_main_thread = HostThread(info.hThread); - m_main_thread.GetNativeThread().SetOwnsHandle(false); - m_image_file = info.hFile; - - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); - m_debug_delegate->OnDebuggerConnected(load_addr); - - return DBG_CONTINUE; +DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, + DWORD thread_id) { + uint32_t process_id = ::GetProcessId(info.hProcess); + + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, + "HandleCreateProcessEvent process %u spawned", process_id); + + std::string thread_name; + llvm::raw_string_ostream name_stream(thread_name); + name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; + name_stream.flush(); + ThisThread::SetName(thread_name.c_str()); + + // info.hProcess and info.hThread are closed automatically by Windows when + // EXIT_PROCESS_DEBUG_EVENT is received. + m_process = HostProcess(info.hProcess); + ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); + m_main_thread = HostThread(info.hThread); + m_main_thread.GetNativeThread().SetOwnsHandle(false); + m_image_file = info.hFile; + + lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); + m_debug_delegate->OnDebuggerConnected(load_addr); + + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleExitThreadEvent Thread %u exited with code %u in process %I64u", - thread_id, info.dwExitCode, m_process.GetProcessId()); - m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); - return DBG_CONTINUE; +DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY( + WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleExitThreadEvent Thread %u exited with code %u in process %I64u", + thread_id, info.dwExitCode, m_process.GetProcessId()); + m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, - "HandleExitProcessEvent process %I64u exited with code %u", - m_process.GetProcessId(), info.dwExitCode); +DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, + "HandleExitProcessEvent process %I64u exited with code %u", + m_process.GetProcessId(), info.dwExitCode); - m_debug_delegate->OnExitProcess(info.dwExitCode); + m_debug_delegate->OnExitProcess(info.dwExitCode); - FreeProcessHandles(); - return DBG_CONTINUE; + FreeProcessHandles(); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id) -{ - if (info.hFile == nullptr) - { - // Not sure what this is, so just ignore it. - WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has a NULL file handle, returning...", - m_process.GetProcessId()); - return DBG_CONTINUE; - } - - std::vector<wchar_t> buffer(1); - DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); - if (required_size > 0) - { - buffer.resize(required_size + 1); - required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size, VOLUME_NAME_DOS); - std::string path_str_utf8; - llvm::convertWideToUTF8(buffer.data(), path_str_utf8); - llvm::StringRef path_str = path_str_utf8; - const char *path = path_str.data(); - if (path_str.startswith("\\\\?\\")) - path += 4; - - FileSpec file_spec(path, false); - ModuleSpec module_spec(file_spec); - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); - - WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL '%s' loaded at address 0x%p...", - m_process.GetProcessId(), path, info.lpBaseOfDll); - - m_debug_delegate->OnLoadDll(module_spec, load_addr); - } - else - { - WINERR_IFALL(WINDOWS_LOG_EVENT, - "Inferior %I64u - HandleLoadDllEvent Error %u occurred calling GetFinalPathNameByHandle", - m_process.GetProcessId(), ::GetLastError()); - } - // Windows does not automatically close info.hFile, so we need to do it. - ::CloseHandle(info.hFile); +DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, + DWORD thread_id) { + if (info.hFile == nullptr) { + // Not sure what this is, so just ignore it. + WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has " + "a NULL file handle, returning...", + m_process.GetProcessId()); return DBG_CONTINUE; + } + + std::vector<wchar_t> buffer(1); + DWORD required_size = + GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); + if (required_size > 0) { + buffer.resize(required_size + 1); + required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], + required_size, VOLUME_NAME_DOS); + std::string path_str_utf8; + llvm::convertWideToUTF8(buffer.data(), path_str_utf8); + llvm::StringRef path_str = path_str_utf8; + const char *path = path_str.data(); + if (path_str.startswith("\\\\?\\")) + path += 4; + + FileSpec file_spec(path, false); + ModuleSpec module_spec(file_spec); + lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); + + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL " + "'%s' loaded at address 0x%p...", + m_process.GetProcessId(), path, info.lpBaseOfDll); + + m_debug_delegate->OnLoadDll(module_spec, load_addr); + } else { + WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent Error " + "%u occurred calling " + "GetFinalPathNameByHandle", + m_process.GetProcessId(), ::GetLastError()); + } + // Windows does not automatically close info.hFile, so we need to do it. + ::CloseHandle(info.hFile); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id) -{ - WINLOG_IFALL(WINDOWS_LOG_EVENT, - "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.", - m_process.GetProcessId(), info.lpBaseOfDll); - - m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); - return DBG_CONTINUE; +DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, + DWORD thread_id) { + WINLOG_IFALL(WINDOWS_LOG_EVENT, + "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.", + m_process.GetProcessId(), info.lpBaseOfDll); + + m_debug_delegate->OnUnloadDll( + reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id) -{ - return DBG_CONTINUE; +DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, + DWORD thread_id) { + return DBG_CONTINUE; } DWORD -DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) -{ - WINERR_IFALL(WINDOWS_LOG_EVENT, - "HandleRipEvent encountered error %u (type=%u) in process %I64u thread %u", - info.dwError, info.dwType, m_process.GetProcessId(), thread_id); +DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { + WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %u " + "(type=%u) in process %I64u thread %u", + info.dwError, info.dwType, m_process.GetProcessId(), thread_id); - Error error(info.dwError, eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, info.dwType); + Error error(info.dwError, eErrorTypeWin32); + m_debug_delegate->OnDebuggerError(error, info.dwType); - return DBG_CONTINUE; + return DBG_CONTINUE; } diff --git a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h index 6a261941395..fb536b4cc11 100644 --- a/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h +++ b/lldb/source/Plugins/Process/Windows/Live/DebuggerThread.h @@ -19,8 +19,7 @@ #include "lldb/Host/Predicate.h" #include "lldb/Host/windows/windows.h" -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- // DebuggerThread @@ -28,72 +27,76 @@ namespace lldb_private // Debugs a single process, notifying listeners as appropriate when interesting // things occur. //---------------------------------------------------------------------- -class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> -{ - public: - DebuggerThread(DebugDelegateSP debug_delegate); - virtual ~DebuggerThread(); - - Error DebugLaunch(const ProcessLaunchInfo &launch_info); - Error DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info); - - HostProcess - GetProcess() const - { - return m_process; - } - HostThread - GetMainThread() const - { - return m_main_thread; - } - std::weak_ptr<ExceptionRecord> - GetActiveException() - { - return m_active_exception; - } - - Error StopDebugging(bool terminate); - - void ContinueAsyncException(ExceptionResult result); - - private: - void FreeProcessHandles(); - void DebugLoop(); - ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id); - DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id); - - DebugDelegateSP m_debug_delegate; - - HostProcess m_process; // The process being debugged. - HostThread m_main_thread; // The main thread of the inferior. - HANDLE m_image_file; // The image file of the process being debugged. - - ExceptionRecordSP m_active_exception; // The current exception waiting to be handled - - Predicate<ExceptionResult> m_exception_pred; // A predicate which gets signalled when an exception - // is finished processing and the debug loop can be - // continued. - - HANDLE m_debugging_ended_event; // An event which gets signalled by the debugger thread when it - // exits the debugger loop and is detached from the inferior. - - std::atomic<DWORD> m_pid_to_detach; // Signals the loop to detach from the process (specified by pid). - std::atomic<bool> m_is_shutting_down; // Signals the debug loop to stop processing certain types of - // events that block shutdown. - bool m_detached; // Indicates we've detached from the inferior process and the debug loop can exit. - - static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data); - lldb::thread_result_t DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info); - static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data); - lldb::thread_result_t DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &launch_info); +class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> { +public: + DebuggerThread(DebugDelegateSP debug_delegate); + virtual ~DebuggerThread(); + + Error DebugLaunch(const ProcessLaunchInfo &launch_info); + Error DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info); + + HostProcess GetProcess() const { return m_process; } + HostThread GetMainThread() const { return m_main_thread; } + std::weak_ptr<ExceptionRecord> GetActiveException() { + return m_active_exception; + } + + Error StopDebugging(bool terminate); + + void ContinueAsyncException(ExceptionResult result); + +private: + void FreeProcessHandles(); + void DebugLoop(); + ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id); + DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, + DWORD thread_id); + DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id); + DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id); + + DebugDelegateSP m_debug_delegate; + + HostProcess m_process; // The process being debugged. + HostThread m_main_thread; // The main thread of the inferior. + HANDLE m_image_file; // The image file of the process being debugged. + + ExceptionRecordSP + m_active_exception; // The current exception waiting to be handled + + Predicate<ExceptionResult> + m_exception_pred; // A predicate which gets signalled when an exception + // is finished processing and the debug loop can be + // continued. + + HANDLE m_debugging_ended_event; // An event which gets signalled by the + // debugger thread when it + // exits the debugger loop and is detached from the inferior. + + std::atomic<DWORD> m_pid_to_detach; // Signals the loop to detach from the + // process (specified by pid). + std::atomic<bool> m_is_shutting_down; // Signals the debug loop to stop + // processing certain types of + // events that block shutdown. + bool m_detached; // Indicates we've detached from the inferior process and the + // debug loop can exit. + + static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data); + lldb::thread_result_t + DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info); + static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data); + lldb::thread_result_t + DebuggerThreadAttachRoutine(lldb::pid_t pid, + const ProcessAttachInfo &launch_info); }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h b/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h index a782597555e..cfe1b79cee1 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h +++ b/lldb/source/Plugins/Process/Windows/Live/ForwardDecl.h @@ -14,17 +14,18 @@ // ExceptionResult is returned by the debug delegate to specify how it processed // the exception. -enum class ExceptionResult -{ - BreakInDebugger, // Break in the debugger and give the user a chance to interact with - // the program before continuing. - MaskException, // Eat the exception and don't let the application know it occurred. - SendToApplication // Send the exception to the application to be handled as if there were - // no debugger attached. +enum class ExceptionResult { + BreakInDebugger, // Break in the debugger and give the user a chance to + // interact with + // the program before continuing. + MaskException, // Eat the exception and don't let the application know it + // occurred. + SendToApplication // Send the exception to the application to be handled as if + // there were + // no debugger attached. }; -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; diff --git a/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h b/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h index 6d864de7ed4..e88e0ada053 100644 --- a/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h +++ b/lldb/source/Plugins/Process/Windows/Live/IDebugDelegate.h @@ -15,8 +15,7 @@ #include "lldb/lldb-types.h" #include <string> -namespace lldb_private -{ +namespace lldb_private { class Error; class HostThread; @@ -26,20 +25,21 @@ class HostThread; // IDebugDelegate defines an interface which allows implementors to receive // notification of events that happen in a debugged process. //---------------------------------------------------------------------- -class IDebugDelegate -{ - public: - virtual ~IDebugDelegate() {} +class IDebugDelegate { +public: + virtual ~IDebugDelegate() {} - virtual void OnExitProcess(uint32_t exit_code) = 0; - virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0; - virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) = 0; - virtual void OnCreateThread(const HostThread &thread) = 0; - virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0; - virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) = 0; - virtual void OnUnloadDll(lldb::addr_t module_addr) = 0; - virtual void OnDebugString(const std::string &string) = 0; - virtual void OnDebuggerError(const Error &error, uint32_t type) = 0; + virtual void OnExitProcess(uint32_t exit_code) = 0; + virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0; + virtual ExceptionResult OnDebugException(bool first_chance, + const ExceptionRecord &record) = 0; + virtual void OnCreateThread(const HostThread &thread) = 0; + virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0; + virtual void OnLoadDll(const ModuleSpec &module_spec, + lldb::addr_t module_addr) = 0; + virtual void OnUnloadDll(lldb::addr_t module_addr) = 0; + virtual void OnDebugString(const std::string &string) = 0; + virtual void OnDebuggerError(const Error &error, uint32_t type) = 0; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp index a0ac9725c75..af18999f431 100644 --- a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.cpp @@ -14,78 +14,60 @@ using namespace lldb; using namespace lldb_private; LocalDebugDelegate::LocalDebugDelegate(ProcessWP process) - : m_process(process) -{ -} + : m_process(process) {} -void -LocalDebugDelegate::OnExitProcess(uint32_t exit_code) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnExitProcess(exit_code); +void LocalDebugDelegate::OnExitProcess(uint32_t exit_code) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnExitProcess(exit_code); } -void -LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebuggerConnected(image_base); +void LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebuggerConnected(image_base); } ExceptionResult -LocalDebugDelegate::OnDebugException(bool first_chance, const ExceptionRecord &record) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - return process->OnDebugException(first_chance, record); - else - return ExceptionResult::MaskException; +LocalDebugDelegate::OnDebugException(bool first_chance, + const ExceptionRecord &record) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + return process->OnDebugException(first_chance, record); + else + return ExceptionResult::MaskException; } -void -LocalDebugDelegate::OnCreateThread(const HostThread &thread) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnCreateThread(thread); +void LocalDebugDelegate::OnCreateThread(const HostThread &thread) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnCreateThread(thread); } -void -LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnExitThread(thread_id, exit_code); +void LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, + uint32_t exit_code) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnExitThread(thread_id, exit_code); } -void -LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnLoadDll(module_spec, module_addr); +void LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnLoadDll(module_spec, module_addr); } -void -LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnUnloadDll(module_addr); +void LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnUnloadDll(module_addr); } -void -LocalDebugDelegate::OnDebugString(const std::string &string) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebugString(string); +void LocalDebugDelegate::OnDebugString(const std::string &string) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebugString(string); } -void -LocalDebugDelegate::OnDebuggerError(const Error &error, uint32_t type) -{ - if (ProcessWindowsLiveSP process = GetProcessPointer()) - process->OnDebuggerError(error, type); +void LocalDebugDelegate::OnDebuggerError(const Error &error, uint32_t type) { + if (ProcessWindowsLiveSP process = GetProcessPointer()) + process->OnDebuggerError(error, type); } -ProcessWindowsLiveSP -LocalDebugDelegate::GetProcessPointer() -{ - ProcessSP process = m_process.lock(); - return std::static_pointer_cast<ProcessWindowsLive>(process); +ProcessWindowsLiveSP LocalDebugDelegate::GetProcessPointer() { + ProcessSP process = m_process.lock(); + return std::static_pointer_cast<ProcessWindowsLive>(process); } diff --git a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h index ec2f9418142..17e760c4453 100644 --- a/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h +++ b/lldb/source/Plugins/Process/Windows/Live/LocalDebugDelegate.h @@ -16,8 +16,7 @@ #include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindowsLive; typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; @@ -26,9 +25,11 @@ typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; // LocalDebugDelegate // // LocalDebugDelegate creates a connection between a ProcessWindowsLive and the -// debug driver. This serves to decouple ProcessWindowsLive from the debug driver. +// debug driver. This serves to decouple ProcessWindowsLive from the debug +// driver. // It would be possible to get a similar decoupling by just having -// ProcessWindowsLive implement this interface directly. There are two reasons why +// ProcessWindowsLive implement this interface directly. There are two reasons +// why // we don't do this: // // 1) In the future when we add support for local debugging through LLGS, and we @@ -42,26 +43,26 @@ typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP; // driver), so this adapter serves as a way to transparently hold the // ProcessSP while still keeping it decoupled from the driver. //---------------------------------------------------------------------- -class LocalDebugDelegate : public IDebugDelegate -{ - public: - explicit LocalDebugDelegate(lldb::ProcessWP process); +class LocalDebugDelegate : public IDebugDelegate { +public: + explicit LocalDebugDelegate(lldb::ProcessWP process); - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) override; - void OnCreateThread(const HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &message) override; - void OnDebuggerError(const Error &error, uint32_t type) override; + void OnExitProcess(uint32_t exit_code) override; + void OnDebuggerConnected(lldb::addr_t image_base) override; + ExceptionResult OnDebugException(bool first_chance, + const ExceptionRecord &record) override; + void OnCreateThread(const HostThread &thread) override; + void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; + void OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) override; + void OnUnloadDll(lldb::addr_t module_addr) override; + void OnDebugString(const std::string &message) override; + void OnDebuggerError(const Error &error, uint32_t type) override; - private: - ProcessWindowsLiveSP - GetProcessPointer(); +private: + ProcessWindowsLiveSP GetProcessPointer(); - lldb::ProcessWP m_process; + lldb::ProcessWP m_process; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp index 300e0caa437..9bfa247c2ed 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp @@ -24,9 +24,9 @@ #include "lldb/Core/Section.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" -#include "lldb/Host/HostProcess.h" #include "lldb/Host/HostNativeProcessBase.h" #include "lldb/Host/HostNativeThreadBase.h" +#include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/HostThreadWindows.h" @@ -56,1014 +56,991 @@ using namespace lldb_private; #define BOOL_STR(b) ((b) ? "true" : "false") -namespace -{ - -std::string -GetProcessExecutableName(HANDLE process_handle) -{ - std::vector<wchar_t> file_name; - DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit - DWORD copied = 0; - do - { - file_name_size *= 2; - file_name.resize(file_name_size); - copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), file_name_size); - } while (copied >= file_name_size); - file_name.resize(copied); - std::string result; - llvm::convertWideToUTF8(file_name.data(), result); - return result; +namespace { + +std::string GetProcessExecutableName(HANDLE process_handle) { + std::vector<wchar_t> file_name; + DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit + DWORD copied = 0; + do { + file_name_size *= 2; + file_name.resize(file_name_size); + copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), + file_name_size); + } while (copied >= file_name_size); + file_name.resize(copied); + std::string result; + llvm::convertWideToUTF8(file_name.data(), result); + return result; } -std::string -GetProcessExecutableName(DWORD pid) -{ - std::string file_name; - HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (process_handle != NULL) - { - file_name = GetProcessExecutableName(process_handle); - ::CloseHandle(process_handle); - } - return file_name; +std::string GetProcessExecutableName(DWORD pid) { + std::string file_name; + HANDLE process_handle = + ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (process_handle != NULL) { + file_name = GetProcessExecutableName(process_handle); + ::CloseHandle(process_handle); + } + return file_name; } -} // anonymous namespace +} // anonymous namespace -namespace lldb_private -{ +namespace lldb_private { -// We store a pointer to this class in the ProcessWindows, so that we don't expose Windows +// We store a pointer to this class in the ProcessWindows, so that we don't +// expose Windows // OS specific types and implementation details from a public header file. -class ProcessWindowsData -{ - public: - ProcessWindowsData(bool stop_at_entry) - : m_stop_at_entry(stop_at_entry) - , m_initial_stop_event(nullptr) - , m_initial_stop_received(false) - { - m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - - ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } - - lldb_private::Error m_launch_error; - lldb_private::DebuggerThreadSP m_debugger; - StopInfoSP m_pending_stop_info; - HANDLE m_initial_stop_event; - bool m_stop_at_entry; - bool m_initial_stop_received; - std::map<lldb::tid_t, HostThread> m_new_threads; - std::set<lldb::tid_t> m_exited_threads; +class ProcessWindowsData { +public: + ProcessWindowsData(bool stop_at_entry) + : m_stop_at_entry(stop_at_entry), m_initial_stop_event(nullptr), + m_initial_stop_received(false) { + m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + } + + ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } + + lldb_private::Error m_launch_error; + lldb_private::DebuggerThreadSP m_debugger; + StopInfoSP m_pending_stop_info; + HANDLE m_initial_stop_event; + bool m_stop_at_entry; + bool m_initial_stop_received; + std::map<lldb::tid_t, HostThread> m_new_threads; + std::set<lldb::tid_t> m_exited_threads; }; } //------------------------------------------------------------------------------ // Static functions. -ProcessSP -ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *) -{ - return ProcessSP(new ProcessWindowsLive(target_sp, listener_sp)); +ProcessSP ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *) { + return ProcessSP(new ProcessWindowsLive(target_sp, listener_sp)); } -void -ProcessWindowsLive::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - }); +void ProcessWindowsLive::Initialize() { + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) - : lldb_private::ProcessWindows(target_sp, listener_sp) -{ -} +ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp) + : lldb_private::ProcessWindows(target_sp, listener_sp) {} -ProcessWindowsLive::~ProcessWindowsLive() -{ -} +ProcessWindowsLive::~ProcessWindowsLive() {} -void -ProcessWindowsLive::Terminate() -{ -} +void ProcessWindowsLive::Terminate() {} -lldb_private::ConstString -ProcessWindowsLive::GetPluginNameStatic() -{ - static ConstString g_name("windows"); - return g_name; +lldb_private::ConstString ProcessWindowsLive::GetPluginNameStatic() { + static ConstString g_name("windows"); + return g_name; } -const char * -ProcessWindowsLive::GetPluginDescriptionStatic() -{ - return "Process plugin for Windows"; +const char *ProcessWindowsLive::GetPluginDescriptionStatic() { + return "Process plugin for Windows"; } -Error -ProcessWindowsLive::EnableBreakpointSite(BreakpointSite *bp_site) -{ - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%x)", - bp_site->GetID(), bp_site->GetLoadAddress()); - - Error error = EnableSoftwareBreakpoint(bp_site); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", error.AsCString()); - } - return error; +Error ProcessWindowsLive::EnableBreakpointSite(BreakpointSite *bp_site) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, + "EnableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site->GetID(), bp_site->GetLoadAddress()); + + Error error = EnableSoftwareBreakpoint(bp_site); + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", + error.AsCString()); + } + return error; } -Error -ProcessWindowsLive::DisableBreakpointSite(BreakpointSite *bp_site) -{ - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%x)", - bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); +Error ProcessWindowsLive::DisableBreakpointSite(BreakpointSite *bp_site) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, + "DisableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); - Error error = DisableSoftwareBreakpoint(bp_site); + Error error = DisableSoftwareBreakpoint(bp_site); - if (!error.Success()) - { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", error.AsCString()); - } - return error; + if (!error.Success()) { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", + error.AsCString()); + } + return error; } -bool -ProcessWindowsLive::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - // Add all the threads that were previously running and for which we did not detect a thread - // exited event. - int new_size = 0; - int continued_threads = 0; - int exited_threads = 0; - int new_threads = 0; - - for (ThreadSP old_thread : old_thread_list.Threads()) - { - lldb::tid_t old_thread_id = old_thread->GetID(); - auto exited_thread_iter = m_session_data->m_exited_threads.find(old_thread_id); - if (exited_thread_iter == m_session_data->m_exited_threads.end()) - { - new_thread_list.AddThread(old_thread); - ++new_size; - ++continued_threads; - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and is still running.", - old_thread_id); - } - else - { - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and has exited.", - old_thread_id); - ++exited_threads; - } - } - - // Also add all the threads that are new since the last time we broke into the debugger. - for (const auto &thread_info : m_session_data->m_new_threads) - { - ThreadSP thread(new TargetThreadWindowsLive(*this, thread_info.second)); - thread->SetID(thread_info.first); - new_thread_list.AddThread(thread); - ++new_size; - ++new_threads; - WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u is new since last update.", thread_info.first); +bool ProcessWindowsLive::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + // Add all the threads that were previously running and for which we did not + // detect a thread + // exited event. + int new_size = 0; + int continued_threads = 0; + int exited_threads = 0; + int new_threads = 0; + + for (ThreadSP old_thread : old_thread_list.Threads()) { + lldb::tid_t old_thread_id = old_thread->GetID(); + auto exited_thread_iter = + m_session_data->m_exited_threads.find(old_thread_id); + if (exited_thread_iter == m_session_data->m_exited_threads.end()) { + new_thread_list.AddThread(old_thread); + ++new_size; + ++continued_threads; + WINLOGV_IFALL( + WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u was running and is still running.", + old_thread_id); + } else { + WINLOGV_IFALL(WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u was running and has exited.", + old_thread_id); + ++exited_threads; } - - WINLOG_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", - new_threads, continued_threads, exited_threads); - - m_session_data->m_new_threads.clear(); - m_session_data->m_exited_threads.clear(); - - return new_size > 0; + } + + // Also add all the threads that are new since the last time we broke into the + // debugger. + for (const auto &thread_info : m_session_data->m_new_threads) { + ThreadSP thread(new TargetThreadWindowsLive(*this, thread_info.second)); + thread->SetID(thread_info.first); + new_thread_list.AddThread(thread); + ++new_size; + ++new_threads; + WINLOGV_IFALL(WINDOWS_LOG_THREAD, + "UpdateThreadList - Thread %u is new since last update.", + thread_info.first); + } + + WINLOG_IFALL( + WINDOWS_LOG_THREAD, + "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", + new_threads, continued_threads, exited_threads); + + m_session_data->m_new_threads.clear(); + m_session_data->m_exited_threads.clear(); + + return new_size > 0; } -Error -ProcessWindowsLive::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) -{ - // Even though m_session_data is accessed here, it is before a debugger thread has been - // kicked off. So there's no race conditions, and it shouldn't be necessary to acquire - // the mutex. - - Error result; - if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) - { - StreamString stream; - stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can only be used for debug launches.", - launch_info.GetExecutableFile().GetPath().c_str()); - std::string message = stream.GetString(); - result.SetErrorString(message.c_str()); - - WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); - return result; - } - - bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); - m_session_data.reset(new ProcessWindowsData(stop_at_entry)); - - SetPrivateState(eStateLaunching); - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - m_session_data->m_debugger.reset(new DebuggerThread(delegate)); - DebuggerThreadSP debugger = m_session_data->m_debugger; - - // Kick off the DebugLaunch asynchronously and wait for it to complete. - result = debugger->DebugLaunch(launch_info); - if (result.Fail()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), result.AsCString()); - return result; - } - - HostProcess process; - Error error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), error.AsCString()); - return error; - } - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", - launch_info.GetExecutableFile().GetPath().c_str()); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state - // should already be set to eStateStopped as a result of hitting the initial breakpoint. If - // it was not set, the breakpoint should have already been resumed from and the private state - // should already be eStateRunning. - launch_info.SetProcessID(process.GetProcessId()); - SetID(process.GetProcessId()); - +Error ProcessWindowsLive::DoLaunch(Module *exe_module, + ProcessLaunchInfo &launch_info) { + // Even though m_session_data is accessed here, it is before a debugger thread + // has been + // kicked off. So there's no race conditions, and it shouldn't be necessary + // to acquire + // the mutex. + + Error result; + if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { + StreamString stream; + stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can " + "only be used for debug launches.", + launch_info.GetExecutableFile().GetPath().c_str()); + std::string message = stream.GetString(); + result.SetErrorString(message.c_str()); + + WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); return result; + } + + bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); + m_session_data.reset(new ProcessWindowsData(stop_at_entry)); + + SetPrivateState(eStateLaunching); + DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); + m_session_data->m_debugger.reset(new DebuggerThread(delegate)); + DebuggerThreadSP debugger = m_session_data->m_debugger; + + // Kick off the DebugLaunch asynchronously and wait for it to complete. + result = debugger->DebugLaunch(launch_info); + if (result.Fail()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", + launch_info.GetExecutableFile().GetPath().c_str(), + result.AsCString()); + return result; + } + + HostProcess process; + Error error = WaitForDebuggerConnection(debugger, process); + if (error.Fail()) { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", + launch_info.GetExecutableFile().GetPath().c_str(), + error.AsCString()); + return error; + } + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", + launch_info.GetExecutableFile().GetPath().c_str()); + + // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the + // private state + // should already be set to eStateStopped as a result of hitting the initial + // breakpoint. If + // it was not set, the breakpoint should have already been resumed from and + // the private state + // should already be eStateRunning. + launch_info.SetProcessID(process.GetProcessId()); + SetID(process.GetProcessId()); + + return result; } -Error -ProcessWindowsLive::DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - m_session_data.reset(new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - DebuggerThreadSP debugger(new DebuggerThread(delegate)); - - m_session_data->m_debugger = debugger; +Error ProcessWindowsLive::DoAttachToProcessWithID( + lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + m_session_data.reset( + new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - DWORD process_id = static_cast<DWORD>(pid); - Error error = debugger->DebugAttach(process_id, attach_info); - if (error.Fail()) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach. %s", - error.AsCString()); - return error; - } - - HostProcess process; - error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DoAttachToProcessWithID encountered an error waiting for the debugger to connect. %s", - error.AsCString()); - return error; - } + DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); + DebuggerThreadSP debugger(new DebuggerThread(delegate)); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID successfully attached to process with pid=%u", - process_id); + m_session_data->m_debugger = debugger; - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state - // should already be set to eStateStopped as a result of hitting the initial breakpoint. If - // it was not set, the breakpoint should have already been resumed from and the private state - // should already be eStateRunning. - SetID(process.GetProcessId()); + DWORD process_id = static_cast<DWORD>(pid); + Error error = debugger->DebugAttach(process_id, attach_info); + if (error.Fail()) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " + "error occurred initiating the " + "asynchronous attach. %s", + error.AsCString()); + return error; + } + + HostProcess process; + error = WaitForDebuggerConnection(debugger, process); + if (error.Fail()) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " + "error waiting for the debugger to " + "connect. %s", + error.AsCString()); return error; + } + + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoAttachToProcessWithID successfully attached to process with pid=%u", + process_id); + + // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the + // private state + // should already be set to eStateStopped as a result of hitting the initial + // breakpoint. If + // it was not set, the breakpoint should have already been resumed from and + // the private state + // should already be eStateRunning. + SetID(process.GetProcessId()); + return error; } -Error -ProcessWindowsLive::WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process) -{ - Error result; - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection Waiting for loader breakpoint."); - - // Block this function until we receive the initial stop from the process. - if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0) - { - WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection hit loader breakpoint, returning."); +Error ProcessWindowsLive::WaitForDebuggerConnection(DebuggerThreadSP debugger, + HostProcess &process) { + Error result; + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, + "WaitForDebuggerConnection Waiting for loader breakpoint."); + + // Block this function until we receive the initial stop from the process. + if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == + WAIT_OBJECT_0) { + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, + "WaitForDebuggerConnection hit loader breakpoint, returning."); + + process = debugger->GetProcess(); + return m_session_data->m_launch_error; + } else + return Error(::GetLastError(), eErrorTypeWin32); +} - process = debugger->GetProcess(); - return m_session_data->m_launch_error; +Error ProcessWindowsLive::DoResume() { + llvm::sys::ScopedLock lock(m_mutex); + Error error; + + StateType private_state = GetPrivateState(); + if (private_state == eStateStopped || private_state == eStateCrashed) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoResume called for process %I64u while state is %u. Resuming...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); + + ExceptionRecordSP active_exception = + m_session_data->m_debugger->GetActiveException().lock(); + if (active_exception) { + // Resume the process and continue processing debug events. Mask + // the exception so that from the process's view, there is no + // indication that anything happened. + m_session_data->m_debugger->ContinueAsyncException( + ExceptionResult::MaskException); } - else - return Error(::GetLastError(), eErrorTypeWin32); -} -Error -ProcessWindowsLive::DoResume() -{ - llvm::sys::ScopedLock lock(m_mutex); - Error error; + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, + "DoResume resuming %u threads.", m_thread_list.GetSize()); - StateType private_state = GetPrivateState(); - if (private_state == eStateStopped || private_state == eStateCrashed) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u while state is %u. Resuming...", - m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); - - ExceptionRecordSP active_exception = - m_session_data->m_debugger->GetActiveException().lock(); - if (active_exception) - { - // Resume the process and continue processing debug events. Mask - // the exception so that from the process's view, there is no - // indication that anything happened. - m_session_data->m_debugger->ContinueAsyncException( - ExceptionResult::MaskException); - } - - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, "DoResume resuming %u threads.", - m_thread_list.GetSize()); - - for (int i = 0; i < m_thread_list.GetSize(); ++i) - { - auto thread = std::static_pointer_cast<TargetThreadWindowsLive>( - m_thread_list.GetThreadAtIndex(i)); - thread->DoResume(); - } - - SetPrivateState(eStateRunning); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u but state is %u. Returning...", - m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); + for (int i = 0; i < m_thread_list.GetSize(); ++i) { + auto thread = std::static_pointer_cast<TargetThreadWindowsLive>( + m_thread_list.GetThreadAtIndex(i)); + thread->DoResume(); } - return error; -} + SetPrivateState(eStateRunning); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "DoResume called for process %I64u but state is %u. Returning...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); + } + return error; +} //------------------------------------------------------------------------------ // ProcessInterface protocol. -lldb_private::ConstString -ProcessWindowsLive::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessWindowsLive::GetPluginVersion() -{ - return 1; +lldb_private::ConstString ProcessWindowsLive::GetPluginName() { + return GetPluginNameStatic(); } -Error -ProcessWindowsLive::DoDetach(bool keep_stopped) -{ - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire the lock only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which - // will also acquire the lock. Thus we have to release the lock before - // calling StopDebugging(). - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "DoDetach called while state = %u, but there is no active session.", - private_state); - return Error(); - } - - debugger_thread = m_session_data->m_debugger; - } +uint32_t ProcessWindowsLive::GetPluginVersion() { return 1; } - Error error; - if (private_state != eStateExited && private_state != eStateDetached) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoDetach called for process %I64u while state = %u. Detaching...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - error = debugger_thread->StopDebugging(false); - if (error.Success()) - { - SetPrivateState(eStateDetached); - } - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DoDetach called for process %I64u while state = %u, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - } +Error ProcessWindowsLive::DoDetach(bool keep_stopped) { + DebuggerThreadSP debugger_thread; + StateType private_state; + { + // Acquire the lock only long enough to get the DebuggerThread. + // StopDebugging() will trigger a call back into ProcessWindows which + // will also acquire the lock. Thus we have to release the lock before + // calling StopDebugging(). + llvm::sys::ScopedLock lock(m_mutex); - return error; -} + private_state = GetPrivateState(); -Error -ProcessWindowsLive::DoDestroy() -{ - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire this lock inside an inner scope, only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which will acquire the lock - // again, so we need to not deadlock. - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called while state = %u, but there is no active session.", - private_state); - return Error(); - } - - debugger_thread = m_session_data->m_debugger; + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "DoDetach called while state = %u, but there is no active session.", + private_state); + return Error(); } - Error error; - if (private_state != eStateExited && private_state != eStateDetached) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = %u. Shutting down...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); - error = debugger_thread->StopDebugging(true); - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } - else - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DoDestroy called for process %I64u while state = %u, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); + debugger_thread = m_session_data->m_debugger; + } + + Error error; + if (private_state != eStateExited && private_state != eStateDetached) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, + "DoDetach called for process %I64u while state = %u. Detaching...", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + error = debugger_thread->StopDebugging(false); + if (error.Success()) { + SetPrivateState(eStateDetached); } - return error; + // By the time StopDebugging returns, there is no more debugger thread, so + // we can be assured that no other thread will race for the session data. + m_session_data.reset(); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, "DoDetach called for process %I64u while state = " + "%u, but cannot destroy in this state.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + } + + return error; } -void -ProcessWindowsLive::RefreshStateAfterStop() -{ +Error ProcessWindowsLive::DoDestroy() { + DebuggerThreadSP debugger_thread; + StateType private_state; + { + // Acquire this lock inside an inner scope, only long enough to get the + // DebuggerThread. + // StopDebugging() will trigger a call back into ProcessWindows which will + // acquire the lock + // again, so we need to not deadlock. llvm::sys::ScopedLock lock(m_mutex); - if (!m_session_data) - { - WINWARN_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called with no active session. Returning..."); - return; - } - - m_thread_list.RefreshStateAfterStop(); + private_state = GetPrivateState(); - std::weak_ptr<ExceptionRecord> exception_record = m_session_data->m_debugger->GetActiveException(); - ExceptionRecordSP active_exception = exception_record.lock(); - if (!active_exception) - { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called for process %I64u but there is no " - "active exception. Why is the process stopped?", - m_session_data->m_debugger->GetProcess().GetProcessId()); - return; + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "DoDestroy called while state = %u, but there is no active session.", + private_state); + return Error(); } - StopInfoSP stop_info; - m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - ThreadSP stop_thread = m_thread_list.GetSelectedThread(); - if (!stop_thread) - return; - - switch (active_exception->GetExceptionCode()) - { - case EXCEPTION_SINGLE_STEP: - { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - const uint64_t pc = register_context->GetPC(); - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site && site->ValidForThisThread(stop_thread.get())) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, - "Single-stepped onto a breakpoint in process %I64u at " - "address 0x%I64x with breakpoint site %d", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); - stop_thread->SetStopInfo(stop_info); - } - else - { - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, - "RefreshStateAfterStop single stepping thread %u", stop_thread->GetID()); - stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); - stop_thread->SetStopInfo(stop_info); - } - return; - } - - case EXCEPTION_BREAKPOINT: - { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - - // The current EIP is AFTER the BP opcode, which is one byte. - uint64_t pc = register_context->GetPC() - 1; - - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "RefreshStateAfterStop detected breakpoint in process %I64u at " - "address 0x%I64x with breakpoint site %d", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); - - if (site->ValidForThisThread(stop_thread.get())) - { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.", - site->GetID(), stop_thread->GetID()); - - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( - *stop_thread, site->GetID()); - register_context->SetPC(pc); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "Breakpoint site %d is not valid for this thread, creating empty stop info.", - site->GetID()); - } - stop_thread->SetStopInfo(stop_info); - return; - } - else - { - // The thread hit a hard-coded breakpoint like an `int 3` or `__debugbreak()`. - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "No breakpoint site matches for this thread. __debugbreak()? " - "Creating stop info with the exception."); - // FALLTHROUGH: We'll treat this as a generic exception record in the default case. - } - } - - default: - { - std::string desc; - llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8) - << " encountered at address " - << llvm::format_hex(active_exception->GetExceptionAddress(), 8); - stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); - WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str()); - return; - } - } + debugger_thread = m_session_data->m_debugger; + } + + Error error; + if (private_state != eStateExited && private_state != eStateDetached) { + WINLOG_IFALL( + WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = " + "%u. Shutting down...", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + error = debugger_thread->StopDebugging(true); + + // By the time StopDebugging returns, there is no more debugger thread, so + // we can be assured that no other thread will race for the session data. + m_session_data.reset(); + } else { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, "DoDestroy called for process %I64u while state = " + "%u, but cannot destroy in this state.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); + } + + return error; } -bool -ProcessWindowsLive::IsAlive() -{ - StateType state = GetPrivateState(); - switch (state) - { - case eStateCrashed: - case eStateDetached: - case eStateUnloaded: - case eStateExited: - case eStateInvalid: - return false; - default: - return true; +void ProcessWindowsLive::RefreshStateAfterStop() { + llvm::sys::ScopedLock lock(m_mutex); + + if (!m_session_data) { + WINWARN_IFALL( + WINDOWS_LOG_PROCESS, + "RefreshStateAfterStop called with no active session. Returning..."); + return; + } + + m_thread_list.RefreshStateAfterStop(); + + std::weak_ptr<ExceptionRecord> exception_record = + m_session_data->m_debugger->GetActiveException(); + ExceptionRecordSP active_exception = exception_record.lock(); + if (!active_exception) { + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "RefreshStateAfterStop called for process %I64u but there is no " + "active exception. Why is the process stopped?", + m_session_data->m_debugger->GetProcess().GetProcessId()); + return; + } + + StopInfoSP stop_info; + m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); + ThreadSP stop_thread = m_thread_list.GetSelectedThread(); + if (!stop_thread) + return; + + switch (active_exception->GetExceptionCode()) { + case EXCEPTION_SINGLE_STEP: { + RegisterContextSP register_context = stop_thread->GetRegisterContext(); + const uint64_t pc = register_context->GetPC(); + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + if (site && site->ValidForThisThread(stop_thread.get())) { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | + WINDOWS_LOG_STEP, + "Single-stepped onto a breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, + site->GetID()); + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, + site->GetID()); + stop_thread->SetStopInfo(stop_info); + } else { + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, + "RefreshStateAfterStop single stepping thread %u", + stop_thread->GetID()); + stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); + stop_thread->SetStopInfo(stop_info); } -} - -Error -ProcessWindowsLive::DoHalt(bool &caused_stop) -{ - Error error; - StateType state = GetPrivateState(); - if (state == eStateStopped) - caused_stop = false; - else - { - llvm::sys::ScopedLock lock(m_mutex); - caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess().GetNativeProcess().GetSystemHandle()); - if (!caused_stop) - { - error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoHalt called DebugBreakProcess, but it failed with error %u", - error.GetError()); - } + return; + } + + case EXCEPTION_BREAKPOINT: { + RegisterContextSP register_context = stop_thread->GetRegisterContext(); + + // The current EIP is AFTER the BP opcode, which is one byte. + uint64_t pc = register_context->GetPC() - 1; + + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + if (site) { + WINLOG_IFANY( + WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "RefreshStateAfterStop detected breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, + site->GetID()); + + if (site->ValidForThisThread(stop_thread.get())) { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is valid for this thread (0x%I64x), " + "creating stop info.", + site->GetID(), stop_thread->GetID()); + + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( + *stop_thread, site->GetID()); + register_context->SetPC(pc); + } else { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is not valid for this thread, " + "creating empty stop info.", + site->GetID()); + } + stop_thread->SetStopInfo(stop_info); + return; + } else { + // The thread hit a hard-coded breakpoint like an `int 3` or + // `__debugbreak()`. + WINLOG_IFALL( + WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "No breakpoint site matches for this thread. __debugbreak()? " + "Creating stop info with the exception."); + // FALLTHROUGH: We'll treat this as a generic exception record in the + // default case. } - return error; -} - -void -ProcessWindowsLive::DidLaunch() -{ - ArchSpec arch_spec; - DidAttach(arch_spec); + } + + default: { + std::string desc; + llvm::raw_string_ostream desc_stream(desc); + desc_stream << "Exception " + << llvm::format_hex(active_exception->GetExceptionCode(), 8) + << " encountered at address " + << llvm::format_hex(active_exception->GetExceptionAddress(), 8); + stop_info = StopInfo::CreateStopReasonWithException( + *stop_thread, desc_stream.str().c_str()); + stop_thread->SetStopInfo(stop_info); + WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str()); + return; + } + } } -void -ProcessWindowsLive::DidAttach(ArchSpec &arch_spec) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // The initial stop won't broadcast the state change event, so account for that here. - if (m_session_data && GetPrivateState() == eStateStopped && m_session_data->m_stop_at_entry) - RefreshStateAfterStop(); +bool ProcessWindowsLive::IsAlive() { + StateType state = GetPrivateState(); + switch (state) { + case eStateCrashed: + case eStateDetached: + case eStateUnloaded: + case eStateExited: + case eStateInvalid: + return false; + default: + return true; + } } -size_t -ProcessWindowsLive::DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - Error &error) -{ +Error ProcessWindowsLive::DoHalt(bool &caused_stop) { + Error error; + StateType state = GetPrivateState(); + if (state == eStateStopped) + caused_stop = false; + else { llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) - return 0; - - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory attempting to read %u bytes from address 0x%I64x", size, vm_addr); - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, buf, size, &bytes_read)) - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", error.GetError()); + caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() + .GetNativeProcess() + .GetSystemHandle()); + if (!caused_stop) { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "DoHalt called DebugBreakProcess, but it failed with error %u", + error.GetError()); } - return bytes_read; + } + return error; } -size_t -ProcessWindowsLive::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) -{ - llvm::sys::ScopedLock lock(m_mutex); - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, vm_addr); +void ProcessWindowsLive::DidLaunch() { + ArchSpec arch_spec; + DidAttach(arch_spec); +} - if (!m_session_data) - { - WINERR_IFANY(WINDOWS_LOG_MEMORY, "DoWriteMemory cannot write, there is no active debugger connection."); - return 0; - } +void ProcessWindowsLive::DidAttach(ArchSpec &arch_spec) { + llvm::sys::ScopedLock lock(m_mutex); - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_written = 0; - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) - FlushInstructionCache(handle, addr, bytes_written); - else - { - error.SetError(GetLastError(), eErrorTypeWin32); - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", error.GetError()); - } - return bytes_written; + // The initial stop won't broadcast the state change event, so account for + // that here. + if (m_session_data && GetPrivateState() == eStateStopped && + m_session_data->m_stop_at_entry) + RefreshStateAfterStop(); } -Error -ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) -{ - Error error; - llvm::sys::ScopedLock lock(m_mutex); - info.Clear(); +size_t ProcessWindowsLive::DoReadMemory(lldb::addr_t vm_addr, void *buf, + size_t size, Error &error) { + llvm::sys::ScopedLock lock(m_mutex); + + if (!m_session_data) + return 0; + + WINLOG_IFALL(WINDOWS_LOG_MEMORY, + "DoReadMemory attempting to read %u bytes from address 0x%I64x", + size, vm_addr); + + HostProcess process = m_session_data->m_debugger->GetProcess(); + void *addr = reinterpret_cast<void *>(vm_addr); + SIZE_T bytes_read = 0; + if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, + buf, size, &bytes_read)) { + error.SetError(GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", + error.GetError()); + } + return bytes_read; +} - if (!m_session_data) - { - error.SetErrorString("GetMemoryRegionInfo called with no debugging session."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); - return error; - } - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (handle == nullptr || handle == LLDB_INVALID_PROCESS) - { - error.SetErrorString("GetMemoryRegionInfo called with an invalid target process."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); - return error; - } +size_t ProcessWindowsLive::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, + size_t size, Error &error) { + llvm::sys::ScopedLock lock(m_mutex); + WINLOG_IFALL( + WINDOWS_LOG_MEMORY, + "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, + vm_addr); + + if (!m_session_data) { + WINERR_IFANY( + WINDOWS_LOG_MEMORY, + "DoWriteMemory cannot write, there is no active debugger connection."); + return 0; + } + + HostProcess process = m_session_data->m_debugger->GetProcess(); + void *addr = reinterpret_cast<void *>(vm_addr); + SIZE_T bytes_written = 0; + lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); + if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) + FlushInstructionCache(handle, addr, bytes_written); + else { + error.SetError(GetLastError(), eErrorTypeWin32); + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", + error.GetError()); + } + return bytes_written; +} - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); - - void *addr = reinterpret_cast<void *>(vm_addr); - MEMORY_BASIC_INFORMATION mem_info = {0}; - SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); - if (result == 0) - { - if (::GetLastError() == ERROR_INVALID_PARAMETER) - { - // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an address - // past the highest accessible address. We should return a range from the vm_addr - // to LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - return error; - } - else - { - error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_MEMORY, - "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", - error.GetError(), vm_addr); - return error; - } - } +Error ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, + MemoryRegionInfo &info) { + Error error; + llvm::sys::ScopedLock lock(m_mutex); + info.Clear(); - // Protect bits are only valid for MEM_COMMIT regions. - if (mem_info.State == MEM_COMMIT) { - const bool readable = IsPageReadable(mem_info.Protect); - const bool executable = IsPageExecutable(mem_info.Protect); - const bool writable = IsPageWritable(mem_info.Protect); - info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - } - else - { - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); + if (!m_session_data) { + error.SetErrorString( + "GetMemoryRegionInfo called with no debugging session."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); + return error; + } + HostProcess process = m_session_data->m_debugger->GetProcess(); + lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); + if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { + error.SetErrorString( + "GetMemoryRegionInfo called with an invalid target process."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); + return error; + } + + WINLOG_IFALL(WINDOWS_LOG_MEMORY, + "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); + + void *addr = reinterpret_cast<void *>(vm_addr); + MEMORY_BASIC_INFORMATION mem_info = {0}; + SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); + if (result == 0) { + if (::GetLastError() == ERROR_INVALID_PARAMETER) { + // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an + // address + // past the highest accessible address. We should return a range from the + // vm_addr + // to LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + return error; + } else { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while " + "getting memory region info for address " + "0x%I64x", + error.GetError(), vm_addr); + return error; } + } + + // Protect bits are only valid for MEM_COMMIT regions. + if (mem_info.State == MEM_COMMIT) { + const bool readable = IsPageReadable(mem_info.Protect); + const bool executable = IsPageExecutable(mem_info.Protect); + const bool writable = IsPageWritable(mem_info.Protect); + info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + info.SetExecutable(executable ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + } else { + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + } + + // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. + if (mem_info.State != MEM_FREE) { + info.GetRange().SetRangeBase( + reinterpret_cast<addr_t>(mem_info.AllocationBase)); + info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + + mem_info.RegionSize); + info.SetMapped(MemoryRegionInfo::eYes); + } else { + // In the unmapped case we need to return the distance to the next block of + // memory. + // VirtualQueryEx nearly does that except that it gives the distance from + // the start + // of the page containing vm_addr. + SYSTEM_INFO data; + GetSystemInfo(&data); + DWORD page_offset = vm_addr % data.dwPageSize; + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); + info.SetMapped(MemoryRegionInfo::eNo); + } + + error.SetError(::GetLastError(), eErrorTypeWin32); + WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: " + "readable=%s, executable=%s, writable=%s", + BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), + BOOL_STR(info.GetWritable())); + return error; +} - // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. - if (mem_info.State != MEM_FREE) { - info.GetRange().SetRangeBase(reinterpret_cast<addr_t>(mem_info.AllocationBase)); - info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + mem_info.RegionSize); - info.SetMapped(MemoryRegionInfo::eYes); - } - else - { - // In the unmapped case we need to return the distance to the next block of memory. - // VirtualQueryEx nearly does that except that it gives the distance from the start - // of the page containing vm_addr. - SYSTEM_INFO data; - GetSystemInfo(&data); - DWORD page_offset = vm_addr % data.dwPageSize; - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); - info.SetMapped(MemoryRegionInfo::eNo); - } +bool ProcessWindowsLive::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + if (plugin_specified_by_name) + return true; - error.SetError(::GetLastError(), eErrorTypeWin32); - WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s", - BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable())); - return error; + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target_sp->GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + // However, if there is no executable module, we return true since we might be + // preparing to attach. + return true; } -bool -ProcessWindowsLive::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - // However, if there is no executable module, we return true since we might be preparing to attach. - return true; +void ProcessWindowsLive::OnExitProcess(uint32_t exit_code) { + // No need to acquire the lock since m_session_data isn't accessed. + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %u exited with code %u", GetID(), + exit_code); + + TargetSP target = m_target_sp.lock(); + if (target) { + ModuleSP executable_module = target->GetExecutableModule(); + ModuleList unloaded_modules; + unloaded_modules.Append(executable_module); + target->ModulesDidUnload(unloaded_modules, true); + } + + SetProcessExitStatus(GetID(), true, 0, exit_code); + SetPrivateState(eStateExited); } -void -ProcessWindowsLive::OnExitProcess(uint32_t exit_code) -{ - // No need to acquire the lock since m_session_data isn't accessed. - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %u exited with code %u", GetID(), exit_code); - - TargetSP target = m_target_sp.lock(); - if (target) - { - ModuleSP executable_module = target->GetExecutableModule(); - ModuleList unloaded_modules; - unloaded_modules.Append(executable_module); - target->ModulesDidUnload(unloaded_modules, true); - } +void ProcessWindowsLive::OnDebuggerConnected(lldb::addr_t image_base) { + DebuggerThreadSP debugger = m_session_data->m_debugger; - SetProcessExitStatus(GetID(), true, 0, exit_code); - SetPrivateState(eStateExited); -} + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "Debugger connected to process %I64u. Image base = 0x%I64x", + debugger->GetProcess().GetProcessId(), image_base); -void -ProcessWindowsLive::OnDebuggerConnected(lldb::addr_t image_base) -{ - DebuggerThreadSP debugger = m_session_data->m_debugger; - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Debugger connected to process %I64u. Image base = 0x%I64x", - debugger->GetProcess().GetProcessId(), image_base); - - ModuleSP module = GetTarget().GetExecutableModule(); - if (!module) - { - // During attach, we won't have the executable module, so find it now. - const DWORD pid = debugger->GetProcess().GetProcessId(); - const std::string file_name = GetProcessExecutableName(pid); - if (file_name.empty()) - { - return; - } - - FileSpec executable_file(file_name, true); - ModuleSpec module_spec(executable_file); - Error error; - module = GetTarget().GetSharedModule(module_spec, &error); - if (!module) - { - return; - } - - GetTarget().SetExecutableModule(module, false); + ModuleSP module = GetTarget().GetExecutableModule(); + if (!module) { + // During attach, we won't have the executable module, so find it now. + const DWORD pid = debugger->GetProcess().GetProcessId(); + const std::string file_name = GetProcessExecutableName(pid); + if (file_name.empty()) { + return; } - bool load_addr_changed; - module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); + FileSpec executable_file(file_name, true); + ModuleSpec module_spec(executable_file); + Error error; + module = GetTarget().GetSharedModule(module_spec, &error); + if (!module) { + return; + } - // Add the main executable module to the list of pending module loads. We can't call - // GetTarget().ModulesDidLoad() here because we still haven't returned from DoLaunch() / DoAttach() yet - // so the target may not have set the process instance to `this` yet. - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wmain_thread = debugger->GetMainThread().GetNativeThread(); - m_session_data->m_new_threads[wmain_thread.GetThreadId()] = debugger->GetMainThread(); + GetTarget().SetExecutableModule(module, false); + } + + bool load_addr_changed; + module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); + + ModuleList loaded_modules; + loaded_modules.Append(module); + GetTarget().ModulesDidLoad(loaded_modules); + + // Add the main executable module to the list of pending module loads. We + // can't call + // GetTarget().ModulesDidLoad() here because we still haven't returned from + // DoLaunch() / DoAttach() yet + // so the target may not have set the process instance to `this` yet. + llvm::sys::ScopedLock lock(m_mutex); + const HostThreadWindows &wmain_thread = + debugger->GetMainThread().GetNativeThread(); + m_session_data->m_new_threads[wmain_thread.GetThreadId()] = + debugger->GetMainThread(); } ExceptionResult -ProcessWindowsLive::OnDebugException(bool first_chance, const ExceptionRecord &record) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // FIXME: Without this check, occasionally when running the test suite there is - // an issue where m_session_data can be null. It's not clear how this could happen - // but it only surfaces while running the test suite. In order to properly diagnose - // this, we probably need to first figure allow the test suite to print out full - // lldb logs, and then add logging to the process plugin. - if (!m_session_data) - { - WINERR_IFANY(WINDOWS_LOG_EXCEPTION, - "Debugger thread reported exception 0x%x at address 0x%I64x, but there is no session.", - record.GetExceptionCode(), record.GetExceptionAddress()); - return ExceptionResult::SendToApplication; - } - - if (!first_chance) - { - // Any second chance exception is an application crash by definition. - SetPrivateState(eStateCrashed); - } - - ExceptionResult result = ExceptionResult::SendToApplication; - switch (record.GetExceptionCode()) - { - case EXCEPTION_BREAKPOINT: - // Handle breakpoints at the first chance. - result = ExceptionResult::BreakInDebugger; - - if (!m_session_data->m_initial_stop_received) - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, - "Hit loader breakpoint at address 0x%I64x, setting initial stop event.", - record.GetExceptionAddress()); - m_session_data->m_initial_stop_received = true; - ::SetEvent(m_session_data->m_initial_stop_event); - } - else - { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, - "Hit non-loader breakpoint at address 0x%I64x.", - record.GetExceptionAddress()); - } - SetPrivateState(eStateStopped); - break; - case EXCEPTION_SINGLE_STEP: - result = ExceptionResult::BreakInDebugger; - SetPrivateState(eStateStopped); - break; - default: - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, - "Debugger thread reported exception 0x%x at address 0x%I64x (first_chance=%s)", - record.GetExceptionCode(), record.GetExceptionAddress(), BOOL_STR(first_chance)); - // For non-breakpoints, give the application a chance to handle the exception first. - if (first_chance) - result = ExceptionResult::SendToApplication; - else - result = ExceptionResult::BreakInDebugger; +ProcessWindowsLive::OnDebugException(bool first_chance, + const ExceptionRecord &record) { + llvm::sys::ScopedLock lock(m_mutex); + + // FIXME: Without this check, occasionally when running the test suite there + // is + // an issue where m_session_data can be null. It's not clear how this could + // happen + // but it only surfaces while running the test suite. In order to properly + // diagnose + // this, we probably need to first figure allow the test suite to print out + // full + // lldb logs, and then add logging to the process plugin. + if (!m_session_data) { + WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " + "0x%x at address 0x%I64x, but there is " + "no session.", + record.GetExceptionCode(), record.GetExceptionAddress()); + return ExceptionResult::SendToApplication; + } + + if (!first_chance) { + // Any second chance exception is an application crash by definition. + SetPrivateState(eStateCrashed); + } + + ExceptionResult result = ExceptionResult::SendToApplication; + switch (record.GetExceptionCode()) { + case EXCEPTION_BREAKPOINT: + // Handle breakpoints at the first chance. + result = ExceptionResult::BreakInDebugger; + + if (!m_session_data->m_initial_stop_received) { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address " + "0x%I64x, setting initial stop " + "event.", + record.GetExceptionAddress()); + m_session_data->m_initial_stop_received = true; + ::SetEvent(m_session_data->m_initial_stop_event); + } else { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, + "Hit non-loader breakpoint at address 0x%I64x.", + record.GetExceptionAddress()); } + SetPrivateState(eStateStopped); + break; + case EXCEPTION_SINGLE_STEP: + result = ExceptionResult::BreakInDebugger; + SetPrivateState(eStateStopped); + break; + default: + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " + "0x%x at address 0x%I64x " + "(first_chance=%s)", + record.GetExceptionCode(), record.GetExceptionAddress(), + BOOL_STR(first_chance)); + // For non-breakpoints, give the application a chance to handle the + // exception first. + if (first_chance) + result = ExceptionResult::SendToApplication; + else + result = ExceptionResult::BreakInDebugger; + } - return result; + return result; } -void -ProcessWindowsLive::OnCreateThread(const HostThread &new_thread) -{ - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); - m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; +void ProcessWindowsLive::OnCreateThread(const HostThread &new_thread) { + llvm::sys::ScopedLock lock(m_mutex); + const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); + m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; } -void -ProcessWindowsLive::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) -{ - llvm::sys::ScopedLock lock(m_mutex); - - // On a forced termination, we may get exit thread events after the session - // data has been cleaned up. - if (!m_session_data) - return; - - // A thread may have started and exited before the debugger stopped allowing a refresh. - // Just remove it from the new threads list in that case. - auto iter = m_session_data->m_new_threads.find(thread_id); - if (iter != m_session_data->m_new_threads.end()) - m_session_data->m_new_threads.erase(iter); - else - m_session_data->m_exited_threads.insert(thread_id); +void ProcessWindowsLive::OnExitThread(lldb::tid_t thread_id, + uint32_t exit_code) { + llvm::sys::ScopedLock lock(m_mutex); + + // On a forced termination, we may get exit thread events after the session + // data has been cleaned up. + if (!m_session_data) + return; + + // A thread may have started and exited before the debugger stopped allowing a + // refresh. + // Just remove it from the new threads list in that case. + auto iter = m_session_data->m_new_threads.find(thread_id); + if (iter != m_session_data->m_new_threads.end()) + m_session_data->m_new_threads.erase(iter); + else + m_session_data->m_exited_threads.insert(thread_id); } -void -ProcessWindowsLive::OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) -{ - // Confusingly, there is no Target::AddSharedModule. Instead, calling GetSharedModule() with - // a new module will add it to the module list and return a corresponding ModuleSP. - Error error; - ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); - bool load_addr_changed = false; - module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); +void ProcessWindowsLive::OnLoadDll(const ModuleSpec &module_spec, + lldb::addr_t module_addr) { + // Confusingly, there is no Target::AddSharedModule. Instead, calling + // GetSharedModule() with + // a new module will add it to the module list and return a corresponding + // ModuleSP. + Error error; + ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); + bool load_addr_changed = false; + module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); + + ModuleList loaded_modules; + loaded_modules.Append(module); + GetTarget().ModulesDidLoad(loaded_modules); } -void -ProcessWindowsLive::OnUnloadDll(lldb::addr_t module_addr) -{ - Address resolved_addr; - if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) - { - ModuleSP module = resolved_addr.GetModule(); - if (module) - { - ModuleList unloaded_modules; - unloaded_modules.Append(module); - GetTarget().ModulesDidUnload(unloaded_modules, false); - } +void ProcessWindowsLive::OnUnloadDll(lldb::addr_t module_addr) { + Address resolved_addr; + if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { + ModuleSP module = resolved_addr.GetModule(); + if (module) { + ModuleList unloaded_modules; + unloaded_modules.Append(module); + GetTarget().ModulesDidUnload(unloaded_modules, false); } + } } -void -ProcessWindowsLive::OnDebugString(const std::string &string) -{ -} - -void -ProcessWindowsLive::OnDebuggerError(const Error &error, uint32_t type) -{ - llvm::sys::ScopedLock lock(m_mutex); - - if (m_session_data->m_initial_stop_received) - { - // This happened while debugging. Do we shutdown the debugging session, try to continue, - // or do something else? - WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. Unexpected behavior may result. %s", - error.GetError(), error.AsCString()); - } - else - { - // If we haven't actually launched the process yet, this was an error launching the - // process. Set the internal error and signal the initial stop event so that the DoLaunch - // method wakes up and returns a failure. - m_session_data->m_launch_error = error; - ::SetEvent(m_session_data->m_initial_stop_event); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred launching the process before the initial stop. %s", - error.GetError(), error.AsCString()); - return; - } +void ProcessWindowsLive::OnDebugString(const std::string &string) {} + +void ProcessWindowsLive::OnDebuggerError(const Error &error, uint32_t type) { + llvm::sys::ScopedLock lock(m_mutex); + + if (m_session_data->m_initial_stop_received) { + // This happened while debugging. Do we shutdown the debugging session, try + // to continue, + // or do something else? + WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. " + "Unexpected behavior may result. %s", + error.GetError(), error.AsCString()); + } else { + // If we haven't actually launched the process yet, this was an error + // launching the + // process. Set the internal error and signal the initial stop event so + // that the DoLaunch + // method wakes up and returns a failure. + m_session_data->m_launch_error = error; + ::SetEvent(m_session_data->m_initial_stop_event); + WINERR_IFALL( + WINDOWS_LOG_PROCESS, + "Error %u occurred launching the process before the initial stop. %s", + error.GetError(), error.AsCString()); + return; + } } diff --git a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h index 657877f529b..89d69f6f043 100644 --- a/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h +++ b/lldb/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h @@ -19,10 +19,10 @@ // Other libraries and framework includes #include "ForwardDecl.h" #include "IDebugDelegate.h" -#include "lldb/lldb-forward.h" #include "lldb/Core/Error.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-forward.h" #include "llvm/Support/Mutex.h" @@ -30,96 +30,100 @@ class ProcessMonitor; -namespace lldb_private -{ +namespace lldb_private { class HostProcess; class ProcessWindowsData; -class ProcessWindowsLive : public lldb_private::ProcessWindows, public lldb_private::IDebugDelegate -{ +class ProcessWindowsLive : public lldb_private::ProcessWindows, + public lldb_private::IDebugDelegate { public: - //------------------------------------------------------------------ - // Static functions. - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *); - - static void - Initialize(); - - static void - Terminate(); - - static lldb_private::ConstString - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessWindowsLive(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp); - - ~ProcessWindowsLive(); - - // lldb_private::Process overrides - lldb_private::ConstString GetPluginName() override; - uint32_t GetPluginVersion() override; - - lldb_private::Error EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - lldb_private::Error DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error DoDetach(bool keep_stopped) override; - lldb_private::Error DoLaunch(lldb_private::Module *exe_module, lldb_private::ProcessLaunchInfo &launch_info) override; - lldb_private::Error DoAttachToProcessWithID(lldb::pid_t pid, - const lldb_private::ProcessAttachInfo &attach_info) override; - lldb_private::Error DoResume() override; - lldb_private::Error DoDestroy() override; - lldb_private::Error DoHalt(bool &caused_stop) override; - - void DidLaunch() override; - void DidAttach(lldb_private::ArchSpec &arch_spec) override; - - void RefreshStateAfterStop() override; - - bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; - bool - DestroyRequiresHalt() override - { - return false; - } - bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override; - bool IsAlive() override; - - size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, lldb_private::Error &error) override; - size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, lldb_private::Error &error) override; - lldb_private::Error GetMemoryRegionInfo(lldb::addr_t vm_addr, lldb_private::MemoryRegionInfo &info) override; - - // IDebugDelegate overrides. - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, const lldb_private::ExceptionRecord &record) override; - void OnCreateThread(const lldb_private::HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const lldb_private::ModuleSpec &module_spec, lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &string) override; - void OnDebuggerError(const lldb_private::Error &error, uint32_t type) override; - - private: - lldb_private::Error WaitForDebuggerConnection(lldb_private::DebuggerThreadSP debugger, - lldb_private::HostProcess &process); - - llvm::sys::Mutex m_mutex; - - // Data for the active debugging session. - std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data; + //------------------------------------------------------------------ + // Static functions. + //------------------------------------------------------------------ + static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *); + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + + ~ProcessWindowsLive(); + + // lldb_private::Process overrides + lldb_private::ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + lldb_private::Error + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + lldb_private::Error + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + + lldb_private::Error DoDetach(bool keep_stopped) override; + lldb_private::Error + DoLaunch(lldb_private::Module *exe_module, + lldb_private::ProcessLaunchInfo &launch_info) override; + lldb_private::Error DoAttachToProcessWithID( + lldb::pid_t pid, + const lldb_private::ProcessAttachInfo &attach_info) override; + lldb_private::Error DoResume() override; + lldb_private::Error DoDestroy() override; + lldb_private::Error DoHalt(bool &caused_stop) override; + + void DidLaunch() override; + void DidAttach(lldb_private::ArchSpec &arch_spec) override; + + void RefreshStateAfterStop() override; + + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + bool DestroyRequiresHalt() override { return false; } + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + bool IsAlive() override; + + size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error) override; + size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t vm_addr, + lldb_private::MemoryRegionInfo &info) override; + + // IDebugDelegate overrides. + void OnExitProcess(uint32_t exit_code) override; + void OnDebuggerConnected(lldb::addr_t image_base) override; + ExceptionResult + OnDebugException(bool first_chance, + const lldb_private::ExceptionRecord &record) override; + void OnCreateThread(const lldb_private::HostThread &thread) override; + void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; + void OnLoadDll(const lldb_private::ModuleSpec &module_spec, + lldb::addr_t module_addr) override; + void OnUnloadDll(lldb::addr_t module_addr) override; + void OnDebugString(const std::string &string) override; + void OnDebuggerError(const lldb_private::Error &error, + uint32_t type) override; + +private: + lldb_private::Error + WaitForDebuggerConnection(lldb_private::DebuggerThreadSP debugger, + lldb_private::HostProcess &process); + + llvm::sys::Mutex m_mutex; + + // Data for the active debugging session. + std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data; }; - } -#endif // liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_ +#endif // liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_ diff --git a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp index 52b32716e67..b965a6cc3dc 100644 --- a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.cpp @@ -16,9 +16,9 @@ #include "lldb/Host/windows/windows.h" #include "lldb/Target/RegisterContext.h" -#include "TargetThreadWindowsLive.h" #include "ProcessWindows.h" #include "ProcessWindowsLog.h" +#include "TargetThreadWindowsLive.h" #include "UnwindLLDB.h" #if defined(_WIN64) @@ -30,118 +30,95 @@ using namespace lldb; using namespace lldb_private; -TargetThreadWindowsLive::TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread) - : TargetThreadWindows(process, thread) - , m_host_thread(thread) -{ -} +TargetThreadWindowsLive::TargetThreadWindowsLive(ProcessWindows &process, + const HostThread &thread) + : TargetThreadWindows(process, thread), m_host_thread(thread) {} -TargetThreadWindowsLive::~TargetThreadWindowsLive() -{ - DestroyThread(); -} +TargetThreadWindowsLive::~TargetThreadWindowsLive() { DestroyThread(); } -void -TargetThreadWindowsLive::RefreshStateAfterStop() -{ - ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - SetState(eStateStopped); - GetRegisterContext()->InvalidateIfNeeded(false); +void TargetThreadWindowsLive::RefreshStateAfterStop() { + ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); + SetState(eStateStopped); + GetRegisterContext()->InvalidateIfNeeded(false); } -void -TargetThreadWindowsLive::WillResume(lldb::StateType resume_state) -{ -} +void TargetThreadWindowsLive::WillResume(lldb::StateType resume_state) {} -void -TargetThreadWindowsLive::DidStop() -{ -} +void TargetThreadWindowsLive::DidStop() {} -RegisterContextSP -TargetThreadWindowsLive::GetRegisterContext() -{ - if (!m_reg_context_sp) - m_reg_context_sp = CreateRegisterContextForFrameIndex(0); +RegisterContextSP TargetThreadWindowsLive::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrameIndex(0); - return m_reg_context_sp; + return m_reg_context_sp; } RegisterContextSP -TargetThreadWindowsLive::CreateRegisterContextForFrame(StackFrame *frame) -{ - return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex()); +TargetThreadWindowsLive::CreateRegisterContextForFrame(StackFrame *frame) { + return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex()); } RegisterContextSP -TargetThreadWindowsLive::CreateRegisterContextForFrameIndex(uint32_t idx) -{ - if (!m_reg_context_sp) - { - ArchSpec arch = HostInfo::GetArchitecture(); - switch (arch.GetMachine()) - { - case llvm::Triple::x86: +TargetThreadWindowsLive::CreateRegisterContextForFrameIndex(uint32_t idx) { + if (!m_reg_context_sp) { + ArchSpec arch = HostInfo::GetArchitecture(); + switch (arch.GetMachine()) { + case llvm::Triple::x86: #if defined(_WIN64) - // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 +// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 #else - m_reg_context_sp.reset(new RegisterContextWindowsLive_x86(*this, idx)); + m_reg_context_sp.reset(new RegisterContextWindowsLive_x86(*this, idx)); #endif - break; - case llvm::Triple::x86_64: + break; + case llvm::Triple::x86_64: #if defined(_WIN64) - m_reg_context_sp.reset(new RegisterContextWindowsLive_x64(*this, idx)); + m_reg_context_sp.reset(new RegisterContextWindowsLive_x64(*this, idx)); #else - // LLDB is 32-bit, but the target process is 64-bit. We probably can't debug this. +// LLDB is 32-bit, but the target process is 64-bit. We probably can't debug +// this. #endif - default: - break; - } + default: + break; } - return m_reg_context_sp; + } + return m_reg_context_sp; } -bool -TargetThreadWindowsLive::CalculateStopInfo() -{ - SetStopInfo(m_stop_info_sp); - return true; +bool TargetThreadWindowsLive::CalculateStopInfo() { + SetStopInfo(m_stop_info_sp); + return true; } -Unwind * -TargetThreadWindowsLive::GetUnwinder() -{ - // FIXME: Implement an unwinder based on the Windows unwinder exposed through DIA SDK. - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); +Unwind *TargetThreadWindowsLive::GetUnwinder() { + // FIXME: Implement an unwinder based on the Windows unwinder exposed through + // DIA SDK. + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + return m_unwinder_ap.get(); } -bool -TargetThreadWindowsLive::DoResume() -{ - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return true; - - if (resume_state == eStateStepping) - { - uint32_t flags_index = GetRegisterContext()->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - uint64_t flags_value = GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); - flags_value |= 0x100; // Set the trap flag on the CPU - GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); - } - - if (resume_state == eStateStepping || resume_state == eStateRunning) - { - DWORD previous_suspend_count = 0; - HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); - do - { - previous_suspend_count = ::ResumeThread(thread_handle); - } while (previous_suspend_count > 0); - } +bool TargetThreadWindowsLive::DoResume() { + StateType resume_state = GetTemporaryResumeState(); + StateType current_state = GetState(); + if (resume_state == current_state) return true; + + if (resume_state == eStateStepping) { + uint32_t flags_index = + GetRegisterContext()->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + uint64_t flags_value = + GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); + flags_value |= 0x100; // Set the trap flag on the CPU + GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); + } + + if (resume_state == eStateStepping || resume_state == eStateRunning) { + DWORD previous_suspend_count = 0; + HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); + do { + previous_suspend_count = ::ResumeThread(thread_handle); + } while (previous_suspend_count > 0); + } + return true; } diff --git a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h index 15262b9e942..47e09247a63 100644 --- a/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h +++ b/lldb/source/Plugins/Process/Windows/Live/TargetThreadWindowsLive.h @@ -10,45 +10,40 @@ #ifndef liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_ #define liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_ -#include "lldb/lldb-forward.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/TargetThreadWindows.h" -namespace lldb_private -{ +namespace lldb_private { class ProcessWindows; class HostThread; class StackFrame; -class TargetThreadWindowsLive : public lldb_private::TargetThreadWindows -{ - public: - TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread); - virtual ~TargetThreadWindowsLive(); - - // lldb_private::Thread overrides - void RefreshStateAfterStop() override; - void WillResume(lldb::StateType resume_state) override; - void DidStop() override; - lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame) override; - bool CalculateStopInfo() override; - Unwind *GetUnwinder() override; - - bool DoResume(); - - HostThread - GetHostThread() const - { - return m_host_thread; - } - - private: - lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx); - - HostThread m_host_thread; +class TargetThreadWindowsLive : public lldb_private::TargetThreadWindows { +public: + TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread); + virtual ~TargetThreadWindowsLive(); + + // lldb_private::Thread overrides + void RefreshStateAfterStop() override; + void WillResume(lldb::StateType resume_state) override; + void DidStop() override; + lldb::RegisterContextSP GetRegisterContext() override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + bool CalculateStopInfo() override; + Unwind *GetUnwinder() override; + + bool DoResume(); + + HostThread GetHostThread() const { return m_host_thread; } + +private: + lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx); + + HostThread m_host_thread; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp index e74647ab68f..33237110991 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.cpp @@ -7,165 +7,160 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "RegisterContextWindowsLive_x64.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; using namespace lldb_private; -RegisterContextWindowsLive_x64::RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows_x64(thread, concrete_frame_idx) -{ -} - -RegisterContextWindowsLive_x64::~RegisterContextWindowsLive_x64() -{ -} +RegisterContextWindowsLive_x64::RegisterContextWindowsLive_x64( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows_x64(thread, concrete_frame_idx) {} +RegisterContextWindowsLive_x64::~RegisterContextWindowsLive_x64() {} -bool -RegisterContextWindowsLive_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - reg_value.SetUInt64(m_context.Rax); - break; - case lldb_rbx_x86_64: - reg_value.SetUInt64(m_context.Rbx); - break; - case lldb_rcx_x86_64: - reg_value.SetUInt64(m_context.Rcx); - break; - case lldb_rdx_x86_64: - reg_value.SetUInt64(m_context.Rdx); - break; - case lldb_rdi_x86_64: - reg_value.SetUInt64(m_context.Rdi); - break; - case lldb_rsi_x86_64: - reg_value.SetUInt64(m_context.Rsi); - break; - case lldb_r8_x86_64: - reg_value.SetUInt64(m_context.R8); - break; - case lldb_r9_x86_64: - reg_value.SetUInt64(m_context.R9); - break; - case lldb_r10_x86_64: - reg_value.SetUInt64(m_context.R10); - break; - case lldb_r11_x86_64: - reg_value.SetUInt64(m_context.R11); - break; - case lldb_r12_x86_64: - reg_value.SetUInt64(m_context.R12); - break; - case lldb_r13_x86_64: - reg_value.SetUInt64(m_context.R13); - break; - case lldb_r14_x86_64: - reg_value.SetUInt64(m_context.R14); - break; - case lldb_r15_x86_64: - reg_value.SetUInt64(m_context.R15); - break; - case lldb_rbp_x86_64: - reg_value.SetUInt64(m_context.Rbp); - break; - case lldb_rsp_x86_64: - reg_value.SetUInt64(m_context.Rsp); - break; - case lldb_rip_x86_64: - reg_value.SetUInt64(m_context.Rip); - break; - case lldb_rflags_x86_64: - reg_value.SetUInt64(m_context.EFlags); - break; - } - return true; + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + reg_value.SetUInt64(m_context.Rax); + break; + case lldb_rbx_x86_64: + reg_value.SetUInt64(m_context.Rbx); + break; + case lldb_rcx_x86_64: + reg_value.SetUInt64(m_context.Rcx); + break; + case lldb_rdx_x86_64: + reg_value.SetUInt64(m_context.Rdx); + break; + case lldb_rdi_x86_64: + reg_value.SetUInt64(m_context.Rdi); + break; + case lldb_rsi_x86_64: + reg_value.SetUInt64(m_context.Rsi); + break; + case lldb_r8_x86_64: + reg_value.SetUInt64(m_context.R8); + break; + case lldb_r9_x86_64: + reg_value.SetUInt64(m_context.R9); + break; + case lldb_r10_x86_64: + reg_value.SetUInt64(m_context.R10); + break; + case lldb_r11_x86_64: + reg_value.SetUInt64(m_context.R11); + break; + case lldb_r12_x86_64: + reg_value.SetUInt64(m_context.R12); + break; + case lldb_r13_x86_64: + reg_value.SetUInt64(m_context.R13); + break; + case lldb_r14_x86_64: + reg_value.SetUInt64(m_context.R14); + break; + case lldb_r15_x86_64: + reg_value.SetUInt64(m_context.R15); + break; + case lldb_rbp_x86_64: + reg_value.SetUInt64(m_context.Rbp); + break; + case lldb_rsp_x86_64: + reg_value.SetUInt64(m_context.Rsp); + break; + case lldb_rip_x86_64: + reg_value.SetUInt64(m_context.Rip); + break; + case lldb_rflags_x86_64: + reg_value.SetUInt64(m_context.EFlags); + break; + } + return true; } -bool -RegisterContextWindowsLive_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - switch (reg_info->kinds[eRegisterKindLLDB]) - { - case lldb_rax_x86_64: - m_context.Rax = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_context.Rbx = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_context.Rcx = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_context.Rdx = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_context.Rdi = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_context.Rsi = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_context.R8 = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_context.R9 = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_context.R10 = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_context.R11 = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_context.R12 = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_context.R13 = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_context.R14 = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_context.R15 = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_context.Rbp = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_context.Rsp = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_context.Rip = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_context.EFlags = reg_value.GetAsUInt64(); - break; - } + switch (reg_info->kinds[eRegisterKindLLDB]) { + case lldb_rax_x86_64: + m_context.Rax = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_context.Rbx = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_context.Rcx = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_context.Rdx = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_context.Rdi = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_context.Rsi = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_context.R8 = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_context.R9 = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_context.R10 = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_context.R11 = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_context.R12 = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_context.R13 = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_context.R14 = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_context.R15 = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_context.Rbp = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_context.Rsp = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_context.Rip = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_context.EFlags = reg_value.GetAsUInt64(); + break; + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } diff --git a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h index bd250a994d3..84425c4fa82 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h +++ b/lldb/source/Plugins/Process/Windows/Live/x64/RegisterContextWindowsLive_x64.h @@ -10,30 +10,30 @@ #ifndef liblldb_RegisterContextWindowsLive_x64_H_ #define liblldb_RegisterContextWindowsLive_x64_H_ -#include "lldb/lldb-forward.h" #include "../../Common/x64/RegisterContextWindows_x64.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsLive_x64 : public RegisterContextWindows_x64 -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindowsLive_x64 : public RegisterContextWindows_x64 { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindowsLive_x64(); + virtual ~RegisterContextWindowsLive_x64(); - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; } diff --git a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp index f2decc72d16..0e7412051ae 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextWindowsLive_x86.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextWindowsLive_x86.cpp ------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,94 +8,101 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" -#include "lldb-x86-register-enums.h" #include "ProcessWindowsLog.h" #include "RegisterContextWindowsLive_x86.h" #include "TargetThreadWindows.h" +#include "lldb-x86-register-enums.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; -namespace lldb_private -{ +namespace lldb_private { -RegisterContextWindowsLive_x86::RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows_x86(thread, concrete_frame_idx) -{ -} - -RegisterContextWindowsLive_x86::~RegisterContextWindowsLive_x86() -{ -} +RegisterContextWindowsLive_x86::RegisterContextWindowsLive_x86( + Thread &thread, uint32_t concrete_frame_idx) + : RegisterContextWindows_x86(thread, concrete_frame_idx) {} +RegisterContextWindowsLive_x86::~RegisterContextWindowsLive_x86() {} -bool -RegisterContextWindowsLive_x86::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - // Since we cannot only write a single register value to the inferior, we need to make sure - // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, - // we may also overwrite some other register with a stale value. - if (!CacheAllRegisterValues()) - return false; +bool RegisterContextWindowsLive_x86::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + // Since we cannot only write a single register value to the inferior, we need + // to make sure + // our cached copy of the register values are fresh. Otherwise when writing + // EAX, for example, + // we may also overwrite some other register with a stale value. + if (!CacheAllRegisterValues()) + return false; - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) - { - case lldb_eax_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX", reg_value.GetAsUInt32()); - m_context.Eax = reg_value.GetAsUInt32(); - break; - case lldb_ebx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX", reg_value.GetAsUInt32()); - m_context.Ebx = reg_value.GetAsUInt32(); - break; - case lldb_ecx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX", reg_value.GetAsUInt32()); - m_context.Ecx = reg_value.GetAsUInt32(); - break; - case lldb_edx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX", reg_value.GetAsUInt32()); - m_context.Edx = reg_value.GetAsUInt32(); - break; - case lldb_edi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI", reg_value.GetAsUInt32()); - m_context.Edi = reg_value.GetAsUInt32(); - break; - case lldb_esi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI", reg_value.GetAsUInt32()); - m_context.Esi = reg_value.GetAsUInt32(); - break; - case lldb_ebp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP", reg_value.GetAsUInt32()); - m_context.Ebp = reg_value.GetAsUInt32(); - break; - case lldb_esp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP", reg_value.GetAsUInt32()); - m_context.Esp = reg_value.GetAsUInt32(); - break; - case lldb_eip_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP", reg_value.GetAsUInt32()); - m_context.Eip = reg_value.GetAsUInt32(); - break; - case lldb_eflags_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS", reg_value.GetAsUInt32()); - m_context.EFlags = reg_value.GetAsUInt32(); - break; - default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to unknown register %u", reg_value.GetAsUInt32(), - reg); - } + uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + switch (reg) { + case lldb_eax_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX", + reg_value.GetAsUInt32()); + m_context.Eax = reg_value.GetAsUInt32(); + break; + case lldb_ebx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX", + reg_value.GetAsUInt32()); + m_context.Ebx = reg_value.GetAsUInt32(); + break; + case lldb_ecx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX", + reg_value.GetAsUInt32()); + m_context.Ecx = reg_value.GetAsUInt32(); + break; + case lldb_edx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX", + reg_value.GetAsUInt32()); + m_context.Edx = reg_value.GetAsUInt32(); + break; + case lldb_edi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI", + reg_value.GetAsUInt32()); + m_context.Edi = reg_value.GetAsUInt32(); + break; + case lldb_esi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI", + reg_value.GetAsUInt32()); + m_context.Esi = reg_value.GetAsUInt32(); + break; + case lldb_ebp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP", + reg_value.GetAsUInt32()); + m_context.Ebp = reg_value.GetAsUInt32(); + break; + case lldb_esp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP", + reg_value.GetAsUInt32()); + m_context.Esp = reg_value.GetAsUInt32(); + break; + case lldb_eip_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP", + reg_value.GetAsUInt32()); + m_context.Eip = reg_value.GetAsUInt32(); + break; + case lldb_eflags_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS", + reg_value.GetAsUInt32()); + m_context.EFlags = reg_value.GetAsUInt32(); + break; + default: + WINWARN_IFALL(WINDOWS_LOG_REGISTERS, + "Write value 0x%x to unknown register %u", + reg_value.GetAsUInt32(), reg); + } - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); + // Physically update the registers in the target process. + TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); + return ::SetThreadContext( + wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h index 9554f017408..e9b8ecd58f5 100644 --- a/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h +++ b/lldb/source/Plugins/Process/Windows/Live/x86/RegisterContextWindowsLive_x86.h @@ -10,27 +10,25 @@ #ifndef liblldb_RegisterContextWindowsLive_x86_H_ #define liblldb_RegisterContextWindowsLive_x86_H_ -#include "lldb/lldb-forward.h" #include "../../Common/x86/RegisterContextWindows_x86.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsLive_x86 : public RegisterContextWindows_x86 -{ - public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx); +class RegisterContextWindowsLive_x86 : public RegisterContextWindows_x86 { +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx); - virtual ~RegisterContextWindowsLive_x86(); + virtual ~RegisterContextWindowsLive_x86(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsLive_x86_H_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp index 05839667688..e7b2dab8ce2 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp @@ -13,9 +13,9 @@ #include <DbgHelp.h> #include <assert.h> -#include <stdlib.h> #include <memory> #include <mutex> +#include <stdlib.h> #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" #include "lldb/Core/DataBufferHeap.h" @@ -47,664 +47,589 @@ using namespace lldb_private; // code, keeping non-portable types out of the header files. // TODO(amccarth): Determine if we need a mutex for access. Given that this is // postmortem debugging, I don't think so. -class ProcessWinMiniDump::Impl -{ +class ProcessWinMiniDump::Impl { public: - Impl(const FileSpec &core_file, ProcessWinMiniDump *self); - ~Impl(); + Impl(const FileSpec &core_file, ProcessWinMiniDump *self); + ~Impl(); - Error - DoLoadCore(); + Error DoLoadCore(); - bool - UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list); + bool UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list); - void - RefreshStateAfterStop(); + void RefreshStateAfterStop(); - size_t - DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error); + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error); - Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info); + Error GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo &info); private: - // Describes a range of memory captured in the mini dump. - struct Range - { - lldb::addr_t start; // virtual address of the beginning of the range - size_t size; // size of the range in bytes - const uint8_t *ptr; // absolute pointer to the first byte of the range - }; - - // If the mini dump has a memory range that contains the desired address, it - // returns true with the details of the range in *range_out. Otherwise, it - // returns false. - bool - FindMemoryRange(lldb::addr_t addr, Range *range_out) const; - - lldb_private::Error - MapMiniDumpIntoMemory(); - - lldb_private::ArchSpec - DetermineArchitecture(); - - void - ReadExceptionRecord(); - - void - ReadMiscInfo(); - - void - ReadModuleList(); - - // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant - // checks. If there's a failure (e.g., if the requested stream doesn't exist), - // the function returns nullptr and sets *size_out to 0. - void * - FindDumpStream(unsigned stream_number, size_t *size_out) const; - - // Getting a string out of a mini dump is a chore. You're usually given a - // relative virtual address (RVA), which points to a counted string that's in - // Windows Unicode (UTF-16). This wrapper handles all the redirection and - // returns a UTF-8 copy of the string. - std::string - GetMiniDumpString(RVA rva) const; - - ProcessWinMiniDump *m_self; // non-owning back pointer - FileSpec m_core_file; - HANDLE m_dump_file; // handle to the open minidump file - HANDLE m_mapping; // handle to the file mapping for the minidump file - void * m_base_addr; // base memory address of the minidump - std::shared_ptr<ExceptionRecord> m_exception_sp; - bool m_is_wow64; // minidump is of a 32-bit process captured with a 64-bit debugger + // Describes a range of memory captured in the mini dump. + struct Range { + lldb::addr_t start; // virtual address of the beginning of the range + size_t size; // size of the range in bytes + const uint8_t *ptr; // absolute pointer to the first byte of the range + }; + + // If the mini dump has a memory range that contains the desired address, it + // returns true with the details of the range in *range_out. Otherwise, it + // returns false. + bool FindMemoryRange(lldb::addr_t addr, Range *range_out) const; + + lldb_private::Error MapMiniDumpIntoMemory(); + + lldb_private::ArchSpec DetermineArchitecture(); + + void ReadExceptionRecord(); + + void ReadMiscInfo(); + + void ReadModuleList(); + + // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant + // checks. If there's a failure (e.g., if the requested stream doesn't + // exist), + // the function returns nullptr and sets *size_out to 0. + void *FindDumpStream(unsigned stream_number, size_t *size_out) const; + + // Getting a string out of a mini dump is a chore. You're usually given a + // relative virtual address (RVA), which points to a counted string that's in + // Windows Unicode (UTF-16). This wrapper handles all the redirection and + // returns a UTF-8 copy of the string. + std::string GetMiniDumpString(RVA rva) const; + + ProcessWinMiniDump *m_self; // non-owning back pointer + FileSpec m_core_file; + HANDLE m_dump_file; // handle to the open minidump file + HANDLE m_mapping; // handle to the file mapping for the minidump file + void *m_base_addr; // base memory address of the minidump + std::shared_ptr<ExceptionRecord> m_exception_sp; + bool m_is_wow64; // minidump is of a 32-bit process captured with a 64-bit + // debugger }; -ProcessWinMiniDump::Impl::Impl(const FileSpec &core_file, ProcessWinMiniDump *self) - : m_self(self), - m_core_file(core_file), - m_dump_file(INVALID_HANDLE_VALUE), - m_mapping(NULL), - m_base_addr(nullptr), - m_exception_sp(), - m_is_wow64(false) -{ -} - -ProcessWinMiniDump::Impl::~Impl() -{ - if (m_base_addr) - { - ::UnmapViewOfFile(m_base_addr); - m_base_addr = nullptr; - } - if (m_mapping) - { - ::CloseHandle(m_mapping); - m_mapping = NULL; - } - if (m_dump_file != INVALID_HANDLE_VALUE) - { - ::CloseHandle(m_dump_file); - m_dump_file = INVALID_HANDLE_VALUE; - } -} - -Error -ProcessWinMiniDump::Impl::DoLoadCore() -{ - Error error = MapMiniDumpIntoMemory(); - if (error.Fail()) - { - return error; - } - - m_self->GetTarget().SetArchitecture(DetermineArchitecture()); - ReadMiscInfo(); // notably for process ID - ReadModuleList(); - ReadExceptionRecord(); - +ProcessWinMiniDump::Impl::Impl(const FileSpec &core_file, + ProcessWinMiniDump *self) + : m_self(self), m_core_file(core_file), m_dump_file(INVALID_HANDLE_VALUE), + m_mapping(NULL), m_base_addr(nullptr), m_exception_sp(), + m_is_wow64(false) {} + +ProcessWinMiniDump::Impl::~Impl() { + if (m_base_addr) { + ::UnmapViewOfFile(m_base_addr); + m_base_addr = nullptr; + } + if (m_mapping) { + ::CloseHandle(m_mapping); + m_mapping = NULL; + } + if (m_dump_file != INVALID_HANDLE_VALUE) { + ::CloseHandle(m_dump_file); + m_dump_file = INVALID_HANDLE_VALUE; + } +} + +Error ProcessWinMiniDump::Impl::DoLoadCore() { + Error error = MapMiniDumpIntoMemory(); + if (error.Fail()) { return error; - -} - -bool -ProcessWinMiniDump::Impl::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - size_t size = 0; - auto thread_list_ptr = static_cast<const MINIDUMP_THREAD_LIST *>(FindDumpStream(ThreadListStream, &size)); - if (thread_list_ptr) - { - const ULONG32 thread_count = thread_list_ptr->NumberOfThreads; - for (ULONG32 i = 0; i < thread_count; ++i) { - const auto &mini_dump_thread = thread_list_ptr->Threads[i]; - auto thread_sp = std::make_shared<ThreadWinMiniDump>(*m_self, mini_dump_thread.ThreadId); - if (mini_dump_thread.ThreadContext.DataSize >= sizeof(CONTEXT)) - { - const CONTEXT *context = reinterpret_cast<const CONTEXT *>(static_cast<const char *>(m_base_addr) + - mini_dump_thread.ThreadContext.Rva); - - if (m_is_wow64) - { - // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. - // If the minidump was captured with a 64-bit debugger, then the CONTEXT - // we just grabbed from the mini_dump_thread is the one for the 64-bit - // "native" process rather than the 32-bit "guest" process we care about. - // In this case, we can get the 32-bit CONTEXT from the TEB (Thread - // Environment Block) of the 64-bit process. - Error error; - TEB64 wow64teb = {0}; - m_self->ReadMemory(mini_dump_thread.Teb, &wow64teb, sizeof(wow64teb), error); - if (error.Success()) - { - // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure - // that includes the 32-bit CONTEXT (after a ULONG). - // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx - const size_t addr = wow64teb.TlsSlots[1]; - Range range = {0}; - if (FindMemoryRange(addr, &range)) - { - lldbassert(range.start <= addr); - const size_t offset = addr - range.start + sizeof(ULONG); - if (offset < range.size) - { - const size_t overlap = range.size - offset; - if (overlap >= sizeof(CONTEXT)) - { - context = reinterpret_cast<const CONTEXT *>(range.ptr + offset); - } - } - } - } - - // NOTE: We don't currently use the TEB for anything else. If we need it in - // the future, the 32-bit TEB is located according to the address stored in the - // first slot of the 64-bit TEB (wow64teb.Reserved1[0]). + } + + m_self->GetTarget().SetArchitecture(DetermineArchitecture()); + ReadMiscInfo(); // notably for process ID + ReadModuleList(); + ReadExceptionRecord(); + + return error; +} + +bool ProcessWinMiniDump::Impl::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + size_t size = 0; + auto thread_list_ptr = static_cast<const MINIDUMP_THREAD_LIST *>( + FindDumpStream(ThreadListStream, &size)); + if (thread_list_ptr) { + const ULONG32 thread_count = thread_list_ptr->NumberOfThreads; + for (ULONG32 i = 0; i < thread_count; ++i) { + const auto &mini_dump_thread = thread_list_ptr->Threads[i]; + auto thread_sp = std::make_shared<ThreadWinMiniDump>( + *m_self, mini_dump_thread.ThreadId); + if (mini_dump_thread.ThreadContext.DataSize >= sizeof(CONTEXT)) { + const CONTEXT *context = reinterpret_cast<const CONTEXT *>( + static_cast<const char *>(m_base_addr) + + mini_dump_thread.ThreadContext.Rva); + + if (m_is_wow64) { + // On Windows, a 32-bit process can run on a 64-bit machine under + // WOW64. + // If the minidump was captured with a 64-bit debugger, then the + // CONTEXT + // we just grabbed from the mini_dump_thread is the one for the 64-bit + // "native" process rather than the 32-bit "guest" process we care + // about. + // In this case, we can get the 32-bit CONTEXT from the TEB (Thread + // Environment Block) of the 64-bit process. + Error error; + TEB64 wow64teb = {0}; + m_self->ReadMemory(mini_dump_thread.Teb, &wow64teb, sizeof(wow64teb), + error); + if (error.Success()) { + // Slot 1 of the thread-local storage in the 64-bit TEB points to a + // structure + // that includes the 32-bit CONTEXT (after a ULONG). + // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx + const size_t addr = wow64teb.TlsSlots[1]; + Range range = {0}; + if (FindMemoryRange(addr, &range)) { + lldbassert(range.start <= addr); + const size_t offset = addr - range.start + sizeof(ULONG); + if (offset < range.size) { + const size_t overlap = range.size - offset; + if (overlap >= sizeof(CONTEXT)) { + context = + reinterpret_cast<const CONTEXT *>(range.ptr + offset); } - - thread_sp->SetContext(context); + } } - new_thread_list.AddThread(thread_sp); - } - } - - return new_thread_list.GetSize(false) > 0; -} + } -void -ProcessWinMiniDump::Impl::RefreshStateAfterStop() -{ - if (!m_exception_sp) - return; - - auto active_exception = m_exception_sp; - std::string desc; - llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8) - << " encountered at address " << llvm::format_hex(active_exception->GetExceptionAddress(), 8); - m_self->m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - auto stop_thread = m_self->m_thread_list.GetSelectedThread(); - auto stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); -} - -size_t -ProcessWinMiniDump::Impl::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - // I don't have a sense of how frequently this is called or how many memory - // ranges a mini dump typically has, so I'm not sure if searching for the - // appropriate range linearly each time is stupid. Perhaps we should build - // an index for faster lookups. - Range range = {0}; - if (!FindMemoryRange(addr, &range)) - { - return 0; - } - - // There's at least some overlap between the beginning of the desired range - // (addr) and the current range. Figure out where the overlap begins and - // how much overlap there is, then copy it to the destination buffer. - lldbassert(range.start <= addr); - const size_t offset = addr - range.start; - lldbassert(offset < range.size); - const size_t overlap = std::min(size, range.size - offset); - std::memcpy(buf, range.ptr + offset, overlap); - return overlap; -} - -Error -ProcessWinMiniDump::Impl::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) -{ - Error error; - size_t size; - info.Clear(); - const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>(FindDumpStream(MemoryInfoListStream, &size)); - if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) - { - error.SetErrorString("the mini dump contains no memory range information"); - return error; - } - - if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO)) - { - error.SetErrorString("the entries in the mini dump memory info list are smaller than expected"); - return error; - } - - if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries) - { - error.SetErrorString("the mini dump memory info list is incomplete"); - return error; - } - - const MINIDUMP_MEMORY_INFO *next_entry = nullptr; - - for (int i = 0; i < list->NumberOfEntries; ++i) - { - const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(list) + - list->SizeOfHeader + i * list->SizeOfEntry); - const auto head = entry->BaseAddress; - const auto tail = head + entry->RegionSize; - if (head <= load_addr && load_addr < tail) - { - info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head : load_addr); - info.GetRange().SetRangeEnd(tail); - info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(IsPageExecutable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - return error; - } - else if (head > load_addr && (next_entry == nullptr || head < next_entry->BaseAddress) ) - { - // In case there is no region containing load_addr keep track of the nearest region - // after load_addr so we can return the distance to it. - next_entry = entry; + // NOTE: We don't currently use the TEB for anything else. If we + // need it in + // the future, the 32-bit TEB is located according to the address + // stored in the + // first slot of the 64-bit TEB (wow64teb.Reserved1[0]). } - } - - // No containing region found. Create an unmapped region that extends to the next region - // or LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(load_addr); - info.GetRange().SetRangeEnd((next_entry != nullptr)?next_entry->BaseAddress:LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - - // Note that the memory info list doesn't seem to contain ranges in kernel space, - // so if you're walking a stack that has kernel frames, the stack may appear - // truncated. - return error; -} -bool -ProcessWinMiniDump::Impl::FindMemoryRange(lldb::addr_t addr, Range *range_out) const -{ - size_t stream_size = 0; - auto mem_list_stream = static_cast<const MINIDUMP_MEMORY_LIST *>(FindDumpStream(MemoryListStream, &stream_size)); - if (mem_list_stream) - { - for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) - { - const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = mem_list_stream->MemoryRanges[i]; - const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory; - const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; - const size_t range_size = loc_desc.DataSize; - if (range_start <= addr && addr < range_start + range_size) - { - range_out->start = range_start; - range_out->size = range_size; - range_out->ptr = reinterpret_cast<const uint8_t *>(m_base_addr) + loc_desc.Rva; - return true; - } - } - } - - // Some mini dumps have a Memory64ListStream that captures all the heap - // memory. We can't exactly use the same loop as above, because the mini - // dump uses slightly different data structures to describe those. - auto mem_list64_stream = static_cast<const MINIDUMP_MEMORY64_LIST *>(FindDumpStream(Memory64ListStream, &stream_size)); - if (mem_list64_stream) - { - size_t base_rva = mem_list64_stream->BaseRva; - for (ULONG32 i = 0; i < mem_list64_stream->NumberOfMemoryRanges; ++i) { - const MINIDUMP_MEMORY_DESCRIPTOR64 &mem_desc = mem_list64_stream->MemoryRanges[i]; - const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; - const size_t range_size = mem_desc.DataSize; - if (range_start <= addr && addr < range_start + range_size) - { - range_out->start = range_start; - range_out->size = range_size; - range_out->ptr = reinterpret_cast<const uint8_t *>(m_base_addr) + base_rva; - return true; - } - base_rva += range_size; - } + thread_sp->SetContext(context); + } + new_thread_list.AddThread(thread_sp); } + } + + return new_thread_list.GetSize(false) > 0; +} + +void ProcessWinMiniDump::Impl::RefreshStateAfterStop() { + if (!m_exception_sp) + return; + + auto active_exception = m_exception_sp; + std::string desc; + llvm::raw_string_ostream desc_stream(desc); + desc_stream << "Exception " + << llvm::format_hex(active_exception->GetExceptionCode(), 8) + << " encountered at address " + << llvm::format_hex(active_exception->GetExceptionAddress(), 8); + m_self->m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); + auto stop_thread = m_self->m_thread_list.GetSelectedThread(); + auto stop_info = StopInfo::CreateStopReasonWithException( + *stop_thread, desc_stream.str().c_str()); + stop_thread->SetStopInfo(stop_info); +} + +size_t ProcessWinMiniDump::Impl::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Error &error) { + // I don't have a sense of how frequently this is called or how many memory + // ranges a mini dump typically has, so I'm not sure if searching for the + // appropriate range linearly each time is stupid. Perhaps we should build + // an index for faster lookups. + Range range = {0}; + if (!FindMemoryRange(addr, &range)) { + return 0; + } + + // There's at least some overlap between the beginning of the desired range + // (addr) and the current range. Figure out where the overlap begins and + // how much overlap there is, then copy it to the destination buffer. + lldbassert(range.start <= addr); + const size_t offset = addr - range.start; + lldbassert(offset < range.size); + const size_t overlap = std::min(size, range.size - offset); + std::memcpy(buf, range.ptr + offset, overlap); + return overlap; +} + +Error ProcessWinMiniDump::Impl::GetMemoryRegionInfo( + lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) { + Error error; + size_t size; + info.Clear(); + const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>( + FindDumpStream(MemoryInfoListStream, &size)); + if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) { + error.SetErrorString("the mini dump contains no memory range information"); + return error; + } - return false; -} + if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO)) { + error.SetErrorString("the entries in the mini dump memory info list are " + "smaller than expected"); + return error; + } -Error -ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory() -{ - Error error; - const char *file = m_core_file.GetCString(); - std::wstring wfile; - if (!llvm::ConvertUTF8toWide(file, wfile)) - { - error.SetErrorString("Error converting path to UTF-16"); - return error; + if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries) { + error.SetErrorString("the mini dump memory info list is incomplete"); + return error; + } + + const MINIDUMP_MEMORY_INFO *next_entry = nullptr; + + for (int i = 0; i < list->NumberOfEntries; ++i) { + const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>( + reinterpret_cast<const char *>(list) + list->SizeOfHeader + + i * list->SizeOfEntry); + const auto head = entry->BaseAddress; + const auto tail = head + entry->RegionSize; + if (head <= load_addr && load_addr < tail) { + info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head + : load_addr); + info.GetRange().SetRangeEnd(tail); + info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetExecutable(IsPageExecutable(entry->Protect) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + return error; + } else if (head > load_addr && + (next_entry == nullptr || head < next_entry->BaseAddress)) { + // In case there is no region containing load_addr keep track of the + // nearest region + // after load_addr so we can return the distance to it. + next_entry = entry; } - m_dump_file = - ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (m_dump_file == INVALID_HANDLE_VALUE) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + } + + // No containing region found. Create an unmapped region that extends to the + // next region + // or LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(load_addr); + info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->BaseAddress + : LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + + // Note that the memory info list doesn't seem to contain ranges in kernel + // space, + // so if you're walking a stack that has kernel frames, the stack may appear + // truncated. + return error; +} + +bool ProcessWinMiniDump::Impl::FindMemoryRange(lldb::addr_t addr, + Range *range_out) const { + size_t stream_size = 0; + auto mem_list_stream = static_cast<const MINIDUMP_MEMORY_LIST *>( + FindDumpStream(MemoryListStream, &stream_size)); + if (mem_list_stream) { + for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) { + const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = + mem_list_stream->MemoryRanges[i]; + const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory; + const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; + const size_t range_size = loc_desc.DataSize; + if (range_start <= addr && addr < range_start + range_size) { + range_out->start = range_start; + range_out->size = range_size; + range_out->ptr = + reinterpret_cast<const uint8_t *>(m_base_addr) + loc_desc.Rva; + return true; + } } - - m_mapping = ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL); - if (m_mapping == NULL) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; - } - - m_base_addr = ::MapViewOfFile(m_mapping, FILE_MAP_READ, 0, 0, 0); - if (m_base_addr == nullptr) - { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return error; + } + + // Some mini dumps have a Memory64ListStream that captures all the heap + // memory. We can't exactly use the same loop as above, because the mini + // dump uses slightly different data structures to describe those. + auto mem_list64_stream = static_cast<const MINIDUMP_MEMORY64_LIST *>( + FindDumpStream(Memory64ListStream, &stream_size)); + if (mem_list64_stream) { + size_t base_rva = mem_list64_stream->BaseRva; + for (ULONG32 i = 0; i < mem_list64_stream->NumberOfMemoryRanges; ++i) { + const MINIDUMP_MEMORY_DESCRIPTOR64 &mem_desc = + mem_list64_stream->MemoryRanges[i]; + const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; + const size_t range_size = mem_desc.DataSize; + if (range_start <= addr && addr < range_start + range_size) { + range_out->start = range_start; + range_out->size = range_size; + range_out->ptr = + reinterpret_cast<const uint8_t *>(m_base_addr) + base_rva; + return true; + } + base_rva += range_size; } + } - return error; + return false; } -ArchSpec -ProcessWinMiniDump::Impl::DetermineArchitecture() -{ - size_t size = 0; - auto system_info_ptr = static_cast<const MINIDUMP_SYSTEM_INFO *>(FindDumpStream(SystemInfoStream, &size)); - if (system_info_ptr) - { - switch (system_info_ptr->ProcessorArchitecture) - { - case PROCESSOR_ARCHITECTURE_INTEL: - if (system_info_ptr->ProcessorLevel == 6) - { - return ArchSpec("i686-pc-windows"); - } - else - { - return ArchSpec("i386-pc-windows"); - } - break; - case PROCESSOR_ARCHITECTURE_AMD64: - return ArchSpec("x86_64-pc-windows"); - default: - break; - } - } +Error ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory() { + Error error; + const char *file = m_core_file.GetCString(); + std::wstring wfile; + if (!llvm::ConvertUTF8toWide(file, wfile)) { + error.SetErrorString("Error converting path to UTF-16"); + return error; + } + m_dump_file = ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_dump_file == INVALID_HANDLE_VALUE) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } - return ArchSpec(); // invalid or unknown -} + m_mapping = + ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL); + if (m_mapping == NULL) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } -void -ProcessWinMiniDump::Impl::ReadExceptionRecord() -{ - size_t size = 0; - auto exception_stream_ptr = static_cast<MINIDUMP_EXCEPTION_STREAM*>(FindDumpStream(ExceptionStream, &size)); - if (exception_stream_ptr) - { - m_exception_sp.reset( - new ExceptionRecord(exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); - } - else - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump has no exception record."); - // TODO: See if we can recover the exception from the TEB. + m_base_addr = ::MapViewOfFile(m_mapping, FILE_MAP_READ, 0, 0, 0); + if (m_base_addr == nullptr) { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + return error; +} + +ArchSpec ProcessWinMiniDump::Impl::DetermineArchitecture() { + size_t size = 0; + auto system_info_ptr = static_cast<const MINIDUMP_SYSTEM_INFO *>( + FindDumpStream(SystemInfoStream, &size)); + if (system_info_ptr) { + switch (system_info_ptr->ProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + if (system_info_ptr->ProcessorLevel == 6) { + return ArchSpec("i686-pc-windows"); + } else { + return ArchSpec("i386-pc-windows"); + } + break; + case PROCESSOR_ARCHITECTURE_AMD64: + return ArchSpec("x86_64-pc-windows"); + default: + break; } -} - -void -ProcessWinMiniDump::Impl::ReadMiscInfo() -{ - size_t size = 0; - const auto misc_info_ptr = static_cast<MINIDUMP_MISC_INFO*>(FindDumpStream(MiscInfoStream, &size)); - if (!misc_info_ptr || size < sizeof(MINIDUMP_MISC_INFO)) { - return; + } + + return ArchSpec(); // invalid or unknown +} + +void ProcessWinMiniDump::Impl::ReadExceptionRecord() { + size_t size = 0; + auto exception_stream_ptr = static_cast<MINIDUMP_EXCEPTION_STREAM *>( + FindDumpStream(ExceptionStream, &size)); + if (exception_stream_ptr) { + m_exception_sp.reset(new ExceptionRecord( + exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); + } else { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump has no exception record."); + // TODO: See if we can recover the exception from the TEB. + } +} + +void ProcessWinMiniDump::Impl::ReadMiscInfo() { + size_t size = 0; + const auto misc_info_ptr = + static_cast<MINIDUMP_MISC_INFO *>(FindDumpStream(MiscInfoStream, &size)); + if (!misc_info_ptr || size < sizeof(MINIDUMP_MISC_INFO)) { + return; + } + + if ((misc_info_ptr->Flags1 & MINIDUMP_MISC1_PROCESS_ID) != 0) { + // This misc info record has the process ID. + m_self->SetID(misc_info_ptr->ProcessId); + } +} + +void ProcessWinMiniDump::Impl::ReadModuleList() { + size_t size = 0; + auto module_list_ptr = static_cast<MINIDUMP_MODULE_LIST *>( + FindDumpStream(ModuleListStream, &size)); + if (!module_list_ptr || module_list_ptr->NumberOfModules == 0) { + return; + } + + for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) { + const auto &module = module_list_ptr->Modules[i]; + const auto file_name = GetMiniDumpString(module.ModuleNameRva); + const auto file_spec = FileSpec(file_name, true); + if (FileSpec::Compare(file_spec, FileSpec("wow64.dll", false), false) == + 0) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump is for a WOW64 process."); + m_is_wow64 = true; } + ModuleSpec module_spec = file_spec; - if ((misc_info_ptr->Flags1 & MINIDUMP_MISC1_PROCESS_ID) != 0) { - // This misc info record has the process ID. - m_self->SetID(misc_info_ptr->ProcessId); + lldb::ModuleSP module_sp = m_self->GetTarget().GetSharedModule(module_spec); + if (!module_sp) { + continue; } + bool load_addr_changed = false; + module_sp->SetLoadAddress(m_self->GetTarget(), module.BaseOfImage, false, + load_addr_changed); + } } -void -ProcessWinMiniDump::Impl::ReadModuleList() -{ - size_t size = 0; - auto module_list_ptr = static_cast<MINIDUMP_MODULE_LIST*>(FindDumpStream(ModuleListStream, &size)); - if (!module_list_ptr || module_list_ptr->NumberOfModules == 0) - { - return; - } +void *ProcessWinMiniDump::Impl::FindDumpStream(unsigned stream_number, + size_t *size_out) const { + void *stream = nullptr; + *size_out = 0; - for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) - { - const auto &module = module_list_ptr->Modules[i]; - const auto file_name = GetMiniDumpString(module.ModuleNameRva); - const auto file_spec = FileSpec(file_name, true); - if (FileSpec::Compare(file_spec, FileSpec("wow64.dll", false), false) == 0) - { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump is for a WOW64 process."); - m_is_wow64 = true; - } - ModuleSpec module_spec = file_spec; + MINIDUMP_DIRECTORY *dir = nullptr; + if (::MiniDumpReadDumpStream(m_base_addr, stream_number, &dir, nullptr, + nullptr) && + dir != nullptr && dir->Location.DataSize > 0) { + assert(dir->StreamType == stream_number); + *size_out = dir->Location.DataSize; + stream = static_cast<void *>(static_cast<char *>(m_base_addr) + + dir->Location.Rva); + } - lldb::ModuleSP module_sp = m_self->GetTarget().GetSharedModule(module_spec); - if (!module_sp) - { - continue; - } - bool load_addr_changed = false; - module_sp->SetLoadAddress(m_self->GetTarget(), module.BaseOfImage, false, load_addr_changed); - } + return stream; } -void * -ProcessWinMiniDump::Impl::FindDumpStream(unsigned stream_number, size_t *size_out) const -{ - void *stream = nullptr; - *size_out = 0; - - MINIDUMP_DIRECTORY *dir = nullptr; - if (::MiniDumpReadDumpStream(m_base_addr, stream_number, &dir, nullptr, nullptr) && dir != nullptr && - dir->Location.DataSize > 0) - { - assert(dir->StreamType == stream_number); - *size_out = dir->Location.DataSize; - stream = static_cast<void *>(static_cast<char *>(m_base_addr) + dir->Location.Rva); - } - - return stream; -} - -std::string -ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const -{ - std::string result; - if (!m_base_addr) - { - return result; - } - auto md_string = reinterpret_cast<const MINIDUMP_STRING *>(static_cast<const char *>(m_base_addr) + rva); - auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer); - const auto source_length = ::wcslen(md_string->Buffer); - const auto source_end = source_start + source_length; - result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length); // worst case length - auto result_start = reinterpret_cast<UTF8 *>(&result[0]); - const auto result_end = result_start + result.size(); - ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion); - const auto result_size = std::distance(reinterpret_cast<UTF8 *>(&result[0]), result_start); - result.resize(result_size); // shrink to actual length +std::string ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const { + std::string result; + if (!m_base_addr) { return result; + } + auto md_string = reinterpret_cast<const MINIDUMP_STRING *>( + static_cast<const char *>(m_base_addr) + rva); + auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer); + const auto source_length = ::wcslen(md_string->Buffer); + const auto source_end = source_start + source_length; + result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * + source_length); // worst case length + auto result_start = reinterpret_cast<UTF8 *>(&result[0]); + const auto result_end = result_start + result.size(); + ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, + strictConversion); + const auto result_size = + std::distance(reinterpret_cast<UTF8 *>(&result[0]), result_start); + result.resize(result_size); // shrink to actual length + return result; } -ConstString -ProcessWinMiniDump::GetPluginNameStatic() -{ - static ConstString g_name("win-minidump"); - return g_name; +ConstString ProcessWinMiniDump::GetPluginNameStatic() { + static ConstString g_name("win-minidump"); + return g_name; } -const char * -ProcessWinMiniDump::GetPluginDescriptionStatic() -{ - return "Windows minidump plug-in."; +const char *ProcessWinMiniDump::GetPluginDescriptionStatic() { + return "Windows minidump plug-in."; } -void -ProcessWinMiniDump::Terminate() -{ - PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); +void ProcessWinMiniDump::Terminate() { + PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); } -lldb::ProcessSP -ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file) -{ - lldb::ProcessSP process_sp; - if (crash_file) - { - process_sp.reset(new ProcessWinMiniDump(target_sp, listener_sp, *crash_file)); - } - return process_sp; +lldb::ProcessSP ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *crash_file) { + lldb::ProcessSP process_sp; + if (crash_file) { + process_sp.reset( + new ProcessWinMiniDump(target_sp, listener_sp, *crash_file)); + } + return process_sp; } -bool -ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - // TODO(amccarth): Eventually, this needs some actual logic. - return true; +bool ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + // TODO(amccarth): Eventually, this needs some actual logic. + return true; } -ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) - : ProcessWindows(target_sp, listener_sp), m_impl_up(new Impl(core_file, this)) -{ -} +ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec &core_file) + : ProcessWindows(target_sp, listener_sp), + m_impl_up(new Impl(core_file, this)) {} -ProcessWinMiniDump::~ProcessWinMiniDump() -{ - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); +ProcessWinMiniDump::~ProcessWinMiniDump() { + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); } -ConstString -ProcessWinMiniDump::GetPluginName() -{ - return GetPluginNameStatic(); +ConstString ProcessWinMiniDump::GetPluginName() { + return GetPluginNameStatic(); } -uint32_t -ProcessWinMiniDump::GetPluginVersion() -{ - return 1; -} +uint32_t ProcessWinMiniDump::GetPluginVersion() { return 1; } -Error -ProcessWinMiniDump::DoLoadCore() -{ - return m_impl_up->DoLoadCore(); -} +Error ProcessWinMiniDump::DoLoadCore() { return m_impl_up->DoLoadCore(); } -DynamicLoader * -ProcessWinMiniDump::GetDynamicLoader() -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset(DynamicLoader::FindPlugin(this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); - return m_dyld_ap.get(); +DynamicLoader *ProcessWinMiniDump::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); + return m_dyld_ap.get(); } -bool -ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - return m_impl_up->UpdateThreadList(old_thread_list, new_thread_list); +bool ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + return m_impl_up->UpdateThreadList(old_thread_list, new_thread_list); } -void -ProcessWinMiniDump::RefreshStateAfterStop() -{ - if (!m_impl_up) - return; - return m_impl_up->RefreshStateAfterStop(); +void ProcessWinMiniDump::RefreshStateAfterStop() { + if (!m_impl_up) + return; + return m_impl_up->RefreshStateAfterStop(); } -Error -ProcessWinMiniDump::DoDestroy() -{ - return Error(); -} +Error ProcessWinMiniDump::DoDestroy() { return Error(); } -bool -ProcessWinMiniDump::IsAlive() -{ - return true; -} +bool ProcessWinMiniDump::IsAlive() { return true; } -bool -ProcessWinMiniDump::WarnBeforeDetach() const -{ - // Since this is post-mortem debugging, there's no need to warn the user - // that quitting the debugger will terminate the process. - return false; +bool ProcessWinMiniDump::WarnBeforeDetach() const { + // Since this is post-mortem debugging, there's no need to warn the user + // that quitting the debugger will terminate the process. + return false; } -size_t -ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - // Don't allow the caching that lldb_private::Process::ReadMemory does - // since we have it all cached our our dump file anyway. - return DoReadMemory(addr, buf, size, error); +size_t ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + Error &error) { + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since we have it all cached our our dump file anyway. + return DoReadMemory(addr, buf, size, error); } -size_t -ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - return m_impl_up->DoReadMemory(addr, buf, size, error); +size_t ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Error &error) { + return m_impl_up->DoReadMemory(addr, buf, size, error); } -Error -ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) -{ - return m_impl_up->GetMemoryRegionInfo(load_addr, info); +Error ProcessWinMiniDump::GetMemoryRegionInfo( + lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) { + return m_impl_up->GetMemoryRegionInfo(load_addr, info); } -void -ProcessWinMiniDump::Clear() -{ - m_thread_list.Clear(); -} +void ProcessWinMiniDump::Clear() { m_thread_list.Clear(); } -void -ProcessWinMiniDump::Initialize() -{ - static std::once_flag g_once_flag; +void ProcessWinMiniDump::Initialize() { + static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); - }); + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } -ArchSpec -ProcessWinMiniDump::GetArchitecture() -{ - // TODO - return ArchSpec(); +ArchSpec ProcessWinMiniDump::GetArchitecture() { + // TODO + return ArchSpec(); } diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h index 3e1ac4bffbe..c242c60d09b 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h @@ -21,84 +21,66 @@ struct ThreadData; -class ProcessWinMiniDump : public lldb_private::ProcessWindows -{ - public: - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); +class ProcessWinMiniDump : public lldb_private::ProcessWindows { +public: + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path); - static void - Initialize(); + static void Initialize(); - static void - Terminate(); + static void Terminate(); - static lldb_private::ConstString - GetPluginNameStatic(); + static lldb_private::ConstString GetPluginNameStatic(); - static const char * - GetPluginDescriptionStatic(); + static const char *GetPluginDescriptionStatic(); - ProcessWinMiniDump(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec &core_file); + ProcessWinMiniDump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec &core_file); - virtual - ~ProcessWinMiniDump(); + virtual ~ProcessWinMiniDump(); - bool - CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; - lldb_private::Error - DoLoadCore() override; + lldb_private::Error DoLoadCore() override; - lldb_private::DynamicLoader * - GetDynamicLoader() override; + lldb_private::DynamicLoader *GetDynamicLoader() override; - lldb_private::ConstString - GetPluginName() override; + lldb_private::ConstString GetPluginName() override; - uint32_t - GetPluginVersion() override; + uint32_t GetPluginVersion() override; - lldb_private::Error - DoDestroy() override; + lldb_private::Error DoDestroy() override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - bool - IsAlive() override; + bool IsAlive() override; - bool - WarnBeforeDetach () const override; + bool WarnBeforeDetach() const override; - size_t - ReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; - size_t - DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; - lldb_private::ArchSpec - GetArchitecture(); + lldb_private::ArchSpec GetArchitecture(); - lldb_private::Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &range_info) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo &range_info) override; - protected: - void - Clear(); +protected: + void Clear(); - bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; - private: - // Keep Windows-specific types out of this header. - class Impl; - std::unique_ptr<Impl> m_impl_up; +private: + // Keep Windows-specific types out of this header. + class Impl; + std::unique_ptr<Impl> m_impl_up; }; -#endif // liblldb_ProcessWinMiniDump_h_ +#endif // liblldb_ProcessWinMiniDump_h_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp index ddcd15b1ae1..a1d637767dc 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.cpp @@ -27,78 +27,61 @@ using namespace lldb_private; // be fleshed out as more mini-dump functionality is added. class ThreadWinMiniDump::Data { - public: - Data() : m_context(nullptr) {} - const CONTEXT *m_context; +public: + Data() : m_context(nullptr) {} + const CONTEXT *m_context; }; -ThreadWinMiniDump::ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid) : - Thread(process, tid), - m_data(new Data) -{ -} +ThreadWinMiniDump::ThreadWinMiniDump(lldb_private::Process &process, + lldb::tid_t tid) + : Thread(process, tid), m_data(new Data) {} -ThreadWinMiniDump::~ThreadWinMiniDump() -{ -} +ThreadWinMiniDump::~ThreadWinMiniDump() {} -void -ThreadWinMiniDump::RefreshStateAfterStop() -{ -} +void ThreadWinMiniDump::RefreshStateAfterStop() {} -lldb::RegisterContextSP -ThreadWinMiniDump::GetRegisterContext() -{ - if (m_reg_context_sp.get() == NULL) { - m_reg_context_sp = CreateRegisterContextForFrame (NULL); - } - return m_reg_context_sp; +lldb::RegisterContextSP ThreadWinMiniDump::GetRegisterContext() { + if (m_reg_context_sp.get() == NULL) { + m_reg_context_sp = CreateRegisterContextForFrame(NULL); + } + return m_reg_context_sp; } -lldb::RegisterContextSP -ThreadWinMiniDump::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - const uint32_t concrete_frame_idx = (frame) ? frame->GetConcreteFrameIndex() : 0; - RegisterContextSP reg_ctx_sp; - ArchSpec arch = HostInfo::GetArchitecture(); - switch (arch.GetMachine()) - { - case llvm::Triple::x86: +lldb::RegisterContextSP ThreadWinMiniDump::CreateRegisterContextForFrame( + lldb_private::StackFrame *frame) { + const uint32_t concrete_frame_idx = + (frame) ? frame->GetConcreteFrameIndex() : 0; + RegisterContextSP reg_ctx_sp; + ArchSpec arch = HostInfo::GetArchitecture(); + switch (arch.GetMachine()) { + case llvm::Triple::x86: #if defined(_WIN64) - // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 +// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 #else - reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x86(*this, concrete_frame_idx, m_data->m_context)); + reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x86( + *this, concrete_frame_idx, m_data->m_context)); #endif - break; - case llvm::Triple::x86_64: + break; + case llvm::Triple::x86_64: #if defined(_WIN64) - reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x64(*this, concrete_frame_idx, m_data->m_context)); + reg_ctx_sp.reset(new RegisterContextWindowsMiniDump_x64( + *this, concrete_frame_idx, m_data->m_context)); #else - // LLDB is 32-bit, but the target process is 64-bit. We probably can't debug this. +// LLDB is 32-bit, but the target process is 64-bit. We probably can't debug +// this. #endif - default: - break; - } - return reg_ctx_sp; + default: + break; + } + return reg_ctx_sp; } -void -ThreadWinMiniDump::ClearStackFrames() -{ -} +void ThreadWinMiniDump::ClearStackFrames() {} -void -ThreadWinMiniDump::SetContext(const void *context) -{ - if (m_data) - { - m_data->m_context = static_cast<const CONTEXT *>(context); - } +void ThreadWinMiniDump::SetContext(const void *context) { + if (m_data) { + m_data->m_context = static_cast<const CONTEXT *>(context); + } } -bool -ThreadWinMiniDump::CalculateStopInfo() -{ - return false; -} +bool ThreadWinMiniDump::CalculateStopInfo() { return false; } diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h index c7892542210..bee5a6ab5f4 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/ThreadWinMiniDump.h @@ -15,35 +15,29 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Target/Thread.h" -class ThreadWinMiniDump : public lldb_private::Thread -{ +class ThreadWinMiniDump : public lldb_private::Thread { public: - ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid); + ThreadWinMiniDump(lldb_private::Process &process, lldb::tid_t tid); - virtual - ~ThreadWinMiniDump(); + virtual ~ThreadWinMiniDump(); - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - lldb::RegisterContextSP - GetRegisterContext() override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - void - ClearStackFrames() override; + void ClearStackFrames() override; - void - SetContext(const void *context); + void SetContext(const void *context); protected: - lldb::RegisterContextSP m_reg_context_sp; - class Data; - std::unique_ptr<Data> m_data; // for WinAPI-specific data + lldb::RegisterContextSP m_reg_context_sp; + class Data; + std::unique_ptr<Data> m_data; // for WinAPI-specific data - bool CalculateStopInfo() override; + bool CalculateStopInfo() override; }; #endif diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp index 41d9195f1ee..7f523fd0eba 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.cpp @@ -7,41 +7,36 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" #include "RegisterContextWindowsMiniDump_x64.h" using namespace lldb; -namespace lldb_private -{ - -RegisterContextWindowsMiniDump_x64::RegisterContextWindowsMiniDump_x64(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) - : RegisterContextWindows_x64(thread, concrete_frame_idx) -{ - if (context) - { - m_context = *context; - m_context_stale = false; - } -} +namespace lldb_private { -RegisterContextWindowsMiniDump_x64::~RegisterContextWindowsMiniDump_x64() -{ +RegisterContextWindowsMiniDump_x64::RegisterContextWindowsMiniDump_x64( + Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) + : RegisterContextWindows_x64(thread, concrete_frame_idx) { + if (context) { + m_context = *context; + m_context_stale = false; + } } -bool -RegisterContextWindowsMiniDump_x64::WriteRegister(const RegisterInfo * /* reg_info */, const RegisterValue & /* reg_value */) -{ - return false; +RegisterContextWindowsMiniDump_x64::~RegisterContextWindowsMiniDump_x64() {} + +bool RegisterContextWindowsMiniDump_x64::WriteRegister( + const RegisterInfo * /* reg_info */, + const RegisterValue & /* reg_value */) { + return false; } -bool -RegisterContextWindowsMiniDump_x64::CacheAllRegisterValues() -{ - // Since this is post-mortem debugging, we either have the context or we don't. - return !m_context_stale; +bool RegisterContextWindowsMiniDump_x64::CacheAllRegisterValues() { + // Since this is post-mortem debugging, we either have the context or we + // don't. + return !m_context_stale; } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h index 86d58046113..b4b29f7a679 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x64/RegisterContextWindowsMiniDump_x64.h @@ -10,27 +10,27 @@ #ifndef liblldb_RegisterContextWindowsMiniDump_x64_H_ #define liblldb_RegisterContextWindowsMiniDump_x64_H_ -#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsMiniDump_x64 : public RegisterContextWindows_x64 -{ - public: - RegisterContextWindowsMiniDump_x64(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context); +class RegisterContextWindowsMiniDump_x64 : public RegisterContextWindows_x64 { +public: + RegisterContextWindowsMiniDump_x64(Thread &thread, + uint32_t concrete_frame_idx, + const CONTEXT *context); - virtual ~RegisterContextWindowsMiniDump_x64(); + virtual ~RegisterContextWindowsMiniDump_x64(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - protected: - bool CacheAllRegisterValues() override; +protected: + bool CacheAllRegisterValues() override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsMiniDump_x64_H_ diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp index 2c8a069c537..c34a1335b36 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.cpp @@ -7,41 +7,36 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private-types.h" #include "lldb/Host/windows/windows.h" +#include "lldb/lldb-private-types.h" #include "RegisterContextWindowsMiniDump_x86.h" using namespace lldb; -namespace lldb_private -{ - -RegisterContextWindowsMiniDump_x86::RegisterContextWindowsMiniDump_x86(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) - : RegisterContextWindows_x86(thread, concrete_frame_idx) -{ - if (context) - { - m_context = *context; - m_context_stale = false; - } -} +namespace lldb_private { -RegisterContextWindowsMiniDump_x86::~RegisterContextWindowsMiniDump_x86() -{ +RegisterContextWindowsMiniDump_x86::RegisterContextWindowsMiniDump_x86( + Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context) + : RegisterContextWindows_x86(thread, concrete_frame_idx) { + if (context) { + m_context = *context; + m_context_stale = false; + } } -bool -RegisterContextWindowsMiniDump_x86::WriteRegister(const RegisterInfo * /* reg_info */, const RegisterValue & /* reg_value */) -{ - return false; +RegisterContextWindowsMiniDump_x86::~RegisterContextWindowsMiniDump_x86() {} + +bool RegisterContextWindowsMiniDump_x86::WriteRegister( + const RegisterInfo * /* reg_info */, + const RegisterValue & /* reg_value */) { + return false; } -bool -RegisterContextWindowsMiniDump_x86::CacheAllRegisterValues() -{ - // Since this is post-mortem debugging, we either have the context or we don't. - return !m_context_stale; +bool RegisterContextWindowsMiniDump_x86::CacheAllRegisterValues() { + // Since this is post-mortem debugging, we either have the context or we + // don't. + return !m_context_stale; } -} // namespace lldb_private +} // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h index d36e0cfd9e7..2754dcfb03a 100644 --- a/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h +++ b/lldb/source/Plugins/Process/Windows/MiniDump/x86/RegisterContextWindowsMiniDump_x86.h @@ -1,4 +1,5 @@ -//===-- RegisterContextWindowsMiniDump_x86.h ------------------------*- C++ -*-===// +//===-- RegisterContextWindowsMiniDump_x86.h ------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,27 +11,27 @@ #ifndef liblldb_RegisterContextWindowsMiniDump_x86_H_ #define liblldb_RegisterContextWindowsMiniDump_x86_H_ -#include "lldb/lldb-forward.h" #include "Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h" +#include "lldb/lldb-forward.h" -namespace lldb_private -{ +namespace lldb_private { class Thread; -class RegisterContextWindowsMiniDump_x86 : public RegisterContextWindows_x86 -{ - public: - RegisterContextWindowsMiniDump_x86(Thread &thread, uint32_t concrete_frame_idx, const CONTEXT *context); +class RegisterContextWindowsMiniDump_x86 : public RegisterContextWindows_x86 { +public: + RegisterContextWindowsMiniDump_x86(Thread &thread, + uint32_t concrete_frame_idx, + const CONTEXT *context); - virtual ~RegisterContextWindowsMiniDump_x86(); + virtual ~RegisterContextWindowsMiniDump_x86(); - bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; - protected: - bool CacheAllRegisterValues() override; +protected: + bool CacheAllRegisterValues() override; }; - } #endif // #ifndef liblldb_RegisterContextWindowsMiniDump_x86_H_ diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index e938f91eeda..aa985484c18 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -28,8 +28,8 @@ #include "llvm/Support/ELF.h" -#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" // Project includes #include "ProcessElfCore.h" @@ -37,485 +37,418 @@ using namespace lldb_private; -ConstString -ProcessElfCore::GetPluginNameStatic() -{ - static ConstString g_name("elf-core"); - return g_name; +ConstString ProcessElfCore::GetPluginNameStatic() { + static ConstString g_name("elf-core"); + return g_name; } -const char * -ProcessElfCore::GetPluginDescriptionStatic() -{ - return "ELF core dump plug-in."; +const char *ProcessElfCore::GetPluginDescriptionStatic() { + return "ELF core dump plug-in."; } -void -ProcessElfCore::Terminate() -{ - PluginManager::UnregisterPlugin (ProcessElfCore::CreateInstance); +void ProcessElfCore::Terminate() { + PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance); } - -lldb::ProcessSP -ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file) -{ - lldb::ProcessSP process_sp; - if (crash_file) - { - // Read enough data for a ELF32 header or ELF64 header - const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); - - lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size)); - if (data_sp && data_sp->GetByteSize() == header_size && - elf::ELFHeader::MagicBytesMatch (data_sp->GetBytes())) - { - elf::ELFHeader elf_header; - DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); - lldb::offset_t data_offset = 0; - if (elf_header.Parse(data, &data_offset)) - { - if (elf_header.e_type == llvm::ELF::ET_CORE) - process_sp.reset(new ProcessElfCore (target_sp, listener_sp, *crash_file)); - } - } +lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *crash_file) { + lldb::ProcessSP process_sp; + if (crash_file) { + // Read enough data for a ELF32 header or ELF64 header + const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); + + lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size)); + if (data_sp && data_sp->GetByteSize() == header_size && + elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) { + elf::ELFHeader elf_header; + DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); + lldb::offset_t data_offset = 0; + if (elf_header.Parse(data, &data_offset)) { + if (elf_header.e_type == llvm::ELF::ET_CORE) + process_sp.reset( + new ProcessElfCore(target_sp, listener_sp, *crash_file)); + } } - return process_sp; + } + return process_sp; } -bool -ProcessElfCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - if (!m_core_module_sp && m_core_file.Exists()) - { - ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture()); - Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp, - NULL, NULL, NULL)); - if (m_core_module_sp) - { - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) - return true; - } +bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + // For now we are just making sure the file exists for a given module + if (!m_core_module_sp && m_core_file.Exists()) { + ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture()); + Error error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, + NULL, NULL, NULL)); + if (m_core_module_sp) { + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) + return true; } - return false; + } + return false; } //---------------------------------------------------------------------- // ProcessElfCore constructor //---------------------------------------------------------------------- -ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const FileSpec &core_file) : - Process (target_sp, listener_sp), - m_core_module_sp (), - m_core_file (core_file), - m_dyld_plugin_name (), - m_os(llvm::Triple::UnknownOS), - m_thread_data_valid(false), - m_thread_data(), - m_core_aranges () -{ -} +ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec &core_file) + : Process(target_sp, listener_sp), m_core_module_sp(), + m_core_file(core_file), m_dyld_plugin_name(), + m_os(llvm::Triple::UnknownOS), m_thread_data_valid(false), + m_thread_data(), m_core_aranges() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ProcessElfCore::~ProcessElfCore() -{ - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); +ProcessElfCore::~ProcessElfCore() { + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); } //---------------------------------------------------------------------- // PluginInterface //---------------------------------------------------------------------- -ConstString -ProcessElfCore::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessElfCore::GetPluginVersion() -{ - return 1; -} - -lldb::addr_t -ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header) -{ - const lldb::addr_t addr = header->p_vaddr; - FileRange file_range (header->p_offset, header->p_filesz); - VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range); - - VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); - if (last_entry && - last_entry->GetRangeEnd() == range_entry.GetRangeBase() && - last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && - last_entry->GetByteSize() == last_entry->data.GetByteSize()) - { - last_entry->SetRangeEnd (range_entry.GetRangeEnd()); - last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); - } - else - { - m_core_aranges.Append(range_entry); - } - - // Keep a separate map of permissions that that isn't coalesced so all ranges - // are maintained. - const uint32_t permissions = ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0) | - ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0) | - ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0); - - m_core_range_infos.Append(VMRangeToPermissions::Entry(addr, header->p_memsz, permissions)); - - return addr; +ConstString ProcessElfCore::GetPluginName() { return GetPluginNameStatic(); } + +uint32_t ProcessElfCore::GetPluginVersion() { return 1; } + +lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( + const elf::ELFProgramHeader *header) { + const lldb::addr_t addr = header->p_vaddr; + FileRange file_range(header->p_offset, header->p_filesz); + VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range); + + VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); + if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && + last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && + last_entry->GetByteSize() == last_entry->data.GetByteSize()) { + last_entry->SetRangeEnd(range_entry.GetRangeEnd()); + last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); + } else { + m_core_aranges.Append(range_entry); + } + + // Keep a separate map of permissions that that isn't coalesced so all ranges + // are maintained. + const uint32_t permissions = + ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0) | + ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0) | + ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0); + + m_core_range_infos.Append( + VMRangeToPermissions::Entry(addr, header->p_memsz, permissions)); + + return addr; } //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- -Error -ProcessElfCore::DoLoadCore () -{ - Error error; - if (!m_core_module_sp) - { - error.SetErrorString ("invalid core module"); - return error; - } +Error ProcessElfCore::DoLoadCore() { + Error error; + if (!m_core_module_sp) { + error.SetErrorString("invalid core module"); + return error; + } - ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); - if (core == NULL) - { - error.SetErrorString ("invalid core object file"); - return error; - } + ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); + if (core == NULL) { + error.SetErrorString("invalid core object file"); + return error; + } - const uint32_t num_segments = core->GetProgramHeaderCount(); - if (num_segments == 0) - { - error.SetErrorString ("core file has no segments"); - return error; - } + const uint32_t num_segments = core->GetProgramHeaderCount(); + if (num_segments == 0) { + error.SetErrorString("core file has no segments"); + return error; + } - SetCanJIT(false); + SetCanJIT(false); - m_thread_data_valid = true; + m_thread_data_valid = true; - bool ranges_are_sorted = true; - lldb::addr_t vm_addr = 0; - /// Walk through segments and Thread and Address Map information. - /// PT_NOTE - Contains Thread and Register information - /// PT_LOAD - Contains a contiguous range of Process Address Space - for(uint32_t i = 1; i <= num_segments; i++) - { - const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); - assert(header != NULL); + bool ranges_are_sorted = true; + lldb::addr_t vm_addr = 0; + /// Walk through segments and Thread and Address Map information. + /// PT_NOTE - Contains Thread and Register information + /// PT_LOAD - Contains a contiguous range of Process Address Space + for (uint32_t i = 1; i <= num_segments; i++) { + const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); + assert(header != NULL); - DataExtractor data = core->GetSegmentDataByIndex(i); + DataExtractor data = core->GetSegmentDataByIndex(i); - // Parse thread contexts and auxv structure - if (header->p_type == llvm::ELF::PT_NOTE) - { - error = ParseThreadContextsFromNoteSegment(header, data); - if (error.Fail()) - return error; - } - // PT_LOAD segments contains address map - if (header->p_type == llvm::ELF::PT_LOAD) - { - lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); - if (vm_addr > last_addr) - ranges_are_sorted = false; - vm_addr = last_addr; - } + // Parse thread contexts and auxv structure + if (header->p_type == llvm::ELF::PT_NOTE) { + error = ParseThreadContextsFromNoteSegment(header, data); + if (error.Fail()) + return error; } - - if (!ranges_are_sorted) - { - m_core_aranges.Sort(); - m_core_range_infos.Sort(); + // PT_LOAD segments contains address map + if (header->p_type == llvm::ELF::PT_LOAD) { + lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); + if (vm_addr > last_addr) + ranges_are_sorted = false; + vm_addr = last_addr; } - - // Even if the architecture is set in the target, we need to override - // it to match the core file which is always single arch. - ArchSpec arch (m_core_module_sp->GetArchitecture()); - if (arch.IsValid()) - GetTarget().SetArchitecture(arch); - - SetUnixSignals(UnixSignals::Create(GetArchitecture())); - - // Core files are useless without the main executable. See if we can locate the main - // executable using data we found in the core file notes. - lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); - if (!exe_module_sp) - { - // The first entry in the NT_FILE might be our executable - if (!m_nt_file_entries.empty()) - { - ModuleSpec exe_module_spec; - exe_module_spec.GetArchitecture() = arch; - exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false); - if (exe_module_spec.GetFileSpec()) - { - exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); - if (exe_module_sp) - GetTarget().SetExecutableModule(exe_module_sp, false); - } - } + } + + if (!ranges_are_sorted) { + m_core_aranges.Sort(); + m_core_range_infos.Sort(); + } + + // Even if the architecture is set in the target, we need to override + // it to match the core file which is always single arch. + ArchSpec arch(m_core_module_sp->GetArchitecture()); + if (arch.IsValid()) + GetTarget().SetArchitecture(arch); + + SetUnixSignals(UnixSignals::Create(GetArchitecture())); + + // Core files are useless without the main executable. See if we can locate + // the main + // executable using data we found in the core file notes. + lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); + if (!exe_module_sp) { + // The first entry in the NT_FILE might be our executable + if (!m_nt_file_entries.empty()) { + ModuleSpec exe_module_spec; + exe_module_spec.GetArchitecture() = arch; + exe_module_spec.GetFileSpec().SetFile( + m_nt_file_entries[0].path.GetCString(), false); + if (exe_module_spec.GetFileSpec()) { + exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); + if (exe_module_sp) + GetTarget().SetExecutableModule(exe_module_sp, false); + } } - return error; + } + return error; } -lldb_private::DynamicLoader * -ProcessElfCore::GetDynamicLoader () -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString())); - return m_dyld_ap.get(); +lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString())); + return m_dyld_ap.get(); } -bool -ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - const uint32_t num_threads = GetNumThreadContexts (); - if (!m_thread_data_valid) - return false; - - for (lldb::tid_t tid = 0; tid < num_threads; ++tid) - { - const ThreadData &td = m_thread_data[tid]; - lldb::ThreadSP thread_sp(new ThreadElfCore (*this, td)); - new_thread_list.AddThread (thread_sp); - } - return new_thread_list.GetSize(false) > 0; -} +bool ProcessElfCore::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + const uint32_t num_threads = GetNumThreadContexts(); + if (!m_thread_data_valid) + return false; -void -ProcessElfCore::RefreshStateAfterStop () -{ + for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { + const ThreadData &td = m_thread_data[tid]; + lldb::ThreadSP thread_sp(new ThreadElfCore(*this, td)); + new_thread_list.AddThread(thread_sp); + } + return new_thread_list.GetSize(false) > 0; } -Error -ProcessElfCore::DoDestroy () -{ - return Error(); -} +void ProcessElfCore::RefreshStateAfterStop() {} + +Error ProcessElfCore::DoDestroy() { return Error(); } //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ -bool -ProcessElfCore::IsAlive () -{ - return true; -} +bool ProcessElfCore::IsAlive() { return true; } //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ -size_t -ProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - // Don't allow the caching that lldb_private::Process::ReadMemory does - // since in core files we have it all cached our our core file anyway. - return DoReadMemory (addr, buf, size, error); +size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + Error &error) { + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since in core files we have it all cached our our core file anyway. + return DoReadMemory(addr, buf, size, error); } -Error -ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) -{ - region_info.Clear(); - const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); - if (permission_entry) - { - if (permission_entry->Contains(load_addr)) - { - region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); - const Flags permissions(permission_entry->data); - region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eYes); - } - else if (load_addr < permission_entry->GetRangeBase()) - { - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - } - return Error(); +Error ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion_info) { + region_info.Clear(); + const VMRangeToPermissions::Entry *permission_entry = + m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); + if (permission_entry) { + if (permission_entry->Contains(load_addr)) { + region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); + const Flags permissions(permission_entry->data); + region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eYes); + } else if (load_addr < permission_entry->GetRangeBase()) { + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } - - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); return Error(); + } + + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + return Error(); } -size_t -ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - - if (core_objfile == NULL) - return 0; - - // Get the address range - const VMRangeToFileOffset::Entry *address_range = m_core_aranges.FindEntryThatContains (addr); - if (address_range == NULL || address_range->GetRangeEnd() < addr) - { - error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr); - return 0; - } - - // Convert the address into core file offset - const lldb::addr_t offset = addr - address_range->GetRangeBase(); - const lldb::addr_t file_start = address_range->data.GetRangeBase(); - const lldb::addr_t file_end = address_range->data.GetRangeEnd(); - size_t bytes_to_read = size; // Number of bytes to read from the core file - size_t bytes_copied = 0; // Number of bytes actually read from the core file - size_t zero_fill_size = 0; // Padding - lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address - - // Figure out how many on-disk bytes remain in this segment - // starting at the given offset - if (file_end > file_start + offset) - bytes_left = file_end - (file_start + offset); - - // Figure out how many bytes we need to zero-fill if we are - // reading more bytes than available in the on-disk segment - if (bytes_to_read > bytes_left) - { - zero_fill_size = bytes_to_read - bytes_left; - bytes_to_read = bytes_left; - } - - // If there is data available on the core file read it - if (bytes_to_read) - bytes_copied = core_objfile->CopyData(offset + file_start, bytes_to_read, buf); - - assert(zero_fill_size <= size); - // Pad remaining bytes - if (zero_fill_size) - memset(((char *)buf) + bytes_copied, 0, zero_fill_size); - - return bytes_copied + zero_fill_size; +size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Error &error) { + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + + if (core_objfile == NULL) + return 0; + + // Get the address range + const VMRangeToFileOffset::Entry *address_range = + m_core_aranges.FindEntryThatContains(addr); + if (address_range == NULL || address_range->GetRangeEnd() < addr) { + error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, + addr); + return 0; + } + + // Convert the address into core file offset + const lldb::addr_t offset = addr - address_range->GetRangeBase(); + const lldb::addr_t file_start = address_range->data.GetRangeBase(); + const lldb::addr_t file_end = address_range->data.GetRangeEnd(); + size_t bytes_to_read = size; // Number of bytes to read from the core file + size_t bytes_copied = 0; // Number of bytes actually read from the core file + size_t zero_fill_size = 0; // Padding + lldb::addr_t bytes_left = + 0; // Number of bytes available in the core file from the given address + + // Figure out how many on-disk bytes remain in this segment + // starting at the given offset + if (file_end > file_start + offset) + bytes_left = file_end - (file_start + offset); + + // Figure out how many bytes we need to zero-fill if we are + // reading more bytes than available in the on-disk segment + if (bytes_to_read > bytes_left) { + zero_fill_size = bytes_to_read - bytes_left; + bytes_to_read = bytes_left; + } + + // If there is data available on the core file read it + if (bytes_to_read) + bytes_copied = + core_objfile->CopyData(offset + file_start, bytes_to_read, buf); + + assert(zero_fill_size <= size); + // Pad remaining bytes + if (zero_fill_size) + memset(((char *)buf) + bytes_copied, 0, zero_fill_size); + + return bytes_copied + zero_fill_size; } -void -ProcessElfCore::Clear() -{ - m_thread_list.Clear(); - m_os = llvm::Triple::UnknownOS; +void ProcessElfCore::Clear() { + m_thread_list.Clear(); + m_os = llvm::Triple::UnknownOS; - SetUnixSignals(std::make_shared<UnixSignals>()); + SetUnixSignals(std::make_shared<UnixSignals>()); } -void -ProcessElfCore::Initialize() -{ - static std::once_flag g_once_flag; +void ProcessElfCore::Initialize() { + static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin (GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); - }); + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } -lldb::addr_t -ProcessElfCore::GetImageInfoAddress() -{ - ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(&GetTarget()); +lldb::addr_t ProcessElfCore::GetImageInfoAddress() { + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(&GetTarget()); - if (addr.IsValid()) - return addr.GetLoadAddress(&GetTarget()); - return LLDB_INVALID_ADDRESS; + if (addr.IsValid()) + return addr.GetLoadAddress(&GetTarget()); + return LLDB_INVALID_ADDRESS; } /// Core files PT_NOTE segment descriptor types enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_TASKSTRUCT, - NT_PLATFORM, - NT_AUXV, - NT_FILE = 0x46494c45 + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_TASKSTRUCT, + NT_PLATFORM, + NT_AUXV, + NT_FILE = 0x46494c45 }; namespace FREEBSD { enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16, - NT_PPC_VMX = 0x100 + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_THRMISC = 7, + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 }; - } // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. -static void -ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, - ArchSpec &arch) -{ - lldb::offset_t offset = 0; - bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || - arch.GetMachine() == llvm::Triple::mips64 || - arch.GetMachine() == llvm::Triple::ppc64 || - arch.GetMachine() == llvm::Triple::x86_64); - int pr_version = data.GetU32(&offset); - - Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - { - if (pr_version > 1) - log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); - } - - // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate - if (lp64) - offset += 32; - else - offset += 16; - - thread_data.signo = data.GetU32(&offset); // pr_cursig - thread_data.tid = data.GetU32(&offset); // pr_pid - if (lp64) - offset += 4; - - size_t len = data.GetByteSize() - offset; - thread_data.gpregset = DataExtractor(data, offset, len); +static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, + ArchSpec &arch) { + lldb::offset_t offset = 0; + bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || + arch.GetMachine() == llvm::Triple::mips64 || + arch.GetMachine() == llvm::Triple::ppc64 || + arch.GetMachine() == llvm::Triple::x86_64); + int pr_version = data.GetU32(&offset); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) { + if (pr_version > 1) + log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); + } + + // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate + if (lp64) + offset += 32; + else + offset += 16; + + thread_data.signo = data.GetU32(&offset); // pr_cursig + thread_data.tid = data.GetU32(&offset); // pr_pid + if (lp64) + offset += 4; + + size_t len = data.GetByteSize() - offset; + thread_data.gpregset = DataExtractor(data, offset, len); } -static void -ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) -{ - lldb::offset_t offset = 0; - thread_data.name = data.GetCStr(&offset, 20); +static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) { + lldb::offset_t offset = 0; + thread_data.name = data.GetCStr(&offset, 20); } /// Parse Thread context from PT_NOTE segment and store it in the thread list @@ -528,190 +461,173 @@ ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) /// b) NT_PRPSINFO - Process info(pid..) /// c) NT_FPREGSET - Floating point registers /// 4) The NOTE entries can be in any order -/// 5) If a core file contains multiple thread contexts then there is two data forms -/// a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE) +/// 5) If a core file contains multiple thread contexts then there is two data +/// forms +/// a) Each thread context(2 or more NOTE entries) contained in its own +/// segment (PT_NOTE) /// b) All thread context is stored in a single segment(PT_NOTE). -/// This case is little tricker since while parsing we have to find where the +/// This case is little tricker since while parsing we have to find where +/// the /// new thread starts. The current implementation marks beginning of /// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry. /// For case (b) there may be either one NT_PRPSINFO per thread, or a single /// one that applies to all threads (depending on the platform type). -Error -ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header, - DataExtractor segment_data) -{ - assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); - - lldb::offset_t offset = 0; - std::unique_ptr<ThreadData> thread_data(new ThreadData); - bool have_prstatus = false; - bool have_prpsinfo = false; - - ArchSpec arch = GetArchitecture(); - ELFLinuxPrPsInfo prpsinfo; - ELFLinuxPrStatus prstatus; - size_t header_size; - size_t len; - Error error; - - // Loop through the NOTE entires in the segment - while (offset < segment_header->p_filesz) - { - ELFNote note = ELFNote(); - note.Parse(segment_data, &offset); - - // Beginning of new thread - if ((note.n_type == NT_PRSTATUS && have_prstatus) || - (note.n_type == NT_PRPSINFO && have_prpsinfo)) - { - assert(thread_data->gpregset.GetByteSize() > 0); - // Add the new thread to thread list - m_thread_data.push_back(*thread_data); - *thread_data = ThreadData(); - have_prstatus = false; - have_prpsinfo = false; - } +Error ProcessElfCore::ParseThreadContextsFromNoteSegment( + const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { + assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); + + lldb::offset_t offset = 0; + std::unique_ptr<ThreadData> thread_data(new ThreadData); + bool have_prstatus = false; + bool have_prpsinfo = false; + + ArchSpec arch = GetArchitecture(); + ELFLinuxPrPsInfo prpsinfo; + ELFLinuxPrStatus prstatus; + size_t header_size; + size_t len; + Error error; + + // Loop through the NOTE entires in the segment + while (offset < segment_header->p_filesz) { + ELFNote note = ELFNote(); + note.Parse(segment_data, &offset); + + // Beginning of new thread + if ((note.n_type == NT_PRSTATUS && have_prstatus) || + (note.n_type == NT_PRPSINFO && have_prpsinfo)) { + assert(thread_data->gpregset.GetByteSize() > 0); + // Add the new thread to thread list + m_thread_data.push_back(*thread_data); + *thread_data = ThreadData(); + have_prstatus = false; + have_prpsinfo = false; + } - size_t note_start, note_size; - note_start = offset; - note_size = llvm::alignTo(note.n_descsz, 4); - - // Store the NOTE information in the current thread - DataExtractor note_data (segment_data, note_start, note_size); - note_data.SetAddressByteSize(m_core_module_sp->GetArchitecture().GetAddressByteSize()); - if (note.n_name == "FreeBSD") - { - m_os = llvm::Triple::FreeBSD; - switch (note.n_type) - { - case FREEBSD::NT_PRSTATUS: - have_prstatus = true; - ParseFreeBSDPrStatus(*thread_data, note_data, arch); - break; - case FREEBSD::NT_FPREGSET: - thread_data->fpregset = note_data; - break; - case FREEBSD::NT_PRPSINFO: - have_prpsinfo = true; - break; - case FREEBSD::NT_THRMISC: - ParseFreeBSDThrMisc(*thread_data, note_data); - break; - case FREEBSD::NT_PROCSTAT_AUXV: - // FIXME: FreeBSD sticks an int at the beginning of the note - m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); - break; - case FREEBSD::NT_PPC_VMX: - thread_data->vregset = note_data; - break; - default: - break; - } + size_t note_start, note_size; + note_start = offset; + note_size = llvm::alignTo(note.n_descsz, 4); + + // Store the NOTE information in the current thread + DataExtractor note_data(segment_data, note_start, note_size); + note_data.SetAddressByteSize( + m_core_module_sp->GetArchitecture().GetAddressByteSize()); + if (note.n_name == "FreeBSD") { + m_os = llvm::Triple::FreeBSD; + switch (note.n_type) { + case FREEBSD::NT_PRSTATUS: + have_prstatus = true; + ParseFreeBSDPrStatus(*thread_data, note_data, arch); + break; + case FREEBSD::NT_FPREGSET: + thread_data->fpregset = note_data; + break; + case FREEBSD::NT_PRPSINFO: + have_prpsinfo = true; + break; + case FREEBSD::NT_THRMISC: + ParseFreeBSDThrMisc(*thread_data, note_data); + break; + case FREEBSD::NT_PROCSTAT_AUXV: + // FIXME: FreeBSD sticks an int at the beginning of the note + m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); + break; + case FREEBSD::NT_PPC_VMX: + thread_data->vregset = note_data; + break; + default: + break; + } + } else if (note.n_name == "CORE") { + switch (note.n_type) { + case NT_PRSTATUS: + have_prstatus = true; + error = prstatus.Parse(note_data, arch); + if (error.Fail()) + return error; + thread_data->signo = prstatus.pr_cursig; + thread_data->tid = prstatus.pr_pid; + header_size = ELFLinuxPrStatus::GetSize(arch); + len = note_data.GetByteSize() - header_size; + thread_data->gpregset = DataExtractor(note_data, header_size, len); + break; + case NT_FPREGSET: + thread_data->fpregset = note_data; + break; + case NT_PRPSINFO: + have_prpsinfo = true; + error = prpsinfo.Parse(note_data, arch); + if (error.Fail()) + return error; + thread_data->name = prpsinfo.pr_fname; + SetID(prpsinfo.pr_pid); + break; + case NT_AUXV: + m_auxv = DataExtractor(note_data); + break; + case NT_FILE: { + m_nt_file_entries.clear(); + lldb::offset_t offset = 0; + const uint64_t count = note_data.GetAddress(&offset); + note_data.GetAddress(&offset); // Skip page size + for (uint64_t i = 0; i < count; ++i) { + NT_FILE_Entry entry; + entry.start = note_data.GetAddress(&offset); + entry.end = note_data.GetAddress(&offset); + entry.file_ofs = note_data.GetAddress(&offset); + m_nt_file_entries.push_back(entry); } - else if (note.n_name == "CORE") - { - switch (note.n_type) - { - case NT_PRSTATUS: - have_prstatus = true; - error = prstatus.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->signo = prstatus.pr_cursig; - thread_data->tid = prstatus.pr_pid; - header_size = ELFLinuxPrStatus::GetSize(arch); - len = note_data.GetByteSize() - header_size; - thread_data->gpregset = DataExtractor(note_data, header_size, len); - break; - case NT_FPREGSET: - thread_data->fpregset = note_data; - break; - case NT_PRPSINFO: - have_prpsinfo = true; - error = prpsinfo.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->name = prpsinfo.pr_fname; - SetID(prpsinfo.pr_pid); - break; - case NT_AUXV: - m_auxv = DataExtractor(note_data); - break; - case NT_FILE: - { - m_nt_file_entries.clear(); - lldb::offset_t offset = 0; - const uint64_t count = note_data.GetAddress(&offset); - note_data.GetAddress(&offset); // Skip page size - for (uint64_t i = 0; i<count; ++i) - { - NT_FILE_Entry entry; - entry.start = note_data.GetAddress(&offset); - entry.end = note_data.GetAddress(&offset); - entry.file_ofs = note_data.GetAddress(&offset); - m_nt_file_entries.push_back(entry); - } - for (uint64_t i = 0; i<count; ++i) - { - const char *path = note_data.GetCStr(&offset); - if (path && path[0]) - m_nt_file_entries[i].path.SetCString(path); - } - } - break; - default: - break; - } + for (uint64_t i = 0; i < count; ++i) { + const char *path = note_data.GetCStr(&offset); + if (path && path[0]) + m_nt_file_entries[i].path.SetCString(path); } - - offset += note_size; - } - // Add last entry in the note section - if (thread_data && thread_data->gpregset.GetByteSize() > 0) - { - m_thread_data.push_back(*thread_data); + } break; + default: + break; + } } - return error; + offset += note_size; + } + // Add last entry in the note section + if (thread_data && thread_data->gpregset.GetByteSize() > 0) { + m_thread_data.push_back(*thread_data); + } + + return error; } -uint32_t -ProcessElfCore::GetNumThreadContexts () -{ - if (!m_thread_data_valid) - DoLoadCore(); - return m_thread_data.size(); +uint32_t ProcessElfCore::GetNumThreadContexts() { + if (!m_thread_data_valid) + DoLoadCore(); + return m_thread_data.size(); } -ArchSpec -ProcessElfCore::GetArchitecture() -{ - ObjectFileELF *core_file = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); - ArchSpec arch; - core_file->GetArchitecture(arch); - return arch; +ArchSpec ProcessElfCore::GetArchitecture() { + ObjectFileELF *core_file = + (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); + ArchSpec arch; + core_file->GetArchitecture(arch); + return arch; } -const lldb::DataBufferSP -ProcessElfCore::GetAuxvData() -{ - const uint8_t *start = m_auxv.GetDataStart(); - size_t len = m_auxv.GetByteSize(); - lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); - return buffer; +const lldb::DataBufferSP ProcessElfCore::GetAuxvData() { + const uint8_t *start = m_auxv.GetDataStart(); + size_t len = m_auxv.GetByteSize(); + lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); + return buffer; } -bool -ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) -{ - info.Clear(); - info.SetProcessID(GetID()); - info.SetArchitecture(GetArchitecture()); - lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); - if (module_sp) - { - const bool add_exe_file_as_first_arg = false; - info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), add_exe_file_as_first_arg); - } - return true; +bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) { + info.Clear(); + info.SetProcessID(GetID()); + info.SetArchitecture(GetArchitecture()); + lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); + if (module_sp) { + const bool add_exe_file_as_first_arg = false; + info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), + add_exe_file_as_first_arg); + } + return true; } diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index e9005a9a167..a8dde47b307 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -32,151 +32,144 @@ struct ThreadData; -class ProcessElfCore : public lldb_private::Process -{ +class ProcessElfCore : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path); - static void - Initialize(); + static void Initialize(); - static void - Terminate(); + static void Terminate(); - static lldb_private::ConstString - GetPluginNameStatic(); + static lldb_private::ConstString GetPluginNameStatic(); - static const char * - GetPluginDescriptionStatic(); + static const char *GetPluginDescriptionStatic(); - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ProcessElfCore(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const lldb_private::FileSpec &core_file); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec &core_file); - ~ProcessElfCore() override; + ~ProcessElfCore() override; - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + //------------------------------------------------------------------ + // Check if a given Process + //------------------------------------------------------------------ + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - lldb_private::Error DoLoadCore() override; + //------------------------------------------------------------------ + // Creating a new process, or attaching to an existing one + //------------------------------------------------------------------ + lldb_private::Error DoLoadCore() override; - lldb_private::DynamicLoader *GetDynamicLoader() override; + lldb_private::DynamicLoader *GetDynamicLoader() override; - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; - uint32_t GetPluginVersion() override; + uint32_t GetPluginVersion() override; - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - lldb_private::Error DoDestroy() override; + //------------------------------------------------------------------ + // Process Control + //------------------------------------------------------------------ + lldb_private::Error DoDestroy() override; - void RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - bool IsAlive() override; + //------------------------------------------------------------------ + // Process Queries + //------------------------------------------------------------------ + bool IsAlive() override; - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + //------------------------------------------------------------------ + // Process Memory + //------------------------------------------------------------------ + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; - size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; - lldb_private::Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo ®ion_info) override; - lldb::addr_t GetImageInfoAddress() override; + lldb::addr_t GetImageInfoAddress() override; - lldb_private::ArchSpec - GetArchitecture(); + lldb_private::ArchSpec GetArchitecture(); - // Returns AUXV structure found in the core file - const lldb::DataBufferSP - GetAuxvData() override; + // Returns AUXV structure found in the core file + const lldb::DataBufferSP GetAuxvData() override; - bool - GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override; + bool GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override; protected: - void - Clear ( ); + void Clear(); - bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; private: - struct NT_FILE_Entry - { - lldb::addr_t start; - lldb::addr_t end; - lldb::addr_t file_ofs; - lldb_private::ConstString path; - }; - - //------------------------------------------------------------------ - // For ProcessElfCore only - //------------------------------------------------------------------ - typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; - typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> VMRangeToPermissions; - - lldb::ModuleSP m_core_module_sp; - lldb_private::FileSpec m_core_file; - std::string m_dyld_plugin_name; - DISALLOW_COPY_AND_ASSIGN (ProcessElfCore); - - llvm::Triple::OSType m_os; - - // True if m_thread_contexts contains valid entries - bool m_thread_data_valid; - - // Contain thread data read from NOTE segments - std::vector<ThreadData> m_thread_data; - - // AUXV structure found from the NOTE segment - lldb_private::DataExtractor m_auxv; - - // Address ranges found in the core - VMRangeToFileOffset m_core_aranges; - - // Permissions for all ranges - VMRangeToPermissions m_core_range_infos; - - // NT_FILE entries found from the NOTE segment - std::vector<NT_FILE_Entry> m_nt_file_entries; - - // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment - lldb_private::Error - ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header, - lldb_private::DataExtractor segment_data); - - // Returns number of thread contexts stored in the core file - uint32_t - GetNumThreadContexts(); - - // Parse a contiguous address range of the process from LOAD segment - lldb::addr_t - AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header); + struct NT_FILE_Entry { + lldb::addr_t start; + lldb::addr_t end; + lldb::addr_t file_ofs; + lldb_private::ConstString path; + }; + + //------------------------------------------------------------------ + // For ProcessElfCore only + //------------------------------------------------------------------ + typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; + typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> + VMRangeToFileOffset; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> + VMRangeToPermissions; + + lldb::ModuleSP m_core_module_sp; + lldb_private::FileSpec m_core_file; + std::string m_dyld_plugin_name; + DISALLOW_COPY_AND_ASSIGN(ProcessElfCore); + + llvm::Triple::OSType m_os; + + // True if m_thread_contexts contains valid entries + bool m_thread_data_valid; + + // Contain thread data read from NOTE segments + std::vector<ThreadData> m_thread_data; + + // AUXV structure found from the NOTE segment + lldb_private::DataExtractor m_auxv; + + // Address ranges found in the core + VMRangeToFileOffset m_core_aranges; + + // Permissions for all ranges + VMRangeToPermissions m_core_range_infos; + + // NT_FILE entries found from the NOTE segment + std::vector<NT_FILE_Entry> m_nt_file_entries; + + // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment + lldb_private::Error ParseThreadContextsFromNoteSegment( + const elf::ELFProgramHeader *segment_header, + lldb_private::DataExtractor segment_data); + + // Returns number of thread contexts stored in the core file + uint32_t GetNumThreadContexts(); + + // Parse a contiguous address range of the process from LOAD segment + lldb::addr_t + AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header); }; #endif // liblldb_ProcessElfCore_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp index 526e737cf76..d7b883089b5 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -14,80 +14,58 @@ using namespace lldb_private; -RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm(Thread &thread, - RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset) - : RegisterContextPOSIX_arm(thread, 0, register_info) -{ - m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); +RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset) + : RegisterContextPOSIX_arm(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); } -RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() -{ -} +RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() {} -bool -RegisterContextCorePOSIX_arm::ReadGPR() -{ - return true; -} +bool RegisterContextCorePOSIX_arm::ReadGPR() { return true; } -bool -RegisterContextCorePOSIX_arm::ReadFPR() -{ - return false; -} +bool RegisterContextCorePOSIX_arm::ReadFPR() { return false; } -bool -RegisterContextCorePOSIX_arm::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_arm::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_arm::WriteFPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_arm::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_arm::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value = v; - return true; - } - return false; +bool RegisterContextCorePOSIX_arm::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value = v; + return true; + } + return false; } -bool -RegisterContextCorePOSIX_arm::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_arm::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_arm::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_arm::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_arm::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_arm::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_arm::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_arm::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index 76deab705f9..a97987da6aa 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -18,50 +18,40 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" -class RegisterContextCorePOSIX_arm : - public RegisterContextPOSIX_arm -{ +class RegisterContextCorePOSIX_arm : public RegisterContextPOSIX_arm { public: - RegisterContextCorePOSIX_arm (lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + RegisterContextCorePOSIX_arm( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); - ~RegisterContextCorePOSIX_arm() override; + ~RegisterContextCorePOSIX_arm() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb_private::DataExtractor m_gpr; + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; }; #endif // liblldb_RegisterContextCorePOSIX_arm_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 58f53d0d050..65314441ffc 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -14,80 +14,58 @@ using namespace lldb_private; -RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(Thread &thread, - RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset) - : RegisterContextPOSIX_arm64(thread, 0, register_info) -{ - m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); +RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset) + : RegisterContextPOSIX_arm64(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); } -RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() -{ -} +RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {} -bool -RegisterContextCorePOSIX_arm64::ReadGPR() -{ - return true; -} +bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; } -bool -RegisterContextCorePOSIX_arm64::ReadFPR() -{ - return false; -} +bool RegisterContextCorePOSIX_arm64::ReadFPR() { return false; } -bool -RegisterContextCorePOSIX_arm64::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_arm64::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_arm64::WriteFPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_arm64::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value = v; - return true; - } - return false; +bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value = v; + return true; + } + return false; } -bool -RegisterContextCorePOSIX_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_arm64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_arm64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_arm64::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_arm64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_arm64::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_arm64::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index f3c7d7b1099..0c2345f2045 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -18,50 +18,40 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" -class RegisterContextCorePOSIX_arm64 : - public RegisterContextPOSIX_arm64 -{ +class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { public: - RegisterContextCorePOSIX_arm64 (lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + RegisterContextCorePOSIX_arm64( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); - ~RegisterContextCorePOSIX_arm64() override; + ~RegisterContextCorePOSIX_arm64() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb_private::DataExtractor m_gpr; + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; }; #endif // liblldb_RegisterContextCorePOSIX_arm64_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index 583b8296b72..41b70a8d146 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -14,80 +14,58 @@ using namespace lldb_private; -RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(Thread &thread, - RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset) - : RegisterContextPOSIX_mips64(thread, 0, register_info) -{ - m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); +RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset) + : RegisterContextPOSIX_mips64(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); } -RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() -{ -} +RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() {} -bool -RegisterContextCorePOSIX_mips64::ReadGPR() -{ - return true; -} +bool RegisterContextCorePOSIX_mips64::ReadGPR() { return true; } -bool -RegisterContextCorePOSIX_mips64::ReadFPR() -{ - return false; -} +bool RegisterContextCorePOSIX_mips64::ReadFPR() { return false; } -bool -RegisterContextCorePOSIX_mips64::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_mips64::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_mips64::WriteFPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_mips64::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value = v; - return true; - } - return false; +bool RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value = v; + return true; + } + return false; } -bool -RegisterContextCorePOSIX_mips64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_mips64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_mips64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_mips64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_mips64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_mips64::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_mips64::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index e84a2ed0805..f92301cc987 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -18,50 +18,40 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" -class RegisterContextCorePOSIX_mips64 : - public RegisterContextPOSIX_mips64 -{ +class RegisterContextCorePOSIX_mips64 : public RegisterContextPOSIX_mips64 { public: - RegisterContextCorePOSIX_mips64 (lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + RegisterContextCorePOSIX_mips64( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); - ~RegisterContextCorePOSIX_mips64() override; + ~RegisterContextCorePOSIX_mips64() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb_private::DataExtractor m_gpr; + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; }; #endif // liblldb_RegisterContextCorePOSIX_mips64_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 557da0294a8..729e8507846 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -1,4 +1,5 @@ -//===-- RegisterContextCorePOSIX_powerpc.cpp ---------------------*- C++ -*-===// +//===-- RegisterContextCorePOSIX_powerpc.cpp ---------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -15,120 +16,92 @@ using namespace lldb_private; -RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, - RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset, - const DataExtractor &vregset) - : RegisterContextPOSIX_powerpc(thread, 0, register_info) -{ - m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); - m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); - m_fpr.SetData(m_fpr_buffer); - m_fpr.SetByteOrder(fpregset.GetByteOrder()); - m_vec_buffer.reset(new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); - m_vec.SetData(m_vec_buffer); - m_vec.SetByteOrder(vregset.GetByteOrder()); +RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset, + const DataExtractor &vregset) + : RegisterContextPOSIX_powerpc(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + m_fpr_buffer.reset( + new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); + m_vec_buffer.reset( + new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); + m_vec.SetData(m_vec_buffer); + m_vec.SetByteOrder(vregset.GetByteOrder()); } -RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() -{ -} +RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() {} -bool -RegisterContextCorePOSIX_powerpc::ReadGPR() -{ - return true; -} +bool RegisterContextCorePOSIX_powerpc::ReadGPR() { return true; } -bool -RegisterContextCorePOSIX_powerpc::ReadFPR() -{ - return true; -} +bool RegisterContextCorePOSIX_powerpc::ReadFPR() { return true; } -bool -RegisterContextCorePOSIX_powerpc::ReadVMX() -{ - return true; -} +bool RegisterContextCorePOSIX_powerpc::ReadVMX() { return true; } -bool -RegisterContextCorePOSIX_powerpc::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_powerpc::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_powerpc::WriteFPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_powerpc::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_powerpc::WriteVMX() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_powerpc::WriteVMX() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - lldb::offset_t offset = reg_info->byte_offset; - if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { - uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value = v; - return true; - } - } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { - uint32_t v[4]; - offset = m_vec.CopyData(offset, reg_info->byte_size, &v); - if (offset == reg_info->byte_size) - { - value.SetBytes(v, reg_info->byte_size, m_vec.GetByteOrder()); - return true; - } - } else { - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - if (reg_info->byte_size < sizeof(v)) - value = (uint32_t)v; - else - value = v; - return true; - } +bool RegisterContextCorePOSIX_powerpc::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value = v; + return true; + } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset = m_vec.CopyData(offset, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) { + value.SetBytes(v, reg_info->byte_size, m_vec.GetByteOrder()); + return true; + } + } else { + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + if (reg_info->byte_size < sizeof(v)) + value = (uint32_t)v; + else + value = v; + return true; } - return false; + } + return false; } -bool -RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_powerpc::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index 05b68a17ac7..0b673c299d4 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -17,61 +17,49 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" #include "lldb/Core/DataExtractor.h" -class RegisterContextCorePOSIX_powerpc : - public RegisterContextPOSIX_powerpc -{ +class RegisterContextCorePOSIX_powerpc : public RegisterContextPOSIX_powerpc { public: - RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset, - const lldb_private::DataExtractor &vregset); + RegisterContextCorePOSIX_powerpc( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset, + const lldb_private::DataExtractor &vregset); - ~RegisterContextCorePOSIX_powerpc() override; + ~RegisterContextCorePOSIX_powerpc() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - ReadVMX() override; + bool ReadVMX() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; - bool - WriteVMX() override; + bool WriteVMX() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb::DataBufferSP m_fpr_buffer; - lldb::DataBufferSP m_vec_buffer; - lldb_private::DataExtractor m_gpr; - lldb_private::DataExtractor m_fpr; - lldb_private::DataExtractor m_vec; + lldb::DataBufferSP m_gpr_buffer; + lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vec_buffer; + lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vec; }; #endif // liblldb_RegisterContextCorePOSIX_powerpc_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index 2371c029d89..fe04a30d645 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -15,102 +15,79 @@ using namespace lldb_private; -RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x(Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset) - : RegisterContextPOSIX_s390x(thread, 0, register_info) -{ - m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); - - m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); - m_fpr.SetData(m_fpr_buffer); - m_fpr.SetByteOrder(fpregset.GetByteOrder()); +RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset) + : RegisterContextPOSIX_s390x(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + m_fpr_buffer.reset( + new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); } -RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() -{ -} +RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() {} -bool -RegisterContextCorePOSIX_s390x::ReadGPR() -{ - return true; -} +bool RegisterContextCorePOSIX_s390x::ReadGPR() { return true; } + +bool RegisterContextCorePOSIX_s390x::ReadFPR() { return true; } -bool -RegisterContextCorePOSIX_s390x::ReadFPR() -{ - return true; +bool RegisterContextCorePOSIX_s390x::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_s390x::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_s390x::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_s390x::WriteFPR() -{ - assert(0); +bool RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) return false; -} -bool -RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return false; - - if (IsGPR(reg)) - { - lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value.SetUInt(v, reg_info->byte_size); - return true; - } + if (IsGPR(reg)) { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value.SetUInt(v, reg_info->byte_size); + return true; } - - if (IsFPR(reg)) - { - lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) - { - value.SetUInt(v, reg_info->byte_size); - return true; - } + } + + if (IsFPR(reg)) { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) { + value.SetUInt(v, reg_info->byte_size); + return true; } + } - return false; + return false; } -bool -RegisterContextCorePOSIX_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_s390x::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_s390x::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_s390x::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_s390x::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_s390x::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h index a9bdff6356e..7eb357375f9 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -17,49 +17,43 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" #include "lldb/Core/DataExtractor.h" -class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x -{ +class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x { public: - RegisterContextCorePOSIX_s390x(lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + RegisterContextCorePOSIX_s390x( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); - ~RegisterContextCorePOSIX_s390x() override; + ~RegisterContextCorePOSIX_s390x() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb_private::DataExtractor m_gpr; + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; - lldb::DataBufferSP m_fpr_buffer; - lldb_private::DataExtractor m_fpr; + lldb::DataBufferSP m_fpr_buffer; + lldb_private::DataExtractor m_fpr; }; #endif // liblldb_RegisterContextCorePOSIX_s390x_h_ diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 926c7aff360..8157401b54e 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -7,93 +7,71 @@ // //===----------------------------------------------------------------------===// +#include "RegisterContextPOSIXCore_x86_64.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIXCore_x86_64.h" using namespace lldb_private; -RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64(Thread &thread, - RegisterInfoInterface *register_info, - const DataExtractor &gpregset, - const DataExtractor &fpregset) - : RegisterContextPOSIX_x86 (thread, 0, register_info) -{ - size_t size, len; +RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, const DataExtractor &fpregset) + : RegisterContextPOSIX_x86(thread, 0, register_info) { + size_t size, len; - size = GetGPRSize(); - m_gpregset = new uint8_t[size]; - len = gpregset.ExtractBytes (0, size, lldb::eByteOrderLittle, m_gpregset); - assert(len == size); + size = GetGPRSize(); + m_gpregset = new uint8_t[size]; + len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset); + assert(len == size); } -RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64() -{ - delete [] m_gpregset; +RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64() { + delete[] m_gpregset; } -bool -RegisterContextCorePOSIX_x86_64::ReadGPR() -{ - return m_gpregset != NULL; -} +bool RegisterContextCorePOSIX_x86_64::ReadGPR() { return m_gpregset != NULL; } -bool -RegisterContextCorePOSIX_x86_64::ReadFPR() -{ - return false; -} +bool RegisterContextCorePOSIX_x86_64::ReadFPR() { return false; } -bool -RegisterContextCorePOSIX_x86_64::WriteGPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_x86_64::WriteGPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_x86_64::WriteFPR() -{ - assert(0); - return false; +bool RegisterContextCorePOSIX_x86_64::WriteFPR() { + assert(0); + return false; } -bool -RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - switch (reg_info->byte_size) - { - case 4: - value = *(uint32_t *)(m_gpregset + reg_info->byte_offset); - return true; - case 8: - value = *(uint64_t *)(m_gpregset + reg_info->byte_offset); - return true; - } - return false; +bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + switch (reg_info->byte_size) { + case 4: + value = *(uint32_t *)(m_gpregset + reg_info->byte_offset); + return true; + case 8: + value = *(uint64_t *)(m_gpregset + reg_info->byte_offset); + return true; + } + return false; } -bool -RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - return false; +bool RegisterContextCorePOSIX_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; } -bool -RegisterContextCorePOSIX_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - return false; +bool RegisterContextCorePOSIX_x86_64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + return false; } -bool -RegisterContextCorePOSIX_x86_64::HardwareSingleStep(bool enable) -{ - return false; +bool RegisterContextCorePOSIX_x86_64::HardwareSingleStep(bool enable) { + return false; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h index 60f2ad33b4a..eeb36b68de0 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -16,49 +16,39 @@ // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" -class RegisterContextCorePOSIX_x86_64 : - public RegisterContextPOSIX_x86 -{ +class RegisterContextCorePOSIX_x86_64 : public RegisterContextPOSIX_x86 { public: - RegisterContextCorePOSIX_x86_64 (lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, - const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + RegisterContextCorePOSIX_x86_64( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); - ~RegisterContextCorePOSIX_x86_64() override; + ~RegisterContextCorePOSIX_x86_64() override; - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) override; + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - HardwareSingleStep(bool enable) override; + bool HardwareSingleStep(bool enable) override; protected: - bool - ReadGPR() override; + bool ReadGPR() override; - bool - ReadFPR() override; + bool ReadFPR() override; - bool - WriteGPR() override; + bool WriteGPR() override; - bool - WriteFPR() override; + bool WriteFPR() override; private: - uint8_t *m_gpregset; + uint8_t *m_gpregset; }; #endif // liblldb_RegisterContextCorePOSIX_x86_64_h_ diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 29f37b6f88f..3135de0632f 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -14,25 +14,25 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" -#include "ThreadElfCore.h" -#include "ProcessElfCore.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" -#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" -#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" +#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" +#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" +#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" +#include "ProcessElfCore.h" #include "RegisterContextPOSIXCore_arm.h" #include "RegisterContextPOSIXCore_arm64.h" #include "RegisterContextPOSIXCore_mips64.h" #include "RegisterContextPOSIXCore_powerpc.h" #include "RegisterContextPOSIXCore_s390x.h" #include "RegisterContextPOSIXCore_x86_64.h" +#include "ThreadElfCore.h" using namespace lldb; using namespace lldb_private; @@ -40,313 +40,283 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Construct a Thread object with given data //---------------------------------------------------------------------- -ThreadElfCore::ThreadElfCore (Process &process, const ThreadData &td) : - Thread(process, td.tid), - m_thread_name(td.name), - m_thread_reg_ctx_sp (), - m_signo(td.signo), - m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset), - m_vregset_data(td.vregset) -{ -} +ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) + : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), + m_signo(td.signo), m_gpregset_data(td.gpregset), + m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {} -ThreadElfCore::~ThreadElfCore () -{ - DestroyThread(); +ThreadElfCore::~ThreadElfCore() { DestroyThread(); } + +void ThreadElfCore::RefreshStateAfterStop() { + GetRegisterContext()->InvalidateIfNeeded(false); } -void -ThreadElfCore::RefreshStateAfterStop() -{ - GetRegisterContext()->InvalidateIfNeeded (false); +void ThreadElfCore::ClearStackFrames() { + Unwind *unwinder = GetUnwinder(); + if (unwinder) + unwinder->Clear(); + Thread::ClearStackFrames(); } -void -ThreadElfCore::ClearStackFrames () -{ - Unwind *unwinder = GetUnwinder (); - if (unwinder) - unwinder->Clear(); - Thread::ClearStackFrames(); +RegisterContextSP ThreadElfCore::GetRegisterContext() { + if (m_reg_context_sp.get() == NULL) { + m_reg_context_sp = CreateRegisterContextForFrame(NULL); + } + return m_reg_context_sp; } RegisterContextSP -ThreadElfCore::GetRegisterContext () -{ - if (m_reg_context_sp.get() == NULL) { - m_reg_context_sp = CreateRegisterContextForFrame (NULL); +ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { + RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + if (m_thread_reg_ctx_sp) + return m_thread_reg_ctx_sp; + + ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get()); + ArchSpec arch = process->GetArchitecture(); + RegisterInfoInterface *reg_interface = NULL; + + switch (arch.GetTriple().getOS()) { + case llvm::Triple::FreeBSD: { + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + reg_interface = new RegisterContextFreeBSD_arm64(arch); + break; + case llvm::Triple::arm: + reg_interface = new RegisterContextFreeBSD_arm(arch); + break; + case llvm::Triple::ppc: + reg_interface = new RegisterContextFreeBSD_powerpc32(arch); + break; + case llvm::Triple::ppc64: + reg_interface = new RegisterContextFreeBSD_powerpc64(arch); + break; + case llvm::Triple::mips64: + reg_interface = new RegisterContextFreeBSD_mips64(arch); + break; + case llvm::Triple::x86: + reg_interface = new RegisterContextFreeBSD_i386(arch); + break; + case llvm::Triple::x86_64: + reg_interface = new RegisterContextFreeBSD_x86_64(arch); + break; + default: + break; + } + break; } - return m_reg_context_sp; -} -RegisterContextSP -ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) -{ - RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex (); - - if (concrete_frame_idx == 0) - { - if (m_thread_reg_ctx_sp) - return m_thread_reg_ctx_sp; - - ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get()); - ArchSpec arch = process->GetArchitecture(); - RegisterInfoInterface *reg_interface = NULL; - - switch (arch.GetTriple().getOS()) - { - case llvm::Triple::FreeBSD: - { - switch (arch.GetMachine()) - { - case llvm::Triple::aarch64: - reg_interface = new RegisterContextFreeBSD_arm64(arch); - break; - case llvm::Triple::arm: - reg_interface = new RegisterContextFreeBSD_arm(arch); - break; - case llvm::Triple::ppc: - reg_interface = new RegisterContextFreeBSD_powerpc32(arch); - break; - case llvm::Triple::ppc64: - reg_interface = new RegisterContextFreeBSD_powerpc64(arch); - break; - case llvm::Triple::mips64: - reg_interface = new RegisterContextFreeBSD_mips64(arch); - break; - case llvm::Triple::x86: - reg_interface = new RegisterContextFreeBSD_i386(arch); - break; - case llvm::Triple::x86_64: - reg_interface = new RegisterContextFreeBSD_x86_64(arch); - break; - default: - break; - } - break; - } - - case llvm::Triple::Linux: - { - switch (arch.GetMachine()) - { - case llvm::Triple::arm: - reg_interface = new RegisterContextLinux_arm(arch); - break; - case llvm::Triple::aarch64: - reg_interface = new RegisterContextLinux_arm64(arch); - break; - case llvm::Triple::systemz: - reg_interface = new RegisterContextLinux_s390x(arch); - break; - case llvm::Triple::x86: - reg_interface = new RegisterContextLinux_i386(arch); - break; - case llvm::Triple::x86_64: - reg_interface = new RegisterContextLinux_x86_64(arch); - break; - default: - break; - } - break; - } - - default: - break; - } - - if (!reg_interface) { - if (log) - log->Printf ("elf-core::%s:: Architecture(%d) or OS(%d) not supported", - __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); - assert (false && "Architecture or OS not supported"); - } - - switch (arch.GetMachine()) - { - case llvm::Triple::aarch64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); - break; - case llvm::Triple::arm: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm (*this, reg_interface, m_gpregset_data, m_fpregset_data)); - break; - case llvm::Triple::mips64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); - break; - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); - break; - case llvm::Triple::systemz: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x (*this, reg_interface, m_gpregset_data, m_fpregset_data)); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); - break; - default: - break; - } - - reg_ctx_sp = m_thread_reg_ctx_sp; + case llvm::Triple::Linux: { + switch (arch.GetMachine()) { + case llvm::Triple::arm: + reg_interface = new RegisterContextLinux_arm(arch); + break; + case llvm::Triple::aarch64: + reg_interface = new RegisterContextLinux_arm64(arch); + break; + case llvm::Triple::systemz: + reg_interface = new RegisterContextLinux_s390x(arch); + break; + case llvm::Triple::x86: + reg_interface = new RegisterContextLinux_i386(arch); + break; + case llvm::Triple::x86_64: + reg_interface = new RegisterContextLinux_x86_64(arch); + break; + default: + break; + } + break; } - else if (m_unwinder_ap.get()) - { - reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame); + + default: + break; + } + + if (!reg_interface) { + if (log) + log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported", + __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); + assert(false && "Architecture or OS not supported"); } - return reg_ctx_sp; -} -bool -ThreadElfCore::CalculateStopInfo () -{ - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo)); - return true; + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; + case llvm::Triple::arm: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; + case llvm::Triple::mips64: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc( + *this, reg_interface, m_gpregset_data, m_fpregset_data, + m_vregset_data)); + break; + case llvm::Triple::systemz: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; + default: + break; } - return false; + + reg_ctx_sp = m_thread_reg_ctx_sp; + } else if (m_unwinder_ap.get()) { + reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; +} + +bool ThreadElfCore::CalculateStopInfo() { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo)); + return true; + } + return false; } //---------------------------------------------------------------- // Parse PRSTATUS from NOTE entry //---------------------------------------------------------------- -ELFLinuxPrStatus::ELFLinuxPrStatus() -{ - memset(this, 0, sizeof(ELFLinuxPrStatus)); +ELFLinuxPrStatus::ELFLinuxPrStatus() { + memset(this, 0, sizeof(ELFLinuxPrStatus)); } -Error -ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) -{ - Error error; - ByteOrder byteorder = data.GetByteOrder(); - if (GetSize(arch) > data.GetByteSize()) - { - error.SetErrorStringWithFormat("NT_PRSTATUS size should be %lu, but the remaining bytes are: %" PRIu64, - GetSize(arch), data.GetByteSize()); - return error; - } - - switch(arch.GetCore()) - { - case ArchSpec::eCore_s390x_generic: - case ArchSpec::eCore_x86_64_x86_64: - data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this); - break; - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - { - // Parsing from a 32 bit ELF core file, and populating/reusing the structure - // properly, because the struct is for the 64 bit version - offset_t offset = 0; - si_signo = data.GetU32(&offset); - si_code = data.GetU32(&offset); - si_errno = data.GetU32(&offset); - - pr_cursig = data.GetU16(&offset); - offset += 2; // pad - - pr_sigpend = data.GetU32(&offset); - pr_sighold = data.GetU32(&offset); - - pr_pid = data.GetU32(&offset); - pr_ppid = data.GetU32(&offset); - pr_pgrp = data.GetU32(&offset); - pr_sid = data.GetU32(&offset); - - pr_utime.tv_sec = data.GetU32(&offset); - pr_utime.tv_usec = data.GetU32(&offset); - - pr_stime.tv_sec = data.GetU32(&offset); - pr_stime.tv_usec = data.GetU32(&offset); - - pr_cutime.tv_sec = data.GetU32(&offset); - pr_cutime.tv_usec = data.GetU32(&offset); - - pr_cstime.tv_sec = data.GetU32(&offset); - pr_cstime.tv_usec = data.GetU32(&offset); - - break; - } - default: - error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture", __FUNCTION__); - break; - } - +Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { + Error error; + ByteOrder byteorder = data.GetByteOrder(); + if (GetSize(arch) > data.GetByteSize()) { + error.SetErrorStringWithFormat( + "NT_PRSTATUS size should be %lu, but the remaining bytes are: %" PRIu64, + GetSize(arch), data.GetByteSize()); return error; + } + + switch (arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: + case ArchSpec::eCore_x86_64_x86_64: + data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this); + break; + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: { + // Parsing from a 32 bit ELF core file, and populating/reusing the structure + // properly, because the struct is for the 64 bit version + offset_t offset = 0; + si_signo = data.GetU32(&offset); + si_code = data.GetU32(&offset); + si_errno = data.GetU32(&offset); + + pr_cursig = data.GetU16(&offset); + offset += 2; // pad + + pr_sigpend = data.GetU32(&offset); + pr_sighold = data.GetU32(&offset); + + pr_pid = data.GetU32(&offset); + pr_ppid = data.GetU32(&offset); + pr_pgrp = data.GetU32(&offset); + pr_sid = data.GetU32(&offset); + + pr_utime.tv_sec = data.GetU32(&offset); + pr_utime.tv_usec = data.GetU32(&offset); + + pr_stime.tv_sec = data.GetU32(&offset); + pr_stime.tv_usec = data.GetU32(&offset); + + pr_cutime.tv_sec = data.GetU32(&offset); + pr_cutime.tv_usec = data.GetU32(&offset); + + pr_cstime.tv_sec = data.GetU32(&offset); + pr_cstime.tv_usec = data.GetU32(&offset); + + break; + } + default: + error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture", + __FUNCTION__); + break; + } + + return error; } //---------------------------------------------------------------- // Parse PRPSINFO from NOTE entry //---------------------------------------------------------------- -ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() -{ - memset(this, 0, sizeof(ELFLinuxPrPsInfo)); +ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { + memset(this, 0, sizeof(ELFLinuxPrPsInfo)); } -Error -ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) -{ - Error error; - ByteOrder byteorder = data.GetByteOrder(); - if (GetSize(arch) > data.GetByteSize()) - { - error.SetErrorStringWithFormat("NT_PRPSINFO size should be %lu, but the remaining bytes are: %" PRIu64, - GetSize(arch), data.GetByteSize()); - return error; - } - - switch(arch.GetCore()) - { - case ArchSpec::eCore_s390x_generic: - case ArchSpec::eCore_x86_64_x86_64: - data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this); - break; - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - { - // Parsing from a 32 bit ELF core file, and populating/reusing the structure - // properly, because the struct is for the 64 bit version - size_t size = 0; - offset_t offset = 0; - - pr_state = data.GetU8(&offset); - pr_sname = data.GetU8(&offset); - pr_zomb = data.GetU8(&offset); - pr_nice = data.GetU8(&offset); - - pr_flag = data.GetU32(&offset); - pr_uid = data.GetU16(&offset); - pr_gid = data.GetU16(&offset); - - pr_pid = data.GetU32(&offset); - pr_ppid = data.GetU32(&offset); - pr_pgrp = data.GetU32(&offset); - pr_sid = data.GetU32(&offset); - - size = 16; - data.ExtractBytes(offset, size, byteorder, pr_fname); - offset += size; - - size = 80; - data.ExtractBytes(offset, size, byteorder, pr_psargs); - offset += size; - - break; - } - default: - error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", __FUNCTION__); - break; - } - +Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { + Error error; + ByteOrder byteorder = data.GetByteOrder(); + if (GetSize(arch) > data.GetByteSize()) { + error.SetErrorStringWithFormat( + "NT_PRPSINFO size should be %lu, but the remaining bytes are: %" PRIu64, + GetSize(arch), data.GetByteSize()); return error; + } + + switch (arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: + case ArchSpec::eCore_x86_64_x86_64: + data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this); + break; + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: { + // Parsing from a 32 bit ELF core file, and populating/reusing the structure + // properly, because the struct is for the 64 bit version + size_t size = 0; + offset_t offset = 0; + + pr_state = data.GetU8(&offset); + pr_sname = data.GetU8(&offset); + pr_zomb = data.GetU8(&offset); + pr_nice = data.GetU8(&offset); + + pr_flag = data.GetU32(&offset); + pr_uid = data.GetU16(&offset); + pr_gid = data.GetU16(&offset); + + pr_pid = data.GetU32(&offset); + pr_ppid = data.GetU32(&offset); + pr_pgrp = data.GetU32(&offset); + pr_sid = data.GetU32(&offset); + + size = 16; + data.ExtractBytes(offset, size, byteorder, pr_fname); + offset += size; + + size = 80; + data.ExtractBytes(offset, size, byteorder, pr_psargs); + offset += size; + + break; + } + default: + error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", + __FUNCTION__); + break; + } + + return error; } - diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index e0824c7ac7d..c1445161dcb 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -16,188 +16,171 @@ // Other libraries and framework includes // Project includes -#include "lldb/Target/Thread.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Target/Thread.h" -struct compat_timeval -{ - alignas(8) uint64_t tv_sec; - alignas(8) uint64_t tv_usec; +struct compat_timeval { + alignas(8) uint64_t tv_sec; + alignas(8) uint64_t tv_usec; }; // PRSTATUS structure's size differs based on architecture. // This is the layout in the x86-64 arch. // In the i386 case we parse it manually and fill it again // in the same structure -// The gp registers are also a part of this struct, but they are handled separately +// The gp registers are also a part of this struct, but they are handled +// separately #undef si_signo #undef si_code #undef si_errno -struct ELFLinuxPrStatus -{ - int32_t si_signo; - int32_t si_code; - int32_t si_errno; - - int16_t pr_cursig; - - alignas(8) uint64_t pr_sigpend; - alignas(8) uint64_t pr_sighold; - - uint32_t pr_pid; - uint32_t pr_ppid; - uint32_t pr_pgrp; - uint32_t pr_sid; - - compat_timeval pr_utime; - compat_timeval pr_stime; - compat_timeval pr_cutime; - compat_timeval pr_cstime; - - ELFLinuxPrStatus(); - - lldb_private::Error - Parse(lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch); - - // Return the bytesize of the structure - // 64 bit - just sizeof - // 32 bit - hardcoded because we are reusing the struct, but some of the members are smaller - - // so the layout is not the same - static size_t - GetSize(lldb_private::ArchSpec &arch) - { - switch(arch.GetCore()) - { - case lldb_private::ArchSpec::eCore_s390x_generic: - case lldb_private::ArchSpec::eCore_x86_64_x86_64: - return sizeof(ELFLinuxPrStatus); - case lldb_private::ArchSpec::eCore_x86_32_i386: - case lldb_private::ArchSpec::eCore_x86_32_i486: - return 72; - default: - return 0; - } +struct ELFLinuxPrStatus { + int32_t si_signo; + int32_t si_code; + int32_t si_errno; + + int16_t pr_cursig; + + alignas(8) uint64_t pr_sigpend; + alignas(8) uint64_t pr_sighold; + + uint32_t pr_pid; + uint32_t pr_ppid; + uint32_t pr_pgrp; + uint32_t pr_sid; + + compat_timeval pr_utime; + compat_timeval pr_stime; + compat_timeval pr_cutime; + compat_timeval pr_cstime; + + ELFLinuxPrStatus(); + + lldb_private::Error Parse(lldb_private::DataExtractor &data, + lldb_private::ArchSpec &arch); + + // Return the bytesize of the structure + // 64 bit - just sizeof + // 32 bit - hardcoded because we are reusing the struct, but some of the + // members are smaller - + // so the layout is not the same + static size_t GetSize(lldb_private::ArchSpec &arch) { + switch (arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: + case lldb_private::ArchSpec::eCore_x86_64_x86_64: + return sizeof(ELFLinuxPrStatus); + case lldb_private::ArchSpec::eCore_x86_32_i386: + case lldb_private::ArchSpec::eCore_x86_32_i486: + return 72; + default: + return 0; } + } }; -static_assert(sizeof(ELFLinuxPrStatus) == 112, "sizeof ELFLinuxPrStatus is not correct!"); +static_assert(sizeof(ELFLinuxPrStatus) == 112, + "sizeof ELFLinuxPrStatus is not correct!"); // PRPSINFO structure's size differs based on architecture. // This is the layout in the x86-64 arch case. // In the i386 case we parse it manually and fill it again // in the same structure -struct ELFLinuxPrPsInfo -{ - char pr_state; - char pr_sname; - char pr_zomb; - char pr_nice; - alignas(8) uint64_t pr_flag; - uint32_t pr_uid; - uint32_t pr_gid; - int32_t pr_pid; - int32_t pr_ppid; - int32_t pr_pgrp; - int32_t pr_sid; - char pr_fname[16]; - char pr_psargs[80]; - - ELFLinuxPrPsInfo(); - - lldb_private::Error - Parse(lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch); - - // Return the bytesize of the structure - // 64 bit - just sizeof - // 32 bit - hardcoded because we are reusing the struct, but some of the members are smaller - - // so the layout is not the same - static size_t - GetSize(lldb_private::ArchSpec &arch) - { - switch(arch.GetCore()) - { - case lldb_private::ArchSpec::eCore_s390x_generic: - case lldb_private::ArchSpec::eCore_x86_64_x86_64: - return sizeof(ELFLinuxPrPsInfo); - case lldb_private::ArchSpec::eCore_x86_32_i386: - case lldb_private::ArchSpec::eCore_x86_32_i486: - return 124; - default: - return 0; - } +struct ELFLinuxPrPsInfo { + char pr_state; + char pr_sname; + char pr_zomb; + char pr_nice; + alignas(8) uint64_t pr_flag; + uint32_t pr_uid; + uint32_t pr_gid; + int32_t pr_pid; + int32_t pr_ppid; + int32_t pr_pgrp; + int32_t pr_sid; + char pr_fname[16]; + char pr_psargs[80]; + + ELFLinuxPrPsInfo(); + + lldb_private::Error Parse(lldb_private::DataExtractor &data, + lldb_private::ArchSpec &arch); + + // Return the bytesize of the structure + // 64 bit - just sizeof + // 32 bit - hardcoded because we are reusing the struct, but some of the + // members are smaller - + // so the layout is not the same + static size_t GetSize(lldb_private::ArchSpec &arch) { + switch (arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: + case lldb_private::ArchSpec::eCore_x86_64_x86_64: + return sizeof(ELFLinuxPrPsInfo); + case lldb_private::ArchSpec::eCore_x86_32_i386: + case lldb_private::ArchSpec::eCore_x86_32_i486: + return 124; + default: + return 0; } + } }; -static_assert(sizeof(ELFLinuxPrPsInfo) == 136, "sizeof ELFLinuxPrPsInfo is not correct!"); +static_assert(sizeof(ELFLinuxPrPsInfo) == 136, + "sizeof ELFLinuxPrPsInfo is not correct!"); -struct ThreadData -{ - lldb_private::DataExtractor gpregset; - lldb_private::DataExtractor fpregset; - lldb_private::DataExtractor vregset; - lldb::tid_t tid; - int signo; - std::string name; +struct ThreadData { + lldb_private::DataExtractor gpregset; + lldb_private::DataExtractor fpregset; + lldb_private::DataExtractor vregset; + lldb::tid_t tid; + int signo; + std::string name; }; -class ThreadElfCore : public lldb_private::Thread -{ +class ThreadElfCore : public lldb_private::Thread { public: - ThreadElfCore (lldb_private::Process &process, const ThreadData &td); + ThreadElfCore(lldb_private::Process &process, const ThreadData &td); - ~ThreadElfCore() override; + ~ThreadElfCore() override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - lldb::RegisterContextSP - GetRegisterContext() override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - void - ClearStackFrames() override; + void ClearStackFrames() override; - static bool - ThreadIDIsValid (lldb::tid_t thread) - { - return thread != 0; - } + static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } - const char * - GetName() override - { - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); - } + const char *GetName() override { + if (m_thread_name.empty()) + return NULL; + return m_thread_name.c_str(); + } - void - SetName(const char *name) override - { - if (name && name[0]) - m_thread_name.assign (name); - else - m_thread_name.clear(); - } + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } protected: - //------------------------------------------------------------------ - // Member variables. - //------------------------------------------------------------------ - std::string m_thread_name; - lldb::RegisterContextSP m_thread_reg_ctx_sp; + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + std::string m_thread_name; + lldb::RegisterContextSP m_thread_reg_ctx_sp; - int m_signo; + int m_signo; - lldb_private::DataExtractor m_gpregset_data; - lldb_private::DataExtractor m_fpregset_data; - lldb_private::DataExtractor m_vregset_data; + lldb_private::DataExtractor m_gpregset_data; + lldb_private::DataExtractor m_fpregset_data; + lldb_private::DataExtractor m_vregset_data; - bool CalculateStopInfo() override; + bool CalculateStopInfo() override; }; #endif // liblldb_ThreadElfCore_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index f99352a0a3a..3b27c10db4a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -29,336 +29,333 @@ static const std::chrono::seconds kInterruptTimeout(5); GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default; -GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0), m_is_running(false), m_should_stop(false) -{ -} +GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name, + const char *listener_name) + : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0), + m_is_running(false), m_should_stop(false) {} + +StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( + ContinueDelegate &delegate, const UnixSignals &signals, + llvm::StringRef payload, StringExtractorGDBRemote &response) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + response.Clear(); + + { + std::lock_guard<std::mutex> lock(m_mutex); + m_continue_packet = payload; + m_should_stop = false; + } + ContinueLock cont_lock(*this); + if (!cont_lock) + return eStateInvalid; + OnRunPacketSent(true); + + for (;;) { + PacketResult read_result = ReadPacket( + response, + std::chrono::duration_cast<std::chrono::microseconds>(kInterruptTimeout) + .count(), + false); + switch (read_result) { + case PacketResult::ErrorReplyTimeout: { + std::lock_guard<std::mutex> lock(m_mutex); + if (m_async_count == 0) + continue; + if (std::chrono::steady_clock::now() >= + m_interrupt_time + kInterruptTimeout) + return eStateInvalid; + } + case PacketResult::Success: + break; + default: + if (log) + log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false", + __FUNCTION__); + return eStateInvalid; + } + if (response.Empty()) + return eStateInvalid; -StateType -GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response) -{ - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - response.Clear(); - - { - std::lock_guard<std::mutex> lock(m_mutex); - m_continue_packet = payload; - m_should_stop = false; + const char stop_type = response.GetChar(); + if (log) + log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, + response.GetStringRef().c_str()); + + switch (stop_type) { + case 'W': + case 'X': + return eStateExited; + case 'E': + // ERROR + return eStateInvalid; + default: + if (log) + log->Printf("GDBRemoteClientBase::%s () unrecognized async packet", + __FUNCTION__); + return eStateInvalid; + case 'O': { + std::string inferior_stdout; + response.GetHexByteString(inferior_stdout); + delegate.HandleAsyncStdout(inferior_stdout); + break; } - ContinueLock cont_lock(*this); - if (!cont_lock) - return eStateInvalid; - OnRunPacketSent(true); - - for (;;) - { - PacketResult read_result = ReadPacket( - response, std::chrono::duration_cast<std::chrono::microseconds>(kInterruptTimeout).count(), false); - switch (read_result) - { - case PacketResult::ErrorReplyTimeout: - { - std::lock_guard<std::mutex> lock(m_mutex); - if (m_async_count == 0) - continue; - if (std::chrono::steady_clock::now() >= m_interrupt_time + kInterruptTimeout) - return eStateInvalid; - } - case PacketResult::Success: - break; - default: - if (log) - log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false", __FUNCTION__); - return eStateInvalid; + case 'A': + delegate.HandleAsyncMisc( + llvm::StringRef(response.GetStringRef()).substr(1)); + break; + + case 'J': + // Asynchronous JSON packet, destined for a + // StructuredDataPlugin. + { + // Parse the content into a StructuredData instance. + auto payload_index = strlen("JSON-async:"); + StructuredData::ObjectSP json_sp = StructuredData::ParseJSON( + response.GetStringRef().substr(payload_index)); + if (log) { + if (json_sp) + log->Printf("GDBRemoteCommmunicationClientBase::%s() " + "received Async StructuredData packet: %s", + __FUNCTION__, + response.GetStringRef().substr(payload_index).c_str()); + else + log->Printf("GDBRemoteCommmunicationClientBase::%s" + "() received StructuredData packet:" + " parse failure", + __FUNCTION__); } - if (response.Empty()) - return eStateInvalid; - const char stop_type = response.GetChar(); + // Pass the data to the process to route to the + // appropriate plugin. The plugin controls what happens + // to it from there. + bool routed = delegate.HandleAsyncStructuredData(json_sp); if (log) - log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str()); - - switch (stop_type) - { - case 'W': - case 'X': - return eStateExited; - case 'E': - // ERROR - return eStateInvalid; - default: - if (log) - log->Printf("GDBRemoteClientBase::%s () unrecognized async packet", __FUNCTION__); - return eStateInvalid; - case 'O': - { - std::string inferior_stdout; - response.GetHexByteString(inferior_stdout); - delegate.HandleAsyncStdout(inferior_stdout); - break; - } - case 'A': - delegate.HandleAsyncMisc(llvm::StringRef(response.GetStringRef()).substr(1)); - break; - - case 'J': - // Asynchronous JSON packet, destined for a - // StructuredDataPlugin. - { - // Parse the content into a StructuredData instance. - auto payload_index = strlen("JSON-async:"); - StructuredData::ObjectSP json_sp = - StructuredData::ParseJSON(response.GetStringRef() - .substr(payload_index)); - if (log) - { - if (json_sp) - log->Printf( - "GDBRemoteCommmunicationClientBase::%s() " - "received Async StructuredData packet: %s", - __FUNCTION__, - response.GetStringRef(). - substr(payload_index).c_str()); - else - log->Printf("GDBRemoteCommmunicationClientBase::%s" - "() received StructuredData packet:" - " parse failure", __FUNCTION__); - } - - // Pass the data to the process to route to the - // appropriate plugin. The plugin controls what happens - // to it from there. - bool routed = delegate.HandleAsyncStructuredData(json_sp); - if (log) - log->Printf("GDBRemoteCommmunicationClientBase::%s()" - " packet %s", __FUNCTION__, - routed ? "handled" : "not handled"); - break; - } - case 'T': - case 'S': - // Do this with the continue lock held. - const bool should_stop = ShouldStop(signals, response); - response.SetFilePos(0); - - // The packet we should resume with. In the future - // we should check our thread list and "do the right thing" - // for new threads that show up while we stop and run async - // packets. Setting the packet to 'c' to continue all threads - // is the right thing to do 99.99% of the time because if a - // thread was single stepping, and we sent an interrupt, we - // will notice above that we didn't stop due to an interrupt - // but stopped due to stepping and we would _not_ continue. - // This packet may get modified by the async actions (e.g. to send a signal). - m_continue_packet = 'c'; - cont_lock.unlock(); - - delegate.HandleStopReply(); - if (should_stop) - return eStateStopped; - - switch (cont_lock.lock()) - { - case ContinueLock::LockResult::Success: - break; - case ContinueLock::LockResult::Failed: - return eStateInvalid; - case ContinueLock::LockResult::Cancelled: - return eStateStopped; - } - OnRunPacketSent(false); - break; - } + log->Printf("GDBRemoteCommmunicationClientBase::%s()" + " packet %s", + __FUNCTION__, routed ? "handled" : "not handled"); + break; + } + case 'T': + case 'S': + // Do this with the continue lock held. + const bool should_stop = ShouldStop(signals, response); + response.SetFilePos(0); + + // The packet we should resume with. In the future + // we should check our thread list and "do the right thing" + // for new threads that show up while we stop and run async + // packets. Setting the packet to 'c' to continue all threads + // is the right thing to do 99.99% of the time because if a + // thread was single stepping, and we sent an interrupt, we + // will notice above that we didn't stop due to an interrupt + // but stopped due to stepping and we would _not_ continue. + // This packet may get modified by the async actions (e.g. to send a + // signal). + m_continue_packet = 'c'; + cont_lock.unlock(); + + delegate.HandleStopReply(); + if (should_stop) + return eStateStopped; + + switch (cont_lock.lock()) { + case ContinueLock::LockResult::Success: + break; + case ContinueLock::LockResult::Failed: + return eStateInvalid; + case ContinueLock::LockResult::Cancelled: + return eStateStopped; + } + OnRunPacketSent(false); + break; } + } } -bool -GDBRemoteClientBase::SendAsyncSignal(int signo) -{ - Lock lock(*this, true); - if (!lock || !lock.DidInterrupt()) - return false; +bool GDBRemoteClientBase::SendAsyncSignal(int signo) { + Lock lock(*this, true); + if (!lock || !lock.DidInterrupt()) + return false; - m_continue_packet = 'C'; - m_continue_packet += llvm::hexdigit((signo / 16) % 16); - m_continue_packet += llvm::hexdigit(signo % 16); - return true; + m_continue_packet = 'C'; + m_continue_packet += llvm::hexdigit((signo / 16) % 16); + m_continue_packet += llvm::hexdigit(signo % 16); + return true; } -bool -GDBRemoteClientBase::Interrupt() -{ - Lock lock(*this, true); - if (!lock.DidInterrupt()) - return false; - m_should_stop = true; - return true; +bool GDBRemoteClientBase::Interrupt() { + Lock lock(*this, true); + if (!lock.DidInterrupt()) + return false; + m_should_stop = true; + return true; } GDBRemoteCommunication::PacketResult -GDBRemoteClientBase::SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async) -{ - Lock lock(*this, send_async); - if (!lock) - { - if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) - log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), send_async); - return PacketResult::ErrorSendFailed; - } - - return SendPacketAndWaitForResponseNoLock(payload, response); +GDBRemoteClientBase::SendPacketAndWaitForResponse( + llvm::StringRef payload, StringExtractorGDBRemote &response, + bool send_async) { + Lock lock(*this, send_async); + if (!lock) { + if (Log *log = + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) + log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending " + "packet '%.*s' (send_async=%d)", + __FUNCTION__, int(payload.size()), payload.data(), + send_async); + return PacketResult::ErrorSendFailed; + } + + return SendPacketAndWaitForResponseNoLock(payload, response); } GDBRemoteCommunication::PacketResult -GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response) -{ - PacketResult packet_result = SendPacketNoLock(payload); - if (packet_result != PacketResult::Success) - return packet_result; - - const size_t max_response_retries = 3; - for (size_t i = 0; i < max_response_retries; ++i) - { - packet_result = ReadPacket(response, GetPacketTimeoutInMicroSeconds(), true); - // Make sure we received a response - if (packet_result != PacketResult::Success) - return packet_result; - // Make sure our response is valid for the payload that was sent - if (response.ValidateResponse()) - return packet_result; - // Response says it wasn't valid - Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS); - if (log) - log->Printf("error: packet with payload \"%.*s\" got invalid response \"%s\": %s", int(payload.size()), - payload.data(), response.GetStringRef().c_str(), - (i == (max_response_retries - 1)) ? "using invalid response and giving up" - : "ignoring response and waiting for another"); - } +GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( + llvm::StringRef payload, StringExtractorGDBRemote &response) { + PacketResult packet_result = SendPacketNoLock(payload); + if (packet_result != PacketResult::Success) return packet_result; -} -bool -GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response) -{ - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + const size_t max_response_retries = 3; + for (size_t i = 0; i < max_response_retries; ++i) { + packet_result = + ReadPacket(response, GetPacketTimeoutInMicroSeconds(), true); + // Make sure we received a response + if (packet_result != PacketResult::Success) + return packet_result; + // Make sure our response is valid for the payload that was sent + if (response.ValidateResponse()) + return packet_result; + // Response says it wasn't valid + Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS); if (log) - log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__); + log->Printf( + "error: packet with payload \"%.*s\" got invalid response \"%s\": %s", + int(payload.size()), payload.data(), response.GetStringRef().c_str(), + (i == (max_response_retries - 1)) + ? "using invalid response and giving up" + : "ignoring response and waiting for another"); + } + return packet_result; +} - // we want to lock down packet sending while we continue - Lock lock(*this, true); +bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, + StringExtractorGDBRemote &response) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__); - if (log) - log->Printf("GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", __FUNCTION__, int(payload.size()), - payload.data()); + // we want to lock down packet sending while we continue + Lock lock(*this, true); - if (SendPacketNoLock(payload) != PacketResult::Success) - return false; + if (log) + log->Printf( + "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", + __FUNCTION__, int(payload.size()), payload.data()); - OnRunPacketSent(true); + if (SendPacketNoLock(payload) != PacketResult::Success) + return false; - // wait for the response to the vCont - if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return true; - } + OnRunPacketSent(true); - return false; + // wait for the response to the vCont + if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success) { + if (response.IsOKResponse()) + return true; + } + + return false; } -bool -GDBRemoteClientBase::ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response) -{ - std::lock_guard<std::mutex> lock(m_mutex); +bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals, + StringExtractorGDBRemote &response) { + std::lock_guard<std::mutex> lock(m_mutex); + + if (m_async_count == 0) + return true; // We were not interrupted. The process stopped on its own. + + // Older debugserver stubs (before April 2016) can return two + // stop-reply packets in response to a ^C packet. + // Additionally, all debugservers still return two stop replies if + // the inferior stops due to some other reason before the remote + // stub manages to interrupt it. We need to wait for this + // additional packet to make sure the packet sequence does not get + // skewed. + StringExtractorGDBRemote extra_stop_reply_packet; + uint32_t timeout_usec = 100000; // 100ms + ReadPacket(extra_stop_reply_packet, timeout_usec, false); + + // Interrupting is typically done using SIGSTOP or SIGINT, so if + // the process stops with some other signal, we definitely want to + // stop. + const uint8_t signo = response.GetHexU8(UINT8_MAX); + if (signo != signals.GetSignalNumberFromName("SIGSTOP") && + signo != signals.GetSignalNumberFromName("SIGINT")) + return true; - if (m_async_count == 0) - return true; // We were not interrupted. The process stopped on its own. - - // Older debugserver stubs (before April 2016) can return two - // stop-reply packets in response to a ^C packet. - // Additionally, all debugservers still return two stop replies if - // the inferior stops due to some other reason before the remote - // stub manages to interrupt it. We need to wait for this - // additional packet to make sure the packet sequence does not get - // skewed. - StringExtractorGDBRemote extra_stop_reply_packet; - uint32_t timeout_usec = 100000; // 100ms - ReadPacket(extra_stop_reply_packet, timeout_usec, false); - - // Interrupting is typically done using SIGSTOP or SIGINT, so if - // the process stops with some other signal, we definitely want to - // stop. - const uint8_t signo = response.GetHexU8(UINT8_MAX); - if (signo != signals.GetSignalNumberFromName("SIGSTOP") && signo != signals.GetSignalNumberFromName("SIGINT")) - return true; - - // We probably only stopped to perform some async processing, so continue after that is done. - // TODO: This is not 100% correct, as the process may have been stopped with SIGINT or SIGSTOP - // that was not caused by us (e.g. raise(SIGINT)). This will normally cause a stop, but if it's - // done concurrently with a async interrupt, that stop will get eaten (llvm.org/pr20231). - return false; + // We probably only stopped to perform some async processing, so continue + // after that is done. + // TODO: This is not 100% correct, as the process may have been stopped with + // SIGINT or SIGSTOP + // that was not caused by us (e.g. raise(SIGINT)). This will normally cause a + // stop, but if it's + // done concurrently with a async interrupt, that stop will get eaten + // (llvm.org/pr20231). + return false; } -void -GDBRemoteClientBase::OnRunPacketSent(bool first) -{ - if (first) - BroadcastEvent(eBroadcastBitRunPacketSent, NULL); +void GDBRemoteClientBase::OnRunPacketSent(bool first) { + if (first) + BroadcastEvent(eBroadcastBitRunPacketSent, NULL); } /////////////////////////////////////// // GDBRemoteClientBase::ContinueLock // /////////////////////////////////////// -GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm) : m_comm(comm), m_acquired(false) -{ - lock(); +GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm) + : m_comm(comm), m_acquired(false) { + lock(); } -GDBRemoteClientBase::ContinueLock::~ContinueLock() -{ - if (m_acquired) - unlock(); +GDBRemoteClientBase::ContinueLock::~ContinueLock() { + if (m_acquired) + unlock(); } -void -GDBRemoteClientBase::ContinueLock::unlock() -{ - lldbassert(m_acquired); - { - std::unique_lock<std::mutex> lock(m_comm.m_mutex); - m_comm.m_is_running = false; - } - m_comm.m_cv.notify_all(); - m_acquired = false; +void GDBRemoteClientBase::ContinueLock::unlock() { + lldbassert(m_acquired); + { + std::unique_lock<std::mutex> lock(m_comm.m_mutex); + m_comm.m_is_running = false; + } + m_comm.m_cv.notify_all(); + m_acquired = false; } GDBRemoteClientBase::ContinueLock::LockResult -GDBRemoteClientBase::ContinueLock::lock() -{ - Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS); +GDBRemoteClientBase::ContinueLock::lock() { + Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS); + if (log) + log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s", + __FUNCTION__, m_comm.m_continue_packet.c_str()); + + lldbassert(!m_acquired); + std::unique_lock<std::mutex> lock(m_comm.m_mutex); + m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; }); + if (m_comm.m_should_stop) { + m_comm.m_should_stop = false; if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s", __FUNCTION__, - m_comm.m_continue_packet.c_str()); - - lldbassert(!m_acquired); - std::unique_lock<std::mutex> lock(m_comm.m_mutex); - m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; }); - if (m_comm.m_should_stop) - { - m_comm.m_should_stop = false; - if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled", __FUNCTION__); - return LockResult::Cancelled; - } - if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) != PacketResult::Success) - return LockResult::Failed; - - lldbassert(!m_comm.m_is_running); - m_comm.m_is_running = true; - m_acquired = true; - return LockResult::Success; + log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled", + __FUNCTION__); + return LockResult::Cancelled; + } + if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) != + PacketResult::Success) + return LockResult::Failed; + + lldbassert(!m_comm.m_is_running); + m_comm.m_is_running = true; + m_acquired = true; + return LockResult::Success; } /////////////////////////////// @@ -366,54 +363,51 @@ GDBRemoteClientBase::ContinueLock::lock() /////////////////////////////// GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt) - : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm), m_acquired(false), m_did_interrupt(false) -{ - SyncWithContinueThread(interrupt); - if (m_acquired) - m_async_lock.lock(); + : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm), + m_acquired(false), m_did_interrupt(false) { + SyncWithContinueThread(interrupt); + if (m_acquired) + m_async_lock.lock(); } -void -GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) -{ - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - std::unique_lock<std::mutex> lock(m_comm.m_mutex); - if (m_comm.m_is_running && !interrupt) - return; // We were asked to avoid interrupting the sender. Lock is not acquired. - - ++m_comm.m_async_count; - if (m_comm.m_is_running) - { - if (m_comm.m_async_count == 1) - { - // The sender has sent the continue packet and we are the first async packet. Let's interrupt it. - const char ctrl_c = '\x03'; - ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL); - if (bytes_written == 0) - { - --m_comm.m_async_count; - if (log) - log->Printf("GDBRemoteClientBase::Lock::Lock failed to send interrupt packet"); - return; - } - if (log) - log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03"); - m_comm.m_interrupt_time = std::chrono::steady_clock::now(); - } - m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; }); - m_did_interrupt = true; +void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + std::unique_lock<std::mutex> lock(m_comm.m_mutex); + if (m_comm.m_is_running && !interrupt) + return; // We were asked to avoid interrupting the sender. Lock is not + // acquired. + + ++m_comm.m_async_count; + if (m_comm.m_is_running) { + if (m_comm.m_async_count == 1) { + // The sender has sent the continue packet and we are the first async + // packet. Let's interrupt it. + const char ctrl_c = '\x03'; + ConnectionStatus status = eConnectionStatusSuccess; + size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL); + if (bytes_written == 0) { + --m_comm.m_async_count; + if (log) + log->Printf("GDBRemoteClientBase::Lock::Lock failed to send " + "interrupt packet"); + return; + } + if (log) + log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03"); + m_comm.m_interrupt_time = std::chrono::steady_clock::now(); } - m_acquired = true; + m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; }); + m_did_interrupt = true; + } + m_acquired = true; } -GDBRemoteClientBase::Lock::~Lock() -{ - if (!m_acquired) - return; - { - std::unique_lock<std::mutex> lock(m_comm.m_mutex); - --m_comm.m_async_count; - } - m_comm.m_cv.notify_one(); +GDBRemoteClientBase::Lock::~Lock() { + if (!m_acquired) + return; + { + std::unique_lock<std::mutex> lock(m_comm.m_mutex); + --m_comm.m_async_count; + } + m_comm.m_cv.notify_one(); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index 684ef3e80d1..f392895405a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -14,147 +14,136 @@ #include <condition_variable> -namespace lldb_private -{ -namespace process_gdb_remote -{ +namespace lldb_private { +namespace process_gdb_remote { -class GDBRemoteClientBase : public GDBRemoteCommunication -{ +class GDBRemoteClientBase : public GDBRemoteCommunication { public: - struct ContinueDelegate - { - virtual ~ContinueDelegate(); - virtual void - HandleAsyncStdout(llvm::StringRef out) = 0; - virtual void - HandleAsyncMisc(llvm::StringRef data) = 0; - virtual void - HandleStopReply() = 0; - - // - /// Processes async structured data. - /// - /// @return - /// true if the data was handled; otherwise, false. - // - virtual bool - HandleAsyncStructuredData(const StructuredData::ObjectSP - &object_sp) = 0; - }; - - GDBRemoteClientBase(const char *comm_name, const char *listener_name); - - bool - SendAsyncSignal(int signo); - - bool - Interrupt(); - - lldb::StateType - SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response); - - PacketResult - SendPacketAndWaitForResponse(const char *payload, size_t len, StringExtractorGDBRemote &response, bool send_async) - { - return SendPacketAndWaitForResponse(llvm::StringRef(payload, len), response, send_async); - } - - PacketResult - SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async); - - bool - SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response); - - class Lock - { - public: - Lock(GDBRemoteClientBase &comm, bool interrupt); - ~Lock(); - - explicit operator bool() { return m_acquired; } - - // Whether we had to interrupt the continue thread to acquire the connection. - bool - DidInterrupt() const - { - return m_did_interrupt; - } - - private: - std::unique_lock<std::recursive_mutex> m_async_lock; - GDBRemoteClientBase &m_comm; - bool m_acquired; - bool m_did_interrupt; - - void - SyncWithContinueThread(bool interrupt); - }; + struct ContinueDelegate { + virtual ~ContinueDelegate(); + virtual void HandleAsyncStdout(llvm::StringRef out) = 0; + virtual void HandleAsyncMisc(llvm::StringRef data) = 0; + virtual void HandleStopReply() = 0; + + // + /// Processes async structured data. + /// + /// @return + /// true if the data was handled; otherwise, false. + // + virtual bool + HandleAsyncStructuredData(const StructuredData::ObjectSP &object_sp) = 0; + }; + + GDBRemoteClientBase(const char *comm_name, const char *listener_name); + + bool SendAsyncSignal(int signo); + + bool Interrupt(); + + lldb::StateType SendContinuePacketAndWaitForResponse( + ContinueDelegate &delegate, const UnixSignals &signals, + llvm::StringRef payload, StringExtractorGDBRemote &response); + + PacketResult SendPacketAndWaitForResponse(const char *payload, size_t len, + StringExtractorGDBRemote &response, + bool send_async) { + return SendPacketAndWaitForResponse(llvm::StringRef(payload, len), response, + send_async); + } + + PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, + StringExtractorGDBRemote &response, + bool send_async); + + bool SendvContPacket(llvm::StringRef payload, + StringExtractorGDBRemote &response); + + class Lock { + public: + Lock(GDBRemoteClientBase &comm, bool interrupt); + ~Lock(); + + explicit operator bool() { return m_acquired; } + + // Whether we had to interrupt the continue thread to acquire the + // connection. + bool DidInterrupt() const { return m_did_interrupt; } + + private: + std::unique_lock<std::recursive_mutex> m_async_lock; + GDBRemoteClientBase &m_comm; + bool m_acquired; + bool m_did_interrupt; + + void SyncWithContinueThread(bool interrupt); + }; protected: - PacketResult - SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response); + PacketResult + SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, + StringExtractorGDBRemote &response); - virtual void - OnRunPacketSent(bool first); + virtual void OnRunPacketSent(bool first); private: - // Variables handling synchronization between the Continue thread and any other threads - // wishing to send packets over the connection. Either the continue thread has control over - // the connection (m_is_running == true) or the connection is free for an arbitrary number of - // other senders to take which indicate their interest by incrementing m_async_count. - // Semantics of individual states: - // - m_continue_packet == false, m_async_count == 0: connection is free - // - m_continue_packet == true, m_async_count == 0: only continue thread is present - // - m_continue_packet == true, m_async_count > 0: continue thread has control, async threads - // should interrupt it and wait for it to set m_continue_packet to false - // - m_continue_packet == false, m_async_count > 0: async threads have control, continue - // thread needs to wait for them to finish (m_async_count goes down to 0). - std::mutex m_mutex; - std::condition_variable m_cv; - // Packet with which to resume after an async interrupt. Can be changed by an async thread - // e.g. to inject a signal. - std::string m_continue_packet; - // When was the interrupt packet sent. Used to make sure we time out if the stub does not - // respond to interrupt requests. - std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time; - uint32_t m_async_count; - bool m_is_running; - bool m_should_stop; // Whether we should resume after a stop. - // end of continue thread synchronization block - - // This handles the synchronization between individual async threads. For now they just use a - // simple mutex. - std::recursive_mutex m_async_mutex; - - bool - ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response); - - class ContinueLock - { - public: - enum class LockResult - { - Success, - Cancelled, - Failed - }; - - explicit ContinueLock(GDBRemoteClientBase &comm); - ~ContinueLock(); - explicit operator bool() { return m_acquired; } - - LockResult - lock(); - - void - unlock(); - - private: - GDBRemoteClientBase &m_comm; - bool m_acquired; - }; + // Variables handling synchronization between the Continue thread and any + // other threads + // wishing to send packets over the connection. Either the continue thread has + // control over + // the connection (m_is_running == true) or the connection is free for an + // arbitrary number of + // other senders to take which indicate their interest by incrementing + // m_async_count. + // Semantics of individual states: + // - m_continue_packet == false, m_async_count == 0: connection is free + // - m_continue_packet == true, m_async_count == 0: only continue thread is + // present + // - m_continue_packet == true, m_async_count > 0: continue thread has + // control, async threads + // should interrupt it and wait for it to set m_continue_packet to false + // - m_continue_packet == false, m_async_count > 0: async threads have + // control, continue + // thread needs to wait for them to finish (m_async_count goes down to 0). + std::mutex m_mutex; + std::condition_variable m_cv; + // Packet with which to resume after an async interrupt. Can be changed by an + // async thread + // e.g. to inject a signal. + std::string m_continue_packet; + // When was the interrupt packet sent. Used to make sure we time out if the + // stub does not + // respond to interrupt requests. + std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time; + uint32_t m_async_count; + bool m_is_running; + bool m_should_stop; // Whether we should resume after a stop. + // end of continue thread synchronization block + + // This handles the synchronization between individual async threads. For now + // they just use a + // simple mutex. + std::recursive_mutex m_async_mutex; + + bool ShouldStop(const UnixSignals &signals, + StringExtractorGDBRemote &response); + + class ContinueLock { + public: + enum class LockResult { Success, Cancelled, Failed }; + + explicit ContinueLock(GDBRemoteClientBase &comm); + ~ContinueLock(); + explicit operator bool() { return m_acquired; } + + LockResult lock(); + + void unlock(); + + private: + GDBRemoteClientBase &m_comm; + bool m_acquired; + }; }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index f3892d2627d..ef3e75bbf09 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "GDBRemoteCommunication.h" // C Includes @@ -39,16 +38,16 @@ #include "ProcessGDBRemoteLog.h" #if defined(__APPLE__) -# define DEBUGSERVER_BASENAME "debugserver" +#define DEBUGSERVER_BASENAME "debugserver" #else -# define DEBUGSERVER_BASENAME "lldb-server" +#define DEBUGSERVER_BASENAME "lldb-server" #endif -#if defined (HAVE_LIBCOMPRESSION) +#if defined(HAVE_LIBCOMPRESSION) #include <compression.h> #endif -#if defined (HAVE_LIBZ) +#if defined(HAVE_LIBZ) #include <zlib.h> #endif @@ -56,1434 +55,1328 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -GDBRemoteCommunication::History::History (uint32_t size) : - m_packets(), - m_curr_idx (0), - m_total_packet_count (0), - m_dumped_to_log (false) -{ - m_packets.resize(size); +GDBRemoteCommunication::History::History(uint32_t size) + : m_packets(), m_curr_idx(0), m_total_packet_count(0), + m_dumped_to_log(false) { + m_packets.resize(size); } -GDBRemoteCommunication::History::~History () -{ +GDBRemoteCommunication::History::~History() {} + +void GDBRemoteCommunication::History::AddPacket(char packet_char, + PacketType type, + uint32_t bytes_transmitted) { + const size_t size = m_packets.size(); + if (size > 0) { + const uint32_t idx = GetNextIndex(); + m_packets[idx].packet.assign(1, packet_char); + m_packets[idx].type = type; + m_packets[idx].bytes_transmitted = bytes_transmitted; + m_packets[idx].packet_idx = m_total_packet_count; + m_packets[idx].tid = Host::GetCurrentThreadID(); + } } -void -GDBRemoteCommunication::History::AddPacket (char packet_char, - PacketType type, - uint32_t bytes_transmitted) -{ - const size_t size = m_packets.size(); - if (size > 0) - { - const uint32_t idx = GetNextIndex(); - m_packets[idx].packet.assign (1, packet_char); - m_packets[idx].type = type; - m_packets[idx].bytes_transmitted = bytes_transmitted; - m_packets[idx].packet_idx = m_total_packet_count; - m_packets[idx].tid = Host::GetCurrentThreadID(); - } +void GDBRemoteCommunication::History::AddPacket(const std::string &src, + uint32_t src_len, + PacketType type, + uint32_t bytes_transmitted) { + const size_t size = m_packets.size(); + if (size > 0) { + const uint32_t idx = GetNextIndex(); + m_packets[idx].packet.assign(src, 0, src_len); + m_packets[idx].type = type; + m_packets[idx].bytes_transmitted = bytes_transmitted; + m_packets[idx].packet_idx = m_total_packet_count; + m_packets[idx].tid = Host::GetCurrentThreadID(); + } } -void -GDBRemoteCommunication::History::AddPacket (const std::string &src, - uint32_t src_len, - PacketType type, - uint32_t bytes_transmitted) -{ - const size_t size = m_packets.size(); - if (size > 0) - { - const uint32_t idx = GetNextIndex(); - m_packets[idx].packet.assign (src, 0, src_len); - m_packets[idx].type = type; - m_packets[idx].bytes_transmitted = bytes_transmitted; - m_packets[idx].packet_idx = m_total_packet_count; - m_packets[idx].tid = Host::GetCurrentThreadID(); - } +void GDBRemoteCommunication::History::Dump(Stream &strm) const { + const uint32_t size = GetNumPacketsInHistory(); + const uint32_t first_idx = GetFirstSavedPacketIndex(); + const uint32_t stop_idx = m_curr_idx + size; + for (uint32_t i = first_idx; i < stop_idx; ++i) { + const uint32_t idx = NormalizeIndex(i); + const Entry &entry = m_packets[idx]; + if (entry.type == ePacketTypeInvalid || entry.packet.empty()) + break; + strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", + entry.packet_idx, entry.tid, entry.bytes_transmitted, + (entry.type == ePacketTypeSend) ? "send" : "read", + entry.packet.c_str()); + } } -void -GDBRemoteCommunication::History::Dump (Stream &strm) const -{ - const uint32_t size = GetNumPacketsInHistory (); - const uint32_t first_idx = GetFirstSavedPacketIndex (); +void GDBRemoteCommunication::History::Dump(Log *log) const { + if (log && !m_dumped_to_log) { + m_dumped_to_log = true; + const uint32_t size = GetNumPacketsInHistory(); + const uint32_t first_idx = GetFirstSavedPacketIndex(); const uint32_t stop_idx = m_curr_idx + size; - for (uint32_t i = first_idx; i < stop_idx; ++i) - { - const uint32_t idx = NormalizeIndex (i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.empty()) - break; - strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", - entry.packet_idx, - entry.tid, - entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.c_str()); - } -} - -void -GDBRemoteCommunication::History::Dump (Log *log) const -{ - if (log && !m_dumped_to_log) - { - m_dumped_to_log = true; - const uint32_t size = GetNumPacketsInHistory (); - const uint32_t first_idx = GetFirstSavedPacketIndex (); - const uint32_t stop_idx = m_curr_idx + size; - for (uint32_t i = first_idx; i < stop_idx; ++i) - { - const uint32_t idx = NormalizeIndex (i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.empty()) - break; - log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", - entry.packet_idx, - entry.tid, - entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.c_str()); - } + for (uint32_t i = first_idx; i < stop_idx; ++i) { + const uint32_t idx = NormalizeIndex(i); + const Entry &entry = m_packets[idx]; + if (entry.type == ePacketTypeInvalid || entry.packet.empty()) + break; + log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", + entry.packet_idx, entry.tid, entry.bytes_transmitted, + (entry.type == ePacketTypeSend) ? "send" : "read", + entry.packet.c_str()); } + } } //---------------------------------------------------------------------- // GDBRemoteCommunication constructor //---------------------------------------------------------------------- -GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) +GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, + const char *listener_name) : Communication(comm_name), #ifdef LLDB_CONFIGURATION_DEBUG m_packet_timeout(1000), #else m_packet_timeout(1), #endif - m_echo_number(0), - m_supports_qEcho(eLazyBoolCalculate), - m_history(512), - m_send_acks(true), - m_compression_type(CompressionType::None), - m_listen_url() -{ + m_echo_number(0), m_supports_qEcho(eLazyBoolCalculate), m_history(512), + m_send_acks(true), m_compression_type(CompressionType::None), + m_listen_url() { } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -GDBRemoteCommunication::~GDBRemoteCommunication() -{ - if (IsConnected()) - { - Disconnect(); - } - - // Stop the communications read thread which is used to parse all - // incoming packets. This function will block until the read - // thread returns. - if (m_read_thread_enabled) - StopReadThread(); +GDBRemoteCommunication::~GDBRemoteCommunication() { + if (IsConnected()) { + Disconnect(); + } + + // Stop the communications read thread which is used to parse all + // incoming packets. This function will block until the read + // thread returns. + if (m_read_thread_enabled) + StopReadThread(); } -char -GDBRemoteCommunication::CalculcateChecksum (llvm::StringRef payload) -{ - int checksum = 0; +char GDBRemoteCommunication::CalculcateChecksum(llvm::StringRef payload) { + int checksum = 0; - for (char c : payload) - checksum += c; + for (char c : payload) + checksum += c; - return checksum & 255; + return checksum & 255; } -size_t -GDBRemoteCommunication::SendAck () -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); - ConnectionStatus status = eConnectionStatusSuccess; - char ch = '+'; - const size_t bytes_written = Write (&ch, 1, status, NULL); - if (log) - log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); - return bytes_written; +size_t GDBRemoteCommunication::SendAck() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + ConnectionStatus status = eConnectionStatusSuccess; + char ch = '+'; + const size_t bytes_written = Write(&ch, 1, status, NULL); + if (log) + log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written); + return bytes_written; } -size_t -GDBRemoteCommunication::SendNack () -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); - ConnectionStatus status = eConnectionStatusSuccess; - char ch = '-'; - const size_t bytes_written = Write (&ch, 1, status, NULL); - if (log) - log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); - return bytes_written; +size_t GDBRemoteCommunication::SendNack() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + ConnectionStatus status = eConnectionStatusSuccess; + char ch = '-'; + const size_t bytes_written = Write(&ch, 1, status, NULL); + if (log) + log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written); + return bytes_written; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::SendPacketNoLock (llvm::StringRef payload) -{ - if (IsConnected()) - { - StreamString packet(0, 4, eByteOrderBig); - - packet.PutChar('$'); - packet.Write (payload.data(), payload.size()); - packet.PutChar('#'); - packet.PutHex8(CalculcateChecksum (payload)); - - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); - ConnectionStatus status = eConnectionStatusSuccess; - const char *packet_data = packet.GetData(); - const size_t packet_length = packet.GetSize(); - size_t bytes_written = Write (packet_data, packet_length, status, NULL); - if (log) - { - size_t binary_start_offset = 0; - if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0) - { - const char *first_comma = strchr(packet_data, ','); - if (first_comma) - { - const char *second_comma = strchr(first_comma + 1, ','); - if (second_comma) - binary_start_offset = second_comma - packet_data + 1; - } - } +GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) { + if (IsConnected()) { + StreamString packet(0, 4, eByteOrderBig); - // If logging was just enabled and we have history, then dump out what - // we have to the log so we get the historical context. The Dump() call that - // logs all of the packet will set a boolean so that we don't dump this more - // than once - if (!m_history.DidDumpToLog ()) - m_history.Dump (log); - - if (binary_start_offset) - { - StreamString strm; - // Print non binary data header - strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data); - const uint8_t *p; - // Print binary data exactly as sent - for (p = (const uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p) - strm.Printf("\\x%2.2x", *p); - // Print the checksum - strm.Printf("%*s", (int)3, p); - log->PutCString(strm.GetString().c_str()); - } - else - log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data); - } + packet.PutChar('$'); + packet.Write(payload.data(), payload.size()); + packet.PutChar('#'); + packet.PutHex8(CalculcateChecksum(payload)); - m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written); + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + ConnectionStatus status = eConnectionStatusSuccess; + const char *packet_data = packet.GetData(); + const size_t packet_length = packet.GetSize(); + size_t bytes_written = Write(packet_data, packet_length, status, NULL); + if (log) { + size_t binary_start_offset = 0; + if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == + 0) { + const char *first_comma = strchr(packet_data, ','); + if (first_comma) { + const char *second_comma = strchr(first_comma + 1, ','); + if (second_comma) + binary_start_offset = second_comma - packet_data + 1; + } + } + + // If logging was just enabled and we have history, then dump out what + // we have to the log so we get the historical context. The Dump() call + // that + // logs all of the packet will set a boolean so that we don't dump this + // more + // than once + if (!m_history.DidDumpToLog()) + m_history.Dump(log); + + if (binary_start_offset) { + StreamString strm; + // Print non binary data header + strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, + (int)binary_start_offset, packet_data); + const uint8_t *p; + // Print binary data exactly as sent + for (p = (const uint8_t *)packet_data + binary_start_offset; *p != '#'; + ++p) + strm.Printf("\\x%2.2x", *p); + // Print the checksum + strm.Printf("%*s", (int)3, p); + log->PutCString(strm.GetString().c_str()); + } else + log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, + (int)packet_length, packet_data); + } + m_history.AddPacket(packet.GetString(), packet_length, + History::ePacketTypeSend, bytes_written); - if (bytes_written == packet_length) - { - if (GetSendAcks ()) - return GetAck (); - else - return PacketResult::Success; - } - else - { - if (log) - log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data); - } + if (bytes_written == packet_length) { + if (GetSendAcks()) + return GetAck(); + else + return PacketResult::Success; + } else { + if (log) + log->Printf("error: failed to send packet: %.*s", (int)packet_length, + packet_data); } - return PacketResult::ErrorSendFailed; + } + return PacketResult::ErrorSendFailed; } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::GetAck () -{ - StringExtractorGDBRemote packet; - PacketResult result = ReadPacket (packet, GetPacketTimeoutInMicroSeconds (), false); - if (result == PacketResult::Success) - { - if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck) - return PacketResult::Success; - else - return PacketResult::ErrorSendAck; - } - return result; +GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() { + StringExtractorGDBRemote packet; + PacketResult result = + ReadPacket(packet, GetPacketTimeoutInMicroSeconds(), false); + if (result == PacketResult::Success) { + if (packet.GetResponseType() == + StringExtractorGDBRemote::ResponseType::eAck) + return PacketResult::Success; + else + return PacketResult::ErrorSendAck; + } + return result; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout) -{ - if (m_read_thread_enabled) - return PopPacketFromQueue (response, timeout_usec); - else - return WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec, sync_on_timeout); +GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response, + uint32_t timeout_usec, + bool sync_on_timeout) { + if (m_read_thread_enabled) + return PopPacketFromQueue(response, timeout_usec); + else + return WaitForPacketWithTimeoutMicroSecondsNoLock(response, timeout_usec, + sync_on_timeout); } - // This function is called when a packet is requested. // A whole packet is popped from the packet queue and returned to the caller. // Packets are placed into this queue from the communication read thread. // See GDBRemoteCommunication::AppendBytesToCache. GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec) -{ - auto until = std::chrono::system_clock::now() + std::chrono::microseconds(timeout_usec); +GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response, + uint32_t timeout_usec) { + auto until = std::chrono::system_clock::now() + + std::chrono::microseconds(timeout_usec); - while (true) + while (true) { + // scope for the mutex { - // scope for the mutex - { - // lock down the packet queue - std::unique_lock<std::mutex> lock(m_packet_queue_mutex); - - // Wait on condition variable. - if (m_packet_queue.size() == 0) - { - std::cv_status result = m_condition_queue_not_empty.wait_until(lock, until); - if (result == std::cv_status::timeout) - break; - } - - if (m_packet_queue.size() > 0) - { - // get the front element of the queue - response = m_packet_queue.front(); + // lock down the packet queue + std::unique_lock<std::mutex> lock(m_packet_queue_mutex); - // remove the front element - m_packet_queue.pop(); + // Wait on condition variable. + if (m_packet_queue.size() == 0) { + std::cv_status result = + m_condition_queue_not_empty.wait_until(lock, until); + if (result == std::cv_status::timeout) + break; + } - // we got a packet - return PacketResult::Success; - } - } + if (m_packet_queue.size() > 0) { + // get the front element of the queue + response = m_packet_queue.front(); - // Disconnected - if (!IsConnected()) - return PacketResult::ErrorDisconnected; + // remove the front element + m_packet_queue.pop(); - // Loop while not timed out + // we got a packet + return PacketResult::Success; + } } - return PacketResult::ErrorReplyTimeout; -} + // Disconnected + if (!IsConnected()) + return PacketResult::ErrorDisconnected; + // Loop while not timed out + } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec, bool sync_on_timeout) -{ - uint8_t buffer[8192]; - Error error; + return PacketResult::ErrorReplyTimeout; +} - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); +GDBRemoteCommunication::PacketResult +GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock( + StringExtractorGDBRemote &packet, uint32_t timeout_usec, + bool sync_on_timeout) { + uint8_t buffer[8192]; + Error error; + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS | + GDBR_LOG_VERBOSE)); + + // Check for a packet from our cache first without trying any reading... + if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid) + return PacketResult::Success; + + bool timed_out = false; + bool disconnected = false; + while (IsConnected() && !timed_out) { + lldb::ConnectionStatus status = eConnectionStatusNoConnection; + size_t bytes_read = + Read(buffer, sizeof(buffer), timeout_usec, status, &error); - // Check for a packet from our cache first without trying any reading... - if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid) + if (log) + log->Printf("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, " + "status = %s, error = %s) => bytes_read = %" PRIu64, + LLVM_PRETTY_FUNCTION, timeout_usec, + Communication::ConnectionStatusAsCString(status), + error.AsCString(), (uint64_t)bytes_read); + + if (bytes_read > 0) { + if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid) return PacketResult::Success; - - bool timed_out = false; - bool disconnected = false; - while (IsConnected() && !timed_out) - { - lldb::ConnectionStatus status = eConnectionStatusNoConnection; - size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); - - if (log) - log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, - LLVM_PRETTY_FUNCTION, - timeout_usec, - Communication::ConnectionStatusAsCString (status), - error.AsCString(), - (uint64_t)bytes_read); - - if (bytes_read > 0) - { - if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid) - return PacketResult::Success; - } - else - { - switch (status) - { - case eConnectionStatusTimedOut: - case eConnectionStatusInterrupted: - if (sync_on_timeout) - { - //------------------------------------------------------------------ - /// Sync the remote GDB server and make sure we get a response that - /// corresponds to what we send. - /// - /// Sends a "qEcho" packet and makes sure it gets the exact packet - /// echoed back. If the qEcho packet isn't supported, we send a qC - /// packet and make sure we get a valid thread ID back. We use the - /// "qC" packet since its response if very unique: is responds with - /// "QC%x" where %x is the thread ID of the current thread. This - /// makes the response unique enough from other packet responses to - /// ensure we are back on track. - /// - /// This packet is needed after we time out sending a packet so we - /// can ensure that we are getting the response for the packet we - /// are sending. There are no sequence IDs in the GDB remote - /// protocol (there used to be, but they are not supported anymore) - /// so if you timeout sending packet "abc", you might then send - /// packet "cde" and get the response for the previous "abc" packet. - /// Many responses are "OK" or "" (unsupported) or "EXX" (error) so - /// many responses for packets can look like responses for other - /// packets. So if we timeout, we need to ensure that we can get - /// back on track. If we can't get back on track, we must - /// disconnect. - //------------------------------------------------------------------ - bool sync_success = false; - bool got_actual_response = false; - // We timed out, we need to sync back up with the - char echo_packet[32]; - int echo_packet_len = 0; - RegularExpression response_regex; - - if (m_supports_qEcho == eLazyBoolYes) - { - echo_packet_len = ::snprintf (echo_packet, sizeof(echo_packet), "qEcho:%u", ++m_echo_number); - std::string regex_str = "^"; - regex_str += echo_packet; - regex_str += "$"; - response_regex.Compile(regex_str.c_str()); - } - else - { - echo_packet_len = ::snprintf (echo_packet, sizeof(echo_packet), "qC"); - response_regex.Compile("^QC[0-9A-Fa-f]+$"); - } - - PacketResult echo_packet_result = SendPacketNoLock (llvm::StringRef(echo_packet, echo_packet_len)); - if (echo_packet_result == PacketResult::Success) - { - const uint32_t max_retries = 3; - uint32_t successful_responses = 0; - for (uint32_t i=0; i<max_retries; ++i) - { - StringExtractorGDBRemote echo_response; - echo_packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (echo_response, timeout_usec, false); - if (echo_packet_result == PacketResult::Success) - { - ++successful_responses; - if (response_regex.Execute(echo_response.GetStringRef().c_str())) - { - sync_success = true; - break; - } - else if (successful_responses == 1) - { - // We got something else back as the first successful response, it probably is - // the response to the packet we actually wanted, so copy it over if this - // is the first success and continue to try to get the qEcho response - packet = echo_response; - got_actual_response = true; - } - } - else if (echo_packet_result == PacketResult::ErrorReplyTimeout) - continue; // Packet timed out, continue waiting for a response - else - break; // Something else went wrong getting the packet back, we failed and are done trying - } - } - - // We weren't able to sync back up with the server, we must abort otherwise - // all responses might not be from the right packets... - if (sync_success) - { - // We timed out, but were able to recover - if (got_actual_response) - { - // We initially timed out, but we did get a response that came in before the successful - // reply to our qEcho packet, so lets say everything is fine... - return PacketResult::Success; - } - } - else - { - disconnected = true; - Disconnect(); - } + } else { + switch (status) { + case eConnectionStatusTimedOut: + case eConnectionStatusInterrupted: + if (sync_on_timeout) { + //------------------------------------------------------------------ + /// Sync the remote GDB server and make sure we get a response that + /// corresponds to what we send. + /// + /// Sends a "qEcho" packet and makes sure it gets the exact packet + /// echoed back. If the qEcho packet isn't supported, we send a qC + /// packet and make sure we get a valid thread ID back. We use the + /// "qC" packet since its response if very unique: is responds with + /// "QC%x" where %x is the thread ID of the current thread. This + /// makes the response unique enough from other packet responses to + /// ensure we are back on track. + /// + /// This packet is needed after we time out sending a packet so we + /// can ensure that we are getting the response for the packet we + /// are sending. There are no sequence IDs in the GDB remote + /// protocol (there used to be, but they are not supported anymore) + /// so if you timeout sending packet "abc", you might then send + /// packet "cde" and get the response for the previous "abc" packet. + /// Many responses are "OK" or "" (unsupported) or "EXX" (error) so + /// many responses for packets can look like responses for other + /// packets. So if we timeout, we need to ensure that we can get + /// back on track. If we can't get back on track, we must + /// disconnect. + //------------------------------------------------------------------ + bool sync_success = false; + bool got_actual_response = false; + // We timed out, we need to sync back up with the + char echo_packet[32]; + int echo_packet_len = 0; + RegularExpression response_regex; + + if (m_supports_qEcho == eLazyBoolYes) { + echo_packet_len = ::snprintf(echo_packet, sizeof(echo_packet), + "qEcho:%u", ++m_echo_number); + std::string regex_str = "^"; + regex_str += echo_packet; + regex_str += "$"; + response_regex.Compile(regex_str.c_str()); + } else { + echo_packet_len = + ::snprintf(echo_packet, sizeof(echo_packet), "qC"); + response_regex.Compile("^QC[0-9A-Fa-f]+$"); + } + + PacketResult echo_packet_result = + SendPacketNoLock(llvm::StringRef(echo_packet, echo_packet_len)); + if (echo_packet_result == PacketResult::Success) { + const uint32_t max_retries = 3; + uint32_t successful_responses = 0; + for (uint32_t i = 0; i < max_retries; ++i) { + StringExtractorGDBRemote echo_response; + echo_packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock( + echo_response, timeout_usec, false); + if (echo_packet_result == PacketResult::Success) { + ++successful_responses; + if (response_regex.Execute( + echo_response.GetStringRef().c_str())) { + sync_success = true; + break; + } else if (successful_responses == 1) { + // We got something else back as the first successful + // response, it probably is + // the response to the packet we actually wanted, so copy it + // over if this + // is the first success and continue to try to get the qEcho + // response + packet = echo_response; + got_actual_response = true; } - timed_out = true; - break; - case eConnectionStatusSuccess: - //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); - break; - - case eConnectionStatusEndOfFile: - case eConnectionStatusNoConnection: - case eConnectionStatusLostConnection: - case eConnectionStatusError: - disconnected = true; - Disconnect(); - break; + } else if (echo_packet_result == PacketResult::ErrorReplyTimeout) + continue; // Packet timed out, continue waiting for a response + else + break; // Something else went wrong getting the packet back, we + // failed and are done trying } + } + + // We weren't able to sync back up with the server, we must abort + // otherwise + // all responses might not be from the right packets... + if (sync_success) { + // We timed out, but were able to recover + if (got_actual_response) { + // We initially timed out, but we did get a response that came in + // before the successful + // reply to our qEcho packet, so lets say everything is fine... + return PacketResult::Success; + } + } else { + disconnected = true; + Disconnect(); + } } + timed_out = true; + break; + case eConnectionStatusSuccess: + // printf ("status = success but error = %s\n", + // error.AsCString("<invalid>")); + break; + + case eConnectionStatusEndOfFile: + case eConnectionStatusNoConnection: + case eConnectionStatusLostConnection: + case eConnectionStatusError: + disconnected = true; + Disconnect(); + break; + } } - packet.Clear (); - if (disconnected) - return PacketResult::ErrorDisconnected; - if (timed_out) - return PacketResult::ErrorReplyTimeout; - else - return PacketResult::ErrorReplyFailed; + } + packet.Clear(); + if (disconnected) + return PacketResult::ErrorDisconnected; + if (timed_out) + return PacketResult::ErrorReplyTimeout; + else + return PacketResult::ErrorReplyFailed; } -bool -GDBRemoteCommunication::DecompressPacket () -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); - - if (!CompressionIsEnabled()) - return true; +bool GDBRemoteCommunication::DecompressPacket() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); - size_t pkt_size = m_bytes.size(); - - // Smallest possible compressed packet is $N#00 - an uncompressed empty reply, most commonly indicating - // an unsupported packet. Anything less than 5 characters, it's definitely not a compressed packet. - if (pkt_size < 5) - return true; - - if (m_bytes[0] != '$' && m_bytes[0] != '%') - return true; - if (m_bytes[1] != 'C' && m_bytes[1] != 'N') - return true; + if (!CompressionIsEnabled()) + return true; - size_t hash_mark_idx = m_bytes.find ('#'); - if (hash_mark_idx == std::string::npos) - return true; - if (hash_mark_idx + 2 >= m_bytes.size()) - return true; + size_t pkt_size = m_bytes.size(); - if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2])) - return true; + // Smallest possible compressed packet is $N#00 - an uncompressed empty reply, + // most commonly indicating + // an unsupported packet. Anything less than 5 characters, it's definitely + // not a compressed packet. + if (pkt_size < 5) + return true; - size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars - size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet - size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters + if (m_bytes[0] != '$' && m_bytes[0] != '%') + return true; + if (m_bytes[1] != 'C' && m_bytes[1] != 'N') + return true; - // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets. - // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed - // version of, leaving the rest of m_bytes unmodified. - size_t size_of_first_packet = hash_mark_idx + 3; + size_t hash_mark_idx = m_bytes.find('#'); + if (hash_mark_idx == std::string::npos) + return true; + if (hash_mark_idx + 2 >= m_bytes.size()) + return true; - // Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload, - // then a : and then the compressed data. e.g. $C1024:<binary>#00 - // Update content_start and content_length to only include the <binary> part of the packet. + if (!::isxdigit(m_bytes[hash_mark_idx + 1]) || + !::isxdigit(m_bytes[hash_mark_idx + 2])) + return true; - uint64_t decompressed_bufsize = ULONG_MAX; - if (m_bytes[1] == 'C') - { - size_t i = content_start; - while (i < hash_mark_idx && isdigit(m_bytes[i])) - i++; - if (i < hash_mark_idx && m_bytes[i] == ':') - { - i++; - content_start = i; - content_length = hash_mark_idx - content_start; - std::string bufsize_str (m_bytes.data() + 2, i - 2 - 1); - errno = 0; - decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10); - if (errno != 0 || decompressed_bufsize == ULONG_MAX) - { - m_bytes.erase (0, size_of_first_packet); - return false; - } - } + size_t content_length = + pkt_size - + 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars + size_t content_start = 2; // The first character of the + // compressed/not-compressed text of the packet + size_t checksum_idx = + hash_mark_idx + + 1; // The first character of the two hex checksum characters + + // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain + // multiple packets. + // size_of_first_packet is the size of the initial packet which we'll replace + // with the decompressed + // version of, leaving the rest of m_bytes unmodified. + size_t size_of_first_packet = hash_mark_idx + 3; + + // Compressed packets ("$C") start with a base10 number which is the size of + // the uncompressed payload, + // then a : and then the compressed data. e.g. $C1024:<binary>#00 + // Update content_start and content_length to only include the <binary> part + // of the packet. + + uint64_t decompressed_bufsize = ULONG_MAX; + if (m_bytes[1] == 'C') { + size_t i = content_start; + while (i < hash_mark_idx && isdigit(m_bytes[i])) + i++; + if (i < hash_mark_idx && m_bytes[i] == ':') { + i++; + content_start = i; + content_length = hash_mark_idx - content_start; + std::string bufsize_str(m_bytes.data() + 2, i - 2 - 1); + errno = 0; + decompressed_bufsize = ::strtoul(bufsize_str.c_str(), NULL, 10); + if (errno != 0 || decompressed_bufsize == ULONG_MAX) { + m_bytes.erase(0, size_of_first_packet); + return false; + } } - - if (GetSendAcks ()) - { - char packet_checksum_cstr[3]; - packet_checksum_cstr[0] = m_bytes[checksum_idx]; - packet_checksum_cstr[1] = m_bytes[checksum_idx + 1]; - packet_checksum_cstr[2] = '\0'; - long packet_checksum = strtol (packet_checksum_cstr, NULL, 16); - - long actual_checksum = CalculcateChecksum (llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1)); - bool success = packet_checksum == actual_checksum; - if (!success) - { - if (log) - log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", - (int)(pkt_size), - m_bytes.c_str(), - (uint8_t)packet_checksum, - (uint8_t)actual_checksum); - } - // Send the ack or nack if needed - if (!success) - { - SendNack(); - m_bytes.erase (0, size_of_first_packet); - return false; - } - else - { - SendAck(); - } + } + + if (GetSendAcks()) { + char packet_checksum_cstr[3]; + packet_checksum_cstr[0] = m_bytes[checksum_idx]; + packet_checksum_cstr[1] = m_bytes[checksum_idx + 1]; + packet_checksum_cstr[2] = '\0'; + long packet_checksum = strtol(packet_checksum_cstr, NULL, 16); + + long actual_checksum = CalculcateChecksum( + llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1)); + bool success = packet_checksum == actual_checksum; + if (!success) { + if (log) + log->Printf( + "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", + (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum, + (uint8_t)actual_checksum); } - - if (m_bytes[1] == 'N') - { - // This packet was not compressed -- delete the 'N' character at the - // start and the packet may be processed as-is. - m_bytes.erase(1, 1); - return true; + // Send the ack or nack if needed + if (!success) { + SendNack(); + m_bytes.erase(0, size_of_first_packet); + return false; + } else { + SendAck(); } + } - // Reverse the gdb-remote binary escaping that was done to the compressed text to - // guard characters like '$', '#', '}', etc. - std::vector<uint8_t> unescaped_content; - unescaped_content.reserve (content_length); - size_t i = content_start; - while (i < hash_mark_idx) - { - if (m_bytes[i] == '}') - { - i++; - unescaped_content.push_back (m_bytes[i] ^ 0x20); - } - else - { - unescaped_content.push_back (m_bytes[i]); - } - i++; + if (m_bytes[1] == 'N') { + // This packet was not compressed -- delete the 'N' character at the + // start and the packet may be processed as-is. + m_bytes.erase(1, 1); + return true; + } + + // Reverse the gdb-remote binary escaping that was done to the compressed text + // to + // guard characters like '$', '#', '}', etc. + std::vector<uint8_t> unescaped_content; + unescaped_content.reserve(content_length); + size_t i = content_start; + while (i < hash_mark_idx) { + if (m_bytes[i] == '}') { + i++; + unescaped_content.push_back(m_bytes[i] ^ 0x20); + } else { + unescaped_content.push_back(m_bytes[i]); } + i++; + } - uint8_t *decompressed_buffer = nullptr; - size_t decompressed_bytes = 0; - - if (decompressed_bufsize != ULONG_MAX) - { - decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1); - if (decompressed_buffer == nullptr) - { - m_bytes.erase (0, size_of_first_packet); - return false; - } + uint8_t *decompressed_buffer = nullptr; + size_t decompressed_bytes = 0; + if (decompressed_bufsize != ULONG_MAX) { + decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize + 1); + if (decompressed_buffer == nullptr) { + m_bytes.erase(0, size_of_first_packet); + return false; } - -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so check that compression_decode_buffer() is available - if (compression_decode_buffer != NULL && - (m_compression_type == CompressionType::ZlibDeflate - || m_compression_type == CompressionType::LZFSE - || m_compression_type == CompressionType::LZ4)) - { - compression_algorithm compression_type; - if (m_compression_type == CompressionType::ZlibDeflate) - compression_type = COMPRESSION_ZLIB; - else if (m_compression_type == CompressionType::LZFSE) - compression_type = COMPRESSION_LZFSE; - else if (m_compression_type == CompressionType::LZ4) - compression_type = COMPRESSION_LZ4_RAW; - else if (m_compression_type == CompressionType::LZMA) - compression_type = COMPRESSION_LZMA; - - - // If we have the expected size of the decompressed payload, we can allocate - // the right-sized buffer and do it. If we don't have that information, we'll - // need to try decoding into a big buffer and if the buffer wasn't big enough, - // increase it and try again. - - if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) - { - decompressed_bytes = compression_decode_buffer (decompressed_buffer, decompressed_bufsize + 10 , - (uint8_t*) unescaped_content.data(), - unescaped_content.size(), - NULL, - compression_type); - } + } + +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so check that compression_decode_buffer() is + // available + if (compression_decode_buffer != NULL && + (m_compression_type == CompressionType::ZlibDeflate || + m_compression_type == CompressionType::LZFSE || + m_compression_type == CompressionType::LZ4)) { + compression_algorithm compression_type; + if (m_compression_type == CompressionType::ZlibDeflate) + compression_type = COMPRESSION_ZLIB; + else if (m_compression_type == CompressionType::LZFSE) + compression_type = COMPRESSION_LZFSE; + else if (m_compression_type == CompressionType::LZ4) + compression_type = COMPRESSION_LZ4_RAW; + else if (m_compression_type == CompressionType::LZMA) + compression_type = COMPRESSION_LZMA; + + // If we have the expected size of the decompressed payload, we can allocate + // the right-sized buffer and do it. If we don't have that information, + // we'll + // need to try decoding into a big buffer and if the buffer wasn't big + // enough, + // increase it and try again. + + if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) { + decompressed_bytes = compression_decode_buffer( + decompressed_buffer, decompressed_bufsize + 10, + (uint8_t *)unescaped_content.data(), unescaped_content.size(), NULL, + compression_type); } + } #endif -#if defined (HAVE_LIBZ) - if (decompressed_bytes == 0 - && decompressed_bufsize != ULONG_MAX - && decompressed_buffer != nullptr - && m_compression_type == CompressionType::ZlibDeflate) - { - z_stream stream; - memset (&stream, 0, sizeof (z_stream)); - stream.next_in = (Bytef *) unescaped_content.data(); - stream.avail_in = (uInt) unescaped_content.size(); - stream.total_in = 0; - stream.next_out = (Bytef *) decompressed_buffer; - stream.avail_out = decompressed_bufsize; - stream.total_out = 0; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - - if (inflateInit2 (&stream, -15) == Z_OK) - { - int status = inflate (&stream, Z_NO_FLUSH); - inflateEnd (&stream); - if (status == Z_STREAM_END) - { - decompressed_bytes = stream.total_out; - } - } +#if defined(HAVE_LIBZ) + if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX && + decompressed_buffer != nullptr && + m_compression_type == CompressionType::ZlibDeflate) { + z_stream stream; + memset(&stream, 0, sizeof(z_stream)); + stream.next_in = (Bytef *)unescaped_content.data(); + stream.avail_in = (uInt)unescaped_content.size(); + stream.total_in = 0; + stream.next_out = (Bytef *)decompressed_buffer; + stream.avail_out = decompressed_bufsize; + stream.total_out = 0; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + if (inflateInit2(&stream, -15) == Z_OK) { + int status = inflate(&stream, Z_NO_FLUSH); + inflateEnd(&stream); + if (status == Z_STREAM_END) { + decompressed_bytes = stream.total_out; + } } + } #endif - if (decompressed_bytes == 0 || decompressed_buffer == nullptr) - { - if (decompressed_buffer) - free (decompressed_buffer); - m_bytes.erase (0, size_of_first_packet); - return false; - } - - std::string new_packet; - new_packet.reserve (decompressed_bytes + 6); - new_packet.push_back (m_bytes[0]); - new_packet.append ((const char *) decompressed_buffer, decompressed_bytes); - new_packet.push_back ('#'); - if (GetSendAcks ()) - { - uint8_t decompressed_checksum = CalculcateChecksum (llvm::StringRef((const char *) decompressed_buffer, decompressed_bytes)); - char decompressed_checksum_str[3]; - snprintf (decompressed_checksum_str, 3, "%02x", decompressed_checksum); - new_packet.append (decompressed_checksum_str); - } - else - { - new_packet.push_back ('0'); - new_packet.push_back ('0'); - } - - m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size()); - - free (decompressed_buffer); - return true; + if (decompressed_bytes == 0 || decompressed_buffer == nullptr) { + if (decompressed_buffer) + free(decompressed_buffer); + m_bytes.erase(0, size_of_first_packet); + return false; + } + + std::string new_packet; + new_packet.reserve(decompressed_bytes + 6); + new_packet.push_back(m_bytes[0]); + new_packet.append((const char *)decompressed_buffer, decompressed_bytes); + new_packet.push_back('#'); + if (GetSendAcks()) { + uint8_t decompressed_checksum = CalculcateChecksum( + llvm::StringRef((const char *)decompressed_buffer, decompressed_bytes)); + char decompressed_checksum_str[3]; + snprintf(decompressed_checksum_str, 3, "%02x", decompressed_checksum); + new_packet.append(decompressed_checksum_str); + } else { + new_packet.push_back('0'); + new_packet.push_back('0'); + } + + m_bytes.replace(0, size_of_first_packet, new_packet.data(), + new_packet.size()); + + free(decompressed_buffer); + return true; } GDBRemoteCommunication::PacketType -GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) -{ - // Put the packet data into the buffer in a thread safe fashion - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); +GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, + StringExtractorGDBRemote &packet) { + // Put the packet data into the buffer in a thread safe fashion + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + + if (src && src_len > 0) { + if (log && log->GetVerbose()) { + StreamString s; + log->Printf("GDBRemoteCommunication::%s adding %u bytes: %.*s", + __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src); + } + m_bytes.append((const char *)src, src_len); + } + + bool isNotifyPacket = false; + + // Parse up the packets into gdb remote packets + if (!m_bytes.empty()) { + // end_idx must be one past the last valid packet byte. Start + // it off with an invalid value that is the same as the current + // index. + size_t content_start = 0; + size_t content_length = 0; + size_t total_length = 0; + size_t checksum_idx = std::string::npos; + + // Size of packet before it is decompressed, for logging purposes + size_t original_packet_size = m_bytes.size(); + if (CompressionIsEnabled()) { + if (DecompressPacket() == false) { + packet.Clear(); + return GDBRemoteCommunication::PacketType::Standard; + } + } - if (src && src_len > 0) - { - if (log && log->GetVerbose()) - { - StreamString s; - log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s", - __FUNCTION__, - (uint32_t)src_len, - (uint32_t)src_len, - src); + switch (m_bytes[0]) { + case '+': // Look for ack + case '-': // Look for cancel + case '\x03': // ^C to halt target + content_length = total_length = 1; // The command is one byte long... + break; + + case '%': // Async notify packet + isNotifyPacket = true; + LLVM_FALLTHROUGH; + + case '$': + // Look for a standard gdb packet? + { + size_t hash_pos = m_bytes.find('#'); + if (hash_pos != std::string::npos) { + if (hash_pos + 2 < m_bytes.size()) { + checksum_idx = hash_pos + 1; + // Skip the dollar sign + content_start = 1; + // Don't include the # in the content or the $ in the content length + content_length = hash_pos - 1; + + total_length = + hash_pos + 3; // Skip the # and the two hex checksum bytes + } else { + // Checksum bytes aren't all here yet + content_length = std::string::npos; + } + } + } + break; + + default: { + // We have an unexpected byte and we need to flush all bad + // data that is in m_bytes, so we need to find the first + // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), + // or '$' character (start of packet header) or of course, + // the end of the data in m_bytes... + const size_t bytes_len = m_bytes.size(); + bool done = false; + uint32_t idx; + for (idx = 1; !done && idx < bytes_len; ++idx) { + switch (m_bytes[idx]) { + case '+': + case '-': + case '\x03': + case '%': + case '$': + done = true; + break; + + default: + break; } - m_bytes.append ((const char *)src, src_len); + } + if (log) + log->Printf("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", + __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); + m_bytes.erase(0, idx - 1); + } break; } - bool isNotifyPacket = false; - - // Parse up the packets into gdb remote packets - if (!m_bytes.empty()) - { - // end_idx must be one past the last valid packet byte. Start - // it off with an invalid value that is the same as the current - // index. - size_t content_start = 0; - size_t content_length = 0; - size_t total_length = 0; - size_t checksum_idx = std::string::npos; - - // Size of packet before it is decompressed, for logging purposes - size_t original_packet_size = m_bytes.size(); - if (CompressionIsEnabled()) - { - if (DecompressPacket() == false) - { - packet.Clear(); - return GDBRemoteCommunication::PacketType::Standard; + if (content_length == std::string::npos) { + packet.Clear(); + return GDBRemoteCommunication::PacketType::Invalid; + } else if (total_length > 0) { + + // We have a valid packet... + assert(content_length <= m_bytes.size()); + assert(total_length <= m_bytes.size()); + assert(content_length <= total_length); + size_t content_end = content_start + content_length; + + bool success = true; + std::string &packet_str = packet.GetStringRef(); + if (log) { + // If logging was just enabled and we have history, then dump out what + // we have to the log so we get the historical context. The Dump() call + // that + // logs all of the packet will set a boolean so that we don't dump this + // more + // than once + if (!m_history.DidDumpToLog()) + m_history.Dump(log); + + bool binary = false; + // Only detect binary for packets that start with a '$' and have a '#CC' + // checksum + if (m_bytes[0] == '$' && total_length > 4) { + for (size_t i = 0; !binary && i < total_length; ++i) { + if (isprint(m_bytes[i]) == 0 && isspace(m_bytes[i]) == 0) { + binary = true; } + } } - - switch (m_bytes[0]) - { - case '+': // Look for ack - case '-': // Look for cancel - case '\x03': // ^C to halt target - content_length = total_length = 1; // The command is one byte long... - break; - - case '%': // Async notify packet - isNotifyPacket = true; - LLVM_FALLTHROUGH; - - case '$': - // Look for a standard gdb packet? - { - size_t hash_pos = m_bytes.find('#'); - if (hash_pos != std::string::npos) - { - if (hash_pos + 2 < m_bytes.size()) - { - checksum_idx = hash_pos + 1; - // Skip the dollar sign - content_start = 1; - // Don't include the # in the content or the $ in the content length - content_length = hash_pos - 1; - - total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes - } - else - { - // Checksum bytes aren't all here yet - content_length = std::string::npos; - } - } - } - break; - - default: - { - // We have an unexpected byte and we need to flush all bad - // data that is in m_bytes, so we need to find the first - // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), - // or '$' character (start of packet header) or of course, - // the end of the data in m_bytes... - const size_t bytes_len = m_bytes.size(); - bool done = false; - uint32_t idx; - for (idx = 1; !done && idx < bytes_len; ++idx) - { - switch (m_bytes[idx]) - { - case '+': - case '-': - case '\x03': - case '%': - case '$': - done = true; - break; - - default: - break; - } - } - if (log) - log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); - m_bytes.erase(0, idx - 1); - } - break; + if (binary) { + StreamString strm; + // Packet header... + if (CompressionIsEnabled()) + strm.Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %c", + (uint64_t)original_packet_size, (uint64_t)total_length, + m_bytes[0]); + else + strm.Printf("<%4" PRIu64 "> read packet: %c", + (uint64_t)total_length, m_bytes[0]); + for (size_t i = content_start; i < content_end; ++i) { + // Remove binary escaped bytes when displaying the packet... + const char ch = m_bytes[i]; + if (ch == 0x7d) { + // 0x7d is the escape character. The next character is to + // be XOR'd with 0x20. + const char escapee = m_bytes[++i] ^ 0x20; + strm.Printf("%2.2x", escapee); + } else { + strm.Printf("%2.2x", (uint8_t)ch); + } + } + // Packet footer... + strm.Printf("%c%c%c", m_bytes[total_length - 3], + m_bytes[total_length - 2], m_bytes[total_length - 1]); + log->PutCString(strm.GetString().c_str()); + } else { + if (CompressionIsEnabled()) + log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", + (uint64_t)original_packet_size, (uint64_t)total_length, + (int)(total_length), m_bytes.c_str()); + else + log->Printf("<%4" PRIu64 "> read packet: %.*s", + (uint64_t)total_length, (int)(total_length), + m_bytes.c_str()); } - - if (content_length == std::string::npos) - { - packet.Clear(); - return GDBRemoteCommunication::PacketType::Invalid; + } + + m_history.AddPacket(m_bytes.c_str(), total_length, + History::ePacketTypeRecv, total_length); + + // Clear packet_str in case there is some existing data in it. + packet_str.clear(); + // Copy the packet from m_bytes to packet_str expanding the + // run-length encoding in the process. + // Reserve enough byte for the most common case (no RLE used) + packet_str.reserve(m_bytes.length()); + for (std::string::const_iterator c = m_bytes.begin() + content_start; + c != m_bytes.begin() + content_end; ++c) { + if (*c == '*') { + // '*' indicates RLE. Next character will give us the + // repeat count and previous character is what is to be + // repeated. + char char_to_repeat = packet_str.back(); + // Number of time the previous character is repeated + int repeat_count = *++c + 3 - ' '; + // We have the char_to_repeat and repeat_count. Now push + // it in the packet. + for (int i = 0; i < repeat_count; ++i) + packet_str.push_back(char_to_repeat); + } else if (*c == 0x7d) { + // 0x7d is the escape character. The next character is to + // be XOR'd with 0x20. + char escapee = *++c ^ 0x20; + packet_str.push_back(escapee); + } else { + packet_str.push_back(*c); } - else if (total_length > 0) - { - - // We have a valid packet... - assert (content_length <= m_bytes.size()); - assert (total_length <= m_bytes.size()); - assert (content_length <= total_length); - size_t content_end = content_start + content_length; - - bool success = true; - std::string &packet_str = packet.GetStringRef(); - if (log) - { - // If logging was just enabled and we have history, then dump out what - // we have to the log so we get the historical context. The Dump() call that - // logs all of the packet will set a boolean so that we don't dump this more - // than once - if (!m_history.DidDumpToLog ()) - m_history.Dump (log); - - bool binary = false; - // Only detect binary for packets that start with a '$' and have a '#CC' checksum - if (m_bytes[0] == '$' && total_length > 4) - { - for (size_t i=0; !binary && i<total_length; ++i) - { - if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0) - { - binary = true; - } - } - } - if (binary) - { - StreamString strm; - // Packet header... - if (CompressionIsEnabled()) - strm.Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %c", (uint64_t) original_packet_size, (uint64_t)total_length, m_bytes[0]); - else - strm.Printf("<%4" PRIu64 "> read packet: %c", (uint64_t)total_length, m_bytes[0]); - for (size_t i=content_start; i<content_end; ++i) - { - // Remove binary escaped bytes when displaying the packet... - const char ch = m_bytes[i]; - if (ch == 0x7d) - { - // 0x7d is the escape character. The next character is to - // be XOR'd with 0x20. - const char escapee = m_bytes[++i] ^ 0x20; - strm.Printf("%2.2x", escapee); - } - else - { - strm.Printf("%2.2x", (uint8_t)ch); - } - } - // Packet footer... - strm.Printf("%c%c%c", m_bytes[total_length-3], m_bytes[total_length-2], m_bytes[total_length-1]); - log->PutCString(strm.GetString().c_str()); - } - else - { - if (CompressionIsEnabled()) - log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", (uint64_t) original_packet_size, (uint64_t)total_length, (int)(total_length), m_bytes.c_str()); - else - log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str()); - } - } - - m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length); - - // Clear packet_str in case there is some existing data in it. - packet_str.clear(); - // Copy the packet from m_bytes to packet_str expanding the - // run-length encoding in the process. - // Reserve enough byte for the most common case (no RLE used) - packet_str.reserve(m_bytes.length()); - for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c) - { - if (*c == '*') - { - // '*' indicates RLE. Next character will give us the - // repeat count and previous character is what is to be - // repeated. - char char_to_repeat = packet_str.back(); - // Number of time the previous character is repeated - int repeat_count = *++c + 3 - ' '; - // We have the char_to_repeat and repeat_count. Now push - // it in the packet. - for (int i = 0; i < repeat_count; ++i) - packet_str.push_back(char_to_repeat); - } - else if (*c == 0x7d) - { - // 0x7d is the escape character. The next character is to - // be XOR'd with 0x20. - char escapee = *++c ^ 0x20; - packet_str.push_back(escapee); - } - else - { - packet_str.push_back(*c); - } - } - - if (m_bytes[0] == '$' || m_bytes[0] == '%') - { - assert (checksum_idx < m_bytes.size()); - if (::isxdigit (m_bytes[checksum_idx+0]) || - ::isxdigit (m_bytes[checksum_idx+1])) - { - if (GetSendAcks ()) - { - const char *packet_checksum_cstr = &m_bytes[checksum_idx]; - char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); - char actual_checksum = CalculcateChecksum (packet_str); - success = packet_checksum == actual_checksum; - if (!success) - { - if (log) - log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", - (int)(total_length), - m_bytes.c_str(), - (uint8_t)packet_checksum, - (uint8_t)actual_checksum); - } - // Send the ack or nack if needed - if (!success) - SendNack(); - else - SendAck(); - } - } - else - { - success = false; - if (log) - log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str()); - } + } + + if (m_bytes[0] == '$' || m_bytes[0] == '%') { + assert(checksum_idx < m_bytes.size()); + if (::isxdigit(m_bytes[checksum_idx + 0]) || + ::isxdigit(m_bytes[checksum_idx + 1])) { + if (GetSendAcks()) { + const char *packet_checksum_cstr = &m_bytes[checksum_idx]; + char packet_checksum = strtol(packet_checksum_cstr, NULL, 16); + char actual_checksum = CalculcateChecksum(packet_str); + success = packet_checksum == actual_checksum; + if (!success) { + if (log) + log->Printf("error: checksum mismatch: %.*s expected 0x%2.2x, " + "got 0x%2.2x", + (int)(total_length), m_bytes.c_str(), + (uint8_t)packet_checksum, (uint8_t)actual_checksum); } - - m_bytes.erase(0, total_length); - packet.SetFilePos(0); - - if (isNotifyPacket) - return GDBRemoteCommunication::PacketType::Notify; + // Send the ack or nack if needed + if (!success) + SendNack(); else - return GDBRemoteCommunication::PacketType::Standard; + SendAck(); + } + } else { + success = false; + if (log) + log->Printf("error: invalid checksum in packet: '%s'\n", + m_bytes.c_str()); } + } + + m_bytes.erase(0, total_length); + packet.SetFilePos(0); + + if (isNotifyPacket) + return GDBRemoteCommunication::PacketType::Notify; + else + return GDBRemoteCommunication::PacketType::Standard; } - packet.Clear(); - return GDBRemoteCommunication::PacketType::Invalid; + } + packet.Clear(); + return GDBRemoteCommunication::PacketType::Invalid; } -Error -GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) -{ - Error error; - if (m_listen_thread.IsJoinable()) - { - error.SetErrorString("listen thread already running"); - } +Error GDBRemoteCommunication::StartListenThread(const char *hostname, + uint16_t port) { + Error error; + if (m_listen_thread.IsJoinable()) { + error.SetErrorString("listen thread already running"); + } else { + char listen_url[512]; + if (hostname && hostname[0]) + snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, + port); else - { - char listen_url[512]; - if (hostname && hostname[0]) - snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port); - else - snprintf(listen_url, sizeof(listen_url), "listen://%i", port); - m_listen_url = listen_url; - SetConnection(new ConnectionFileDescriptor()); - m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error); - } - return error; + snprintf(listen_url, sizeof(listen_url), "listen://%i", port); + m_listen_url = listen_url; + SetConnection(new ConnectionFileDescriptor()); + m_listen_thread = ThreadLauncher::LaunchThread( + listen_url, GDBRemoteCommunication::ListenThread, this, &error); + } + return error; } -bool -GDBRemoteCommunication::JoinListenThread () -{ - if (m_listen_thread.IsJoinable()) - m_listen_thread.Join(nullptr); - return true; +bool GDBRemoteCommunication::JoinListenThread() { + if (m_listen_thread.IsJoinable()) + m_listen_thread.Join(nullptr); + return true; } lldb::thread_result_t -GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg) -{ - GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg; - Error error; - ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection (); - - if (connection) - { - // Do the listen on another thread so we can continue on... - if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess) - comm->SetConnection(NULL); - } - return NULL; +GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) { + GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg; + Error error; + ConnectionFileDescriptor *connection = + (ConnectionFileDescriptor *)comm->GetConnection(); + + if (connection) { + // Do the listen on another thread so we can continue on... + if (connection->Connect(comm->m_listen_url.c_str(), &error) != + eConnectionStatusSuccess) + comm->SetConnection(NULL); + } + return NULL; } -Error -GDBRemoteCommunication::StartDebugserverProcess (const char *url, - Platform *platform, - ProcessLaunchInfo &launch_info, - uint16_t *port, - const Args* inferior_args, - int pass_comm_fd) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); +Error GDBRemoteCommunication::StartDebugserverProcess( + const char *url, Platform *platform, ProcessLaunchInfo &launch_info, + uint16_t *port, const Args *inferior_args, int pass_comm_fd) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", + __FUNCTION__, url ? url : "<empty>", + port ? *port : uint16_t(0)); + + Error error; + // If we locate debugserver, keep that located version around + static FileSpec g_debugserver_file_spec; + + char debugserver_path[PATH_MAX]; + FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); + + // Always check to see if we have an environment override for the path + // to the debugserver to use and use it if we do. + const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); + if (env_debugserver_path) { + debugserver_file_spec.SetFile(env_debugserver_path, false); if (log) - log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); - - Error error; - // If we locate debugserver, keep that located version around - static FileSpec g_debugserver_file_spec; - - char debugserver_path[PATH_MAX]; - FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); - - // Always check to see if we have an environment override for the path - // to the debugserver to use and use it if we do. - const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); - if (env_debugserver_path) - { - debugserver_file_spec.SetFile (env_debugserver_path, false); + log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set " + "from environment variable: %s", + __FUNCTION__, env_debugserver_path); + } else + debugserver_file_spec = g_debugserver_file_spec; + bool debugserver_exists = debugserver_file_spec.Exists(); + if (!debugserver_exists) { + // The debugserver binary is in the LLDB.framework/Resources + // directory. + if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, + debugserver_file_spec)) { + debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME); + debugserver_exists = debugserver_file_spec.Exists(); + if (debugserver_exists) { if (log) - log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path); - } - else - debugserver_file_spec = g_debugserver_file_spec; - bool debugserver_exists = debugserver_file_spec.Exists(); - if (!debugserver_exists) - { - // The debugserver binary is in the LLDB.framework/Resources - // directory. - if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec)) - { - debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME); - debugserver_exists = debugserver_file_spec.Exists(); - if (debugserver_exists) - { - if (log) - log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); - - g_debugserver_file_spec = debugserver_file_spec; - } - else - { - debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME); - if (debugserver_file_spec) - { - // Platform::LocateExecutable() wouldn't return a path if it doesn't exist - debugserver_exists = true; - } - else - { - if (log) - log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); - } - // Don't cache the platform specific GDB server binary as it could change - // from platform to platform - g_debugserver_file_spec.Clear(); - } + log->Printf( + "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); + + g_debugserver_file_spec = debugserver_file_spec; + } else { + debugserver_file_spec = + platform->LocateExecutable(DEBUGSERVER_BASENAME); + if (debugserver_file_spec) { + // Platform::LocateExecutable() wouldn't return a path if it doesn't + // exist + debugserver_exists = true; + } else { + if (log) + log->Printf("GDBRemoteCommunication::%s() could not find " + "gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); } + // Don't cache the platform specific GDB server binary as it could + // change + // from platform to platform + g_debugserver_file_spec.Clear(); + } } - - if (debugserver_exists) - { - debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path)); + } - Args &debugserver_args = launch_info.GetArguments(); - debugserver_args.Clear(); - char arg_cstr[PATH_MAX]; + if (debugserver_exists) { + debugserver_file_spec.GetPath(debugserver_path, sizeof(debugserver_path)); - // Start args with "debugserver /file/path -r --" - debugserver_args.AppendArgument(debugserver_path); + Args &debugserver_args = launch_info.GetArguments(); + debugserver_args.Clear(); + char arg_cstr[PATH_MAX]; + + // Start args with "debugserver /file/path -r --" + debugserver_args.AppendArgument(debugserver_path); #if !defined(__APPLE__) - // First argument to lldb-server must be mode in which to run. - debugserver_args.AppendArgument("gdbserver"); + // First argument to lldb-server must be mode in which to run. + debugserver_args.AppendArgument("gdbserver"); #endif - // If a url is supplied then use it - if (url) - debugserver_args.AppendArgument(url); - - if (pass_comm_fd >= 0) - { - StreamString fd_arg; - fd_arg.Printf("--fd=%i", pass_comm_fd); - debugserver_args.AppendArgument(fd_arg.GetData()); - // Send "pass_comm_fd" down to the inferior so it can use it to - // communicate back with this process - launch_info.AppendDuplicateFileAction(pass_comm_fd, pass_comm_fd); - } + // If a url is supplied then use it + if (url) + debugserver_args.AppendArgument(url); + + if (pass_comm_fd >= 0) { + StreamString fd_arg; + fd_arg.Printf("--fd=%i", pass_comm_fd); + debugserver_args.AppendArgument(fd_arg.GetData()); + // Send "pass_comm_fd" down to the inferior so it can use it to + // communicate back with this process + launch_info.AppendDuplicateFileAction(pass_comm_fd, pass_comm_fd); + } - // use native registers, not the GDB registers - debugserver_args.AppendArgument("--native-regs"); + // use native registers, not the GDB registers + debugserver_args.AppendArgument("--native-regs"); - if (launch_info.GetLaunchInSeparateProcessGroup()) - { - debugserver_args.AppendArgument("--setsid"); - } + if (launch_info.GetLaunchInSeparateProcessGroup()) { + debugserver_args.AppendArgument("--setsid"); + } + + llvm::SmallString<PATH_MAX> named_pipe_path; + // socket_pipe is used by debug server to communicate back either + // TCP port or domain socket name which it listens on. + // The second purpose of the pipe to serve as a synchronization point - + // once data is written to the pipe, debug server is up and running. + Pipe socket_pipe; + + // port is null when debug server should listen on domain socket - + // we're not interested in port value but rather waiting for debug server + // to become available. + if (pass_comm_fd == -1 && + ((port != nullptr && *port == 0) || port == nullptr)) { + if (url) { +// Create a temporary file to get the stdout/stderr and redirect the +// output of the command into this file. We will later read this file +// if all goes well and fill the data into "command_output_ptr" - llvm::SmallString<PATH_MAX> named_pipe_path; - // socket_pipe is used by debug server to communicate back either - // TCP port or domain socket name which it listens on. - // The second purpose of the pipe to serve as a synchronization point - - // once data is written to the pipe, debug server is up and running. - Pipe socket_pipe; - - // port is null when debug server should listen on domain socket - - // we're not interested in port value but rather waiting for debug server - // to become available. - if (pass_comm_fd == -1 && ((port != nullptr && *port == 0) || port == nullptr)) - { - if (url) - { - // Create a temporary file to get the stdout/stderr and redirect the - // output of the command into this file. We will later read this file - // if all goes well and fill the data into "command_output_ptr" - -#if defined(__APPLE__) - // Binding to port zero, we need to figure out what port it ends up - // using using a named pipe... - error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); - if (error.Fail()) - { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "named pipe creation failed: %s", - __FUNCTION__, error.AsCString()); - return error; - } - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path.c_str()); -#else - // Binding to port zero, we need to figure out what port it ends up - // using using an unnamed pipe... - error = socket_pipe.CreateNew(true); - if (error.Fail()) - { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "unnamed pipe creation failed: %s", - __FUNCTION__, error.AsCString()); - return error; - } - int write_fd = socket_pipe.GetWriteFileDescriptor(); - debugserver_args.AppendArgument("--pipe"); - debugserver_args.AppendArgument(llvm::to_string(write_fd).c_str()); - launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor()); -#endif - } - else - { - // No host and port given, so lets listen on our end and make the debugserver - // connect to us.. - error = StartListenThread ("127.0.0.1", 0); - if (error.Fail()) - { - if (log) - log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString()); - return error; - } - - ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); - // Wait for 10 seconds to resolve the bound port - uint16_t port_ = connection->GetListeningPort(10); - if (port_ > 0) - { - char port_cstr[32]; - snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_); - // Send the host and port down that debugserver and specify an option - // so that it connects back to the port we are listening to in this process - debugserver_args.AppendArgument("--reverse-connect"); - debugserver_args.AppendArgument(port_cstr); - if (port) - *port = port_; - } - else - { - error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); - if (log) - log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); - return error; - } - } - } - - const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); - if (env_debugserver_log_file) - { - ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file); - debugserver_args.AppendArgument(arg_cstr); - } - #if defined(__APPLE__) - const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); - if (env_debugserver_log_flags) - { - ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags); - debugserver_args.AppendArgument(arg_cstr); + // Binding to port zero, we need to figure out what port it ends up + // using using a named pipe... + error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", + false, named_pipe_path); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "named pipe creation failed: %s", + __FUNCTION__, error.AsCString()); + return error; } + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path.c_str()); #else - const char *env_debugserver_log_channels = getenv("LLDB_SERVER_LOG_CHANNELS"); - if (env_debugserver_log_channels) - { - ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-channels=%s", env_debugserver_log_channels); - debugserver_args.AppendArgument(arg_cstr); + // Binding to port zero, we need to figure out what port it ends up + // using using an unnamed pipe... + error = socket_pipe.CreateNew(true); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "unnamed pipe creation failed: %s", + __FUNCTION__, error.AsCString()); + return error; } + int write_fd = socket_pipe.GetWriteFileDescriptor(); + debugserver_args.AppendArgument("--pipe"); + debugserver_args.AppendArgument(llvm::to_string(write_fd).c_str()); + launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor()); #endif - - // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back. - uint32_t env_var_index = 1; - bool has_env_var; - do - { - char env_var_name[64]; - snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++); - const char *extra_arg = getenv(env_var_name); - has_env_var = extra_arg != nullptr; - - if (has_env_var) - { - debugserver_args.AppendArgument (extra_arg); - if (log) - log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg); - } - } while (has_env_var); - - if (inferior_args && inferior_args->GetArgumentCount() > 0) - { - debugserver_args.AppendArgument ("--"); - debugserver_args.AppendArguments (*inferior_args); + } else { + // No host and port given, so lets listen on our end and make the + // debugserver + // connect to us.. + error = StartListenThread("127.0.0.1", 0); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunication::%s() unable to start listen " + "thread: %s", + __FUNCTION__, error.AsCString()); + return error; } - // Copy the current environment to the gdbserver/debugserver instance - StringList env; - if (Host::GetEnvironment(env)) - { - for (size_t i = 0; i < env.GetSize(); ++i) - launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str()); + ConnectionFileDescriptor *connection = + (ConnectionFileDescriptor *)GetConnection(); + // Wait for 10 seconds to resolve the bound port + uint16_t port_ = connection->GetListeningPort(10); + if (port_ > 0) { + char port_cstr[32]; + snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_); + // Send the host and port down that debugserver and specify an option + // so that it connects back to the port we are listening to in this + // process + debugserver_args.AppendArgument("--reverse-connect"); + debugserver_args.AppendArgument(port_cstr); + if (port) + *port = port_; + } else { + error.SetErrorString("failed to bind to port 0 on 127.0.0.1"); + if (log) + log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, + error.AsCString()); + return error; } + } + } - // Close STDIN, STDOUT and STDERR. - launch_info.AppendCloseFileAction (STDIN_FILENO); - launch_info.AppendCloseFileAction (STDOUT_FILENO); - launch_info.AppendCloseFileAction (STDERR_FILENO); + const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); + if (env_debugserver_log_file) { + ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-file=%s", + env_debugserver_log_file); + debugserver_args.AppendArgument(arg_cstr); + } - // Redirect STDIN, STDOUT and STDERR to "/dev/null". - launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); - launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); - launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); +#if defined(__APPLE__) + const char *env_debugserver_log_flags = + getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); + if (env_debugserver_log_flags) { + ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-flags=%s", + env_debugserver_log_flags); + debugserver_args.AppendArgument(arg_cstr); + } +#else + const char *env_debugserver_log_channels = + getenv("LLDB_SERVER_LOG_CHANNELS"); + if (env_debugserver_log_channels) { + ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-channels=%s", + env_debugserver_log_channels); + debugserver_args.AppendArgument(arg_cstr); + } +#endif + // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an + // env var doesn't come back. + uint32_t env_var_index = 1; + bool has_env_var; + do { + char env_var_name[64]; + snprintf(env_var_name, sizeof(env_var_name), + "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++); + const char *extra_arg = getenv(env_var_name); + has_env_var = extra_arg != nullptr; + + if (has_env_var) { + debugserver_args.AppendArgument(extra_arg); if (log) - { - StreamString string_stream; - Platform *const platform = nullptr; - launch_info.Dump(string_stream, platform); - log->Printf("launch info for gdb-remote stub:\n%s", string_stream.GetString().c_str()); - } - error = Host::LaunchProcess(launch_info); - - if (error.Success() && (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) && pass_comm_fd == -1) - { - if (named_pipe_path.size() > 0) - { - error = socket_pipe.OpenAsReader(named_pipe_path, false); - if (error.Fail()) - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to open named pipe %s for reading: %s", - __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); - } - - if (socket_pipe.CanWrite()) - socket_pipe.CloseWriteFileDescriptor(); - if (socket_pipe.CanRead()) - { - char port_cstr[PATH_MAX] = {0}; - port_cstr[0] = '\0'; - size_t num_bytes = sizeof(port_cstr); - // Read port from pipe with 10 second timeout. - error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes, - std::chrono::seconds{10}, num_bytes); - if (error.Success() && (port != nullptr)) - { - assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - *port = StringConvert::ToUInt32(port_cstr, 0); - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listens %u port", - __FUNCTION__, *port); - } - else - { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to read a port value from pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); - - } - socket_pipe.Close(); - } - - if (named_pipe_path.size() > 0) - { - const auto err = socket_pipe.Delete(named_pipe_path); - if (err.Fail()) - { - if (log) - log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); - } - } + log->Printf("GDBRemoteCommunication::%s adding env var %s contents " + "to stub command line (%s)", + __FUNCTION__, env_var_name, extra_arg); + } + } while (has_env_var); + + if (inferior_args && inferior_args->GetArgumentCount() > 0) { + debugserver_args.AppendArgument("--"); + debugserver_args.AppendArguments(*inferior_args); + } - // Make sure we actually connect with the debugserver... - JoinListenThread(); - } + // Copy the current environment to the gdbserver/debugserver instance + StringList env; + if (Host::GetEnvironment(env)) { + for (size_t i = 0; i < env.GetSize(); ++i) + launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str()); } - else - { - error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME ); + + // Close STDIN, STDOUT and STDERR. + launch_info.AppendCloseFileAction(STDIN_FILENO); + launch_info.AppendCloseFileAction(STDOUT_FILENO); + launch_info.AppendCloseFileAction(STDERR_FILENO); + + // Redirect STDIN, STDOUT and STDERR to "/dev/null". + launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); + launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); + launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); + + if (log) { + StreamString string_stream; + Platform *const platform = nullptr; + launch_info.Dump(string_stream, platform); + log->Printf("launch info for gdb-remote stub:\n%s", + string_stream.GetString().c_str()); } + error = Host::LaunchProcess(launch_info); + + if (error.Success() && + (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) && + pass_comm_fd == -1) { + if (named_pipe_path.size() > 0) { + error = socket_pipe.OpenAsReader(named_pipe_path, false); + if (error.Fail()) + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "failed to open named pipe %s for reading: %s", + __FUNCTION__, named_pipe_path.c_str(), + error.AsCString()); + } + + if (socket_pipe.CanWrite()) + socket_pipe.CloseWriteFileDescriptor(); + if (socket_pipe.CanRead()) { + char port_cstr[PATH_MAX] = {0}; + port_cstr[0] = '\0'; + size_t num_bytes = sizeof(port_cstr); + // Read port from pipe with 10 second timeout. + error = socket_pipe.ReadWithTimeout( + port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes); + if (error.Success() && (port != nullptr)) { + assert(num_bytes > 0 && port_cstr[num_bytes - 1] == '\0'); + *port = StringConvert::ToUInt32(port_cstr, 0); + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "debugserver listens %u port", + __FUNCTION__, *port); + } else { + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "failed to read a port value from pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), + error.AsCString()); + } + socket_pipe.Close(); + } + + if (named_pipe_path.size() > 0) { + const auto err = socket_pipe.Delete(named_pipe_path); + if (err.Fail()) { + if (log) + log->Printf( + "GDBRemoteCommunication::%s failed to delete pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); + } + } - if (error.Fail()) - { - if (log) - log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); + // Make sure we actually connect with the debugserver... + JoinListenThread(); } + } else { + error.SetErrorStringWithFormat("unable to locate " DEBUGSERVER_BASENAME); + } - return error; -} + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, + error.AsCString()); + } -void -GDBRemoteCommunication::DumpHistory(Stream &strm) -{ - m_history.Dump (strm); + return error; } -GDBRemoteCommunication::ScopedTimeout::ScopedTimeout (GDBRemoteCommunication& gdb_comm, - uint32_t timeout) : - m_gdb_comm (gdb_comm) -{ - m_saved_timeout = m_gdb_comm.SetPacketTimeout (timeout); +void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } + +GDBRemoteCommunication::ScopedTimeout::ScopedTimeout( + GDBRemoteCommunication &gdb_comm, uint32_t timeout) + : m_gdb_comm(gdb_comm) { + m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout); } -GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout () -{ - m_gdb_comm.SetPacketTimeout (m_saved_timeout); +GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() { + m_gdb_comm.SetPacketTimeout(m_saved_timeout); } -// This function is called via the Communications class read thread when bytes become available -// for this connection. This function will consume all incoming bytes and try to parse whole -// packets as they become available. Full packets are placed in a queue, so that all packet -// requests can simply pop from this queue. Async notification packets will be dispatched +// This function is called via the Communications class read thread when bytes +// become available +// for this connection. This function will consume all incoming bytes and try to +// parse whole +// packets as they become available. Full packets are placed in a queue, so that +// all packet +// requests can simply pop from this queue. Async notification packets will be +// dispatched // immediately to the ProcessGDBRemote Async thread via an event. -void GDBRemoteCommunication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status) -{ - StringExtractorGDBRemote packet; - - while (true) - { - PacketType type = CheckForPacket(bytes, len, packet); - - // scrub the data so we do not pass it back to CheckForPacket - // on future passes of the loop - bytes = nullptr; - len = 0; - - // we may have received no packet so lets bail out - if (type == PacketType::Invalid) - break; - - if (type == PacketType::Standard) - { - // scope for the mutex - { - // lock down the packet queue - std::lock_guard<std::mutex> guard(m_packet_queue_mutex); - // push a new packet into the queue - m_packet_queue.push(packet); - // Signal condition variable that we have a packet - m_condition_queue_not_empty.notify_one(); - } - } +void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, + size_t len, bool broadcast, + lldb::ConnectionStatus status) { + StringExtractorGDBRemote packet; + + while (true) { + PacketType type = CheckForPacket(bytes, len, packet); + + // scrub the data so we do not pass it back to CheckForPacket + // on future passes of the loop + bytes = nullptr; + len = 0; + + // we may have received no packet so lets bail out + if (type == PacketType::Invalid) + break; + + if (type == PacketType::Standard) { + // scope for the mutex + { + // lock down the packet queue + std::lock_guard<std::mutex> guard(m_packet_queue_mutex); + // push a new packet into the queue + m_packet_queue.push(packet); + // Signal condition variable that we have a packet + m_condition_queue_not_empty.notify_one(); + } + } - if (type == PacketType::Notify) - { - // put this packet into an event - const char *pdata = packet.GetStringRef().c_str(); + if (type == PacketType::Notify) { + // put this packet into an event + const char *pdata = packet.GetStringRef().c_str(); - // as the communication class, we are a broadcaster and the - // async thread is tuned to listen to us - BroadcastEvent( - eBroadcastBitGdbReadThreadGotNotify, - new EventDataBytes(pdata)); - } + // as the communication class, we are a broadcaster and the + // async thread is tuned to listen to us + BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify, + new EventDataBytes(pdata)); } + } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 5343a910cf8..854fa76ef0a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -14,334 +14,277 @@ // C++ Includes #include <condition_variable> #include <mutex> -#include <string> #include <queue> +#include <string> #include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-public.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" +#include "lldb/lldb-public.h" #include "Utility/StringExtractorGDBRemote.h" namespace lldb_private { namespace process_gdb_remote { -typedef enum -{ - eStoppointInvalid = -1, - eBreakpointSoftware = 0, - eBreakpointHardware, - eWatchpointWrite, - eWatchpointRead, - eWatchpointReadWrite +typedef enum { + eStoppointInvalid = -1, + eBreakpointSoftware = 0, + eBreakpointHardware, + eWatchpointWrite, + eWatchpointRead, + eWatchpointReadWrite } GDBStoppointType; -enum class CompressionType -{ - None = 0, // no compression - ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's libcompression - LZFSE, // an Apple compression scheme, requires Apple's libcompression - LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with https://code.google.com/p/lz4/ - LZMA, // Lempel–Ziv–Markov chain algorithm +enum class CompressionType { + None = 0, // no compression + ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's + // libcompression + LZFSE, // an Apple compression scheme, requires Apple's libcompression + LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with + // https://code.google.com/p/lz4/ + LZMA, // Lempel–Ziv–Markov chain algorithm }; class ProcessGDBRemote; -class GDBRemoteCommunication : public Communication -{ +class GDBRemoteCommunication : public Communication { public: - enum - { - eBroadcastBitRunPacketSent = kLoUserBroadcastBit, - eBroadcastBitGdbReadThreadGotNotify = kLoUserBroadcastBit << 1 // Sent when we received a notify packet. - }; + enum { + eBroadcastBitRunPacketSent = kLoUserBroadcastBit, + eBroadcastBitGdbReadThreadGotNotify = + kLoUserBroadcastBit << 1 // Sent when we received a notify packet. + }; + + enum class PacketType { Invalid = 0, Standard, Notify }; + + enum class PacketResult { + Success = 0, // Success + ErrorSendFailed, // Error sending the packet + ErrorSendAck, // Didn't get an ack back after sending a packet + ErrorReplyFailed, // Error getting the reply + ErrorReplyTimeout, // Timed out waiting for reply + ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that + // was sent + ErrorReplyAck, // Sending reply ack failed + ErrorDisconnected, // We were disconnected + ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet + // request + }; + + // Class to change the timeout for a given scope and restore it to the + // original value when the + // created ScopedTimeout object got out of scope + class ScopedTimeout { + public: + ScopedTimeout(GDBRemoteCommunication &gdb_comm, uint32_t timeout); + ~ScopedTimeout(); + + private: + GDBRemoteCommunication &m_gdb_comm; + uint32_t m_saved_timeout; + }; + + GDBRemoteCommunication(const char *comm_name, const char *listener_name); + + ~GDBRemoteCommunication() override; + + PacketResult GetAck(); + + size_t SendAck(); + + size_t SendNack(); + + char CalculcateChecksum(llvm::StringRef payload); + + PacketType CheckForPacket(const uint8_t *src, size_t src_len, + StringExtractorGDBRemote &packet); + + bool GetSendAcks() { return m_send_acks; } + + //------------------------------------------------------------------ + // Set the global packet timeout. + // + // For clients, this is the timeout that gets used when sending + // packets and waiting for responses. For servers, this might not + // get used, and if it doesn't this should be moved to the + // GDBRemoteCommunicationClient. + //------------------------------------------------------------------ + uint32_t SetPacketTimeout(uint32_t packet_timeout) { + const uint32_t old_packet_timeout = m_packet_timeout; + m_packet_timeout = packet_timeout; + return old_packet_timeout; + } + + uint32_t GetPacketTimeoutInMicroSeconds() const { + return m_packet_timeout * TimeValue::MicroSecPerSec; + } + + //------------------------------------------------------------------ + // Start a debugserver instance on the current host using the + // supplied connection URL. + //------------------------------------------------------------------ + Error StartDebugserverProcess( + const char *url, + Platform *platform, // If non nullptr, then check with the platform for + // the GDB server binary if it can't be located + ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, + int pass_comm_fd); // Communication file descriptor to pass during + // fork/exec to avoid having to connect/accept + + void DumpHistory(Stream &strm); - enum class PacketType - { - Invalid = 0, - Standard, - Notify - }; - - enum class PacketResult - { - Success = 0, // Success - ErrorSendFailed, // Error sending the packet - ErrorSendAck, // Didn't get an ack back after sending a packet - ErrorReplyFailed, // Error getting the reply - ErrorReplyTimeout, // Timed out waiting for reply - ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that was sent - ErrorReplyAck, // Sending reply ack failed - ErrorDisconnected, // We were disconnected - ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet request +protected: + class History { + public: + enum PacketType { + ePacketTypeInvalid = 0, + ePacketTypeSend, + ePacketTypeRecv }; - // Class to change the timeout for a given scope and restore it to the original value when the - // created ScopedTimeout object got out of scope - class ScopedTimeout - { - public: - ScopedTimeout (GDBRemoteCommunication& gdb_comm, uint32_t timeout); - ~ScopedTimeout (); - - private: - GDBRemoteCommunication& m_gdb_comm; - uint32_t m_saved_timeout; + struct Entry { + Entry() + : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), + packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {} + + void Clear() { + packet.clear(); + type = ePacketTypeInvalid; + bytes_transmitted = 0; + packet_idx = 0; + tid = LLDB_INVALID_THREAD_ID; + } + std::string packet; + PacketType type; + uint32_t bytes_transmitted; + uint32_t packet_idx; + lldb::tid_t tid; }; - GDBRemoteCommunication(const char *comm_name, - const char *listener_name); - - ~GDBRemoteCommunication() override; + History(uint32_t size); - PacketResult - GetAck (); + ~History(); - size_t - SendAck (); + // For single char packets for ack, nack and /x03 + void AddPacket(char packet_char, PacketType type, + uint32_t bytes_transmitted); - size_t - SendNack (); + void AddPacket(const std::string &src, uint32_t src_len, PacketType type, + uint32_t bytes_transmitted); - char - CalculcateChecksum (llvm::StringRef payload); + void Dump(Stream &strm) const; - PacketType - CheckForPacket (const uint8_t *src, - size_t src_len, - StringExtractorGDBRemote &packet); + void Dump(Log *log) const; - bool - GetSendAcks () - { - return m_send_acks; - } + bool DidDumpToLog() const { return m_dumped_to_log; } - //------------------------------------------------------------------ - // Set the global packet timeout. - // - // For clients, this is the timeout that gets used when sending - // packets and waiting for responses. For servers, this might not - // get used, and if it doesn't this should be moved to the - // GDBRemoteCommunicationClient. - //------------------------------------------------------------------ - uint32_t - SetPacketTimeout (uint32_t packet_timeout) - { - const uint32_t old_packet_timeout = m_packet_timeout; - m_packet_timeout = packet_timeout; - return old_packet_timeout; + protected: + uint32_t GetFirstSavedPacketIndex() const { + if (m_total_packet_count < m_packets.size()) + return 0; + else + return m_curr_idx + 1; } - uint32_t - GetPacketTimeoutInMicroSeconds () const - { - return m_packet_timeout * TimeValue::MicroSecPerSec; + uint32_t GetNumPacketsInHistory() const { + if (m_total_packet_count < m_packets.size()) + return m_total_packet_count; + else + return (uint32_t)m_packets.size(); } - //------------------------------------------------------------------ - // Start a debugserver instance on the current host using the - // supplied connection URL. - //------------------------------------------------------------------ - Error - StartDebugserverProcess(const char *url, - Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located - ProcessLaunchInfo &launch_info, - uint16_t *port, - const Args *inferior_args, - int pass_comm_fd); // Communication file descriptor to pass during fork/exec to avoid having to connect/accept - - void - DumpHistory(Stream &strm); - -protected: - class History - { - public: - enum PacketType - { - ePacketTypeInvalid = 0, - ePacketTypeSend, - ePacketTypeRecv - }; - - struct Entry - { - Entry() : - packet(), - type (ePacketTypeInvalid), - bytes_transmitted (0), - packet_idx (0), - tid (LLDB_INVALID_THREAD_ID) - { - } - - void - Clear () - { - packet.clear(); - type = ePacketTypeInvalid; - bytes_transmitted = 0; - packet_idx = 0; - tid = LLDB_INVALID_THREAD_ID; - } - std::string packet; - PacketType type; - uint32_t bytes_transmitted; - uint32_t packet_idx; - lldb::tid_t tid; - }; - - History (uint32_t size); - - ~History (); - - // For single char packets for ack, nack and /x03 - void - AddPacket (char packet_char, - PacketType type, - uint32_t bytes_transmitted); - - void - AddPacket (const std::string &src, - uint32_t src_len, - PacketType type, - uint32_t bytes_transmitted); - - void - Dump (Stream &strm) const; - - void - Dump (Log *log) const; - - bool - DidDumpToLog () const - { - return m_dumped_to_log; - } - - protected: - uint32_t - GetFirstSavedPacketIndex () const - { - if (m_total_packet_count < m_packets.size()) - return 0; - else - return m_curr_idx + 1; - } - - uint32_t - GetNumPacketsInHistory () const - { - if (m_total_packet_count < m_packets.size()) - return m_total_packet_count; - else - return (uint32_t)m_packets.size(); - } - - uint32_t - GetNextIndex() - { - ++m_total_packet_count; - const uint32_t idx = m_curr_idx; - m_curr_idx = NormalizeIndex(idx + 1); - return idx; - } - - uint32_t - NormalizeIndex (uint32_t i) const - { - return i % m_packets.size(); - } - - std::vector<Entry> m_packets; - uint32_t m_curr_idx; - uint32_t m_total_packet_count; - mutable bool m_dumped_to_log; - }; - - uint32_t m_packet_timeout; - uint32_t m_echo_number; - LazyBool m_supports_qEcho; - History m_history; - bool m_send_acks; - bool m_is_platform; // Set to true if this class represents a platform, - // false if this class represents a debug session for - // a single process - - CompressionType m_compression_type; - - PacketResult - SendPacketNoLock (llvm::StringRef payload); - - PacketResult - ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout); - - // Pop a packet from the queue in a thread safe manner - PacketResult - PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec); - - PacketResult - WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response, - uint32_t timeout_usec, - bool sync_on_timeout); - - bool - CompressionIsEnabled () - { - return m_compression_type != CompressionType::None; + uint32_t GetNextIndex() { + ++m_total_packet_count; + const uint32_t idx = m_curr_idx; + m_curr_idx = NormalizeIndex(idx + 1); + return idx; } - // If compression is enabled, decompress the packet in m_bytes and update - // m_bytes with the uncompressed version. - // Returns 'true' packet was decompressed and m_bytes is the now-decompressed text. - // Returns 'false' if unable to decompress or if the checksum was invalid. - // - // NB: Once the packet has been decompressed, checksum cannot be computed based - // on m_bytes. The checksum was for the compressed packet. - bool - DecompressPacket (); - - Error - StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0); - - bool - JoinListenThread (); - - static lldb::thread_result_t - ListenThread (lldb::thread_arg_t arg); - - // GDB-Remote read thread - // . this thread constantly tries to read from the communication - // class and stores all packets received in a queue. The usual - // threads read requests simply pop packets off the queue in the - // usual order. - // This setup allows us to intercept and handle async packets, such - // as the notify packet. - - // This method is defined as part of communication.h - // when the read thread gets any bytes it will pass them on to this function - void AppendBytesToCache(const uint8_t * bytes, - size_t len, - bool broadcast, - lldb::ConnectionStatus status) override; + uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); } + + std::vector<Entry> m_packets; + uint32_t m_curr_idx; + uint32_t m_total_packet_count; + mutable bool m_dumped_to_log; + }; + + uint32_t m_packet_timeout; + uint32_t m_echo_number; + LazyBool m_supports_qEcho; + History m_history; + bool m_send_acks; + bool m_is_platform; // Set to true if this class represents a platform, + // false if this class represents a debug session for + // a single process + + CompressionType m_compression_type; + + PacketResult SendPacketNoLock(llvm::StringRef payload); + + PacketResult ReadPacket(StringExtractorGDBRemote &response, + uint32_t timeout_usec, bool sync_on_timeout); + + // Pop a packet from the queue in a thread safe manner + PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response, + uint32_t timeout_usec); + + PacketResult + WaitForPacketWithTimeoutMicroSecondsNoLock(StringExtractorGDBRemote &response, + uint32_t timeout_usec, + bool sync_on_timeout); + + bool CompressionIsEnabled() { + return m_compression_type != CompressionType::None; + } + + // If compression is enabled, decompress the packet in m_bytes and update + // m_bytes with the uncompressed version. + // Returns 'true' packet was decompressed and m_bytes is the now-decompressed + // text. + // Returns 'false' if unable to decompress or if the checksum was invalid. + // + // NB: Once the packet has been decompressed, checksum cannot be computed + // based + // on m_bytes. The checksum was for the compressed packet. + bool DecompressPacket(); + + Error StartListenThread(const char *hostname = "127.0.0.1", + uint16_t port = 0); + + bool JoinListenThread(); + + static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg); + + // GDB-Remote read thread + // . this thread constantly tries to read from the communication + // class and stores all packets received in a queue. The usual + // threads read requests simply pop packets off the queue in the + // usual order. + // This setup allows us to intercept and handle async packets, such + // as the notify packet. + + // This method is defined as part of communication.h + // when the read thread gets any bytes it will pass them on to this function + void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast, + lldb::ConnectionStatus status) override; private: - std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue - std::mutex m_packet_queue_mutex; // Mutex for accessing queue - std::condition_variable m_condition_queue_not_empty; // Condition variable to wait for packets + std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue + std::mutex m_packet_queue_mutex; // Mutex for accessing queue + std::condition_variable + m_condition_queue_not_empty; // Condition variable to wait for packets - HostThread m_listen_thread; - std::string m_listen_url; + HostThread m_listen_thread; + std::string m_listen_url; - DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication); + DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 555ae461b1c..6e09196ed21 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "GDBRemoteCommunicationClient.h" // C Includes @@ -15,35 +14,35 @@ #include <sys/stat.h> // C++ Includes -#include <sstream> #include <numeric> +#include <sstream> // Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamGDBRemote.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/LLDBAssert.h" -#include "lldb/Target/Target.h" // Project includes -#include "Utility/StringExtractorGDBRemote.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" +#include "Utility/StringExtractorGDBRemote.h" #include "lldb/Host/Config.h" #include "llvm/ADT/StringSwitch.h" -#if defined (HAVE_LIBCOMPRESSION) +#if defined(HAVE_LIBCOMPRESSION) #include <compression.h> #endif @@ -76,8 +75,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), m_attach_or_wait_reply(eLazyBoolCalculate), m_prepare_for_reg_writing_reply(eLazyBoolCalculate), - m_supports_p(eLazyBoolCalculate), - m_supports_x(eLazyBoolCalculate), + m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate), m_avoid_g_packets(eLazyBoolCalculate), m_supports_QSaveRegisterState(eLazyBoolCalculate), m_supports_qXfer_auxv_read(eLazyBoolCalculate), @@ -88,532 +86,452 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), - m_supports_qProcessInfoPID(true), - m_supports_qfProcessInfo(true), - m_supports_qUserName(true), - m_supports_qGroupName(true), - m_supports_qThreadStopInfo(true), - m_supports_z0(true), - m_supports_z1(true), - m_supports_z2(true), - m_supports_z3(true), - m_supports_z4(true), - m_supports_QEnvironment(true), - m_supports_QEnvironmentHexEncoded(true), - m_supports_qSymbol(true), - m_qSymbol_requests_done(false), - m_supports_qModuleInfo(true), - m_supports_jThreadsInfo(true), - m_curr_pid(LLDB_INVALID_PROCESS_ID), + m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), + m_supports_qUserName(true), m_supports_qGroupName(true), + m_supports_qThreadStopInfo(true), m_supports_z0(true), + m_supports_z1(true), m_supports_z2(true), m_supports_z3(true), + m_supports_z4(true), m_supports_QEnvironment(true), + m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true), + m_qSymbol_requests_done(false), m_supports_qModuleInfo(true), + m_supports_jThreadsInfo(true), m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID), m_curr_tid_run(LLDB_INVALID_THREAD_ID), - m_num_supported_hardware_watchpoints(0), - m_host_arch(), - m_process_arch(), - m_os_version_major(UINT32_MAX), - m_os_version_minor(UINT32_MAX), - m_os_version_update(UINT32_MAX), - m_os_build(), - m_os_kernel(), - m_hostname(), - m_gdb_server_name(), - m_gdb_server_version(UINT32_MAX), - m_default_packet_timeout(0), - m_max_packet_size(0), - m_qSupported_response(), - m_supported_async_json_packets_is_valid(false), - m_supported_async_json_packets_sp() -{ -} + m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(), + m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX), + m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(), + m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX), + m_default_packet_timeout(0), m_max_packet_size(0), + m_qSupported_response(), m_supported_async_json_packets_is_valid(false), + m_supported_async_json_packets_sp() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() -{ - if (IsConnected()) - Disconnect(); +GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() { + if (IsConnected()) + Disconnect(); } -bool -GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) -{ - ResetDiscoverableSettings(false); - - // Start the read thread after we send the handshake ack since if we - // fail to send the handshake ack, there is no reason to continue... - if (SendAck()) - { - // Wait for any responses that might have been queued up in the remote - // GDB server and flush them all - StringExtractorGDBRemote response; - PacketResult packet_result = PacketResult::Success; - const uint32_t timeout_usec = 10 * 1000; // Wait for 10 ms for a response - while (packet_result == PacketResult::Success) - packet_result = ReadPacket (response, timeout_usec, false); - - // The return value from QueryNoAckModeSupported() is true if the packet - // was sent and _any_ response (including UNIMPLEMENTED) was received), - // or false if no response was received. This quickly tells us if we have - // a live connection to a remote GDB server... - if (QueryNoAckModeSupported()) - { - return true; - } - else - { - if (error_ptr) - error_ptr->SetErrorString("failed to get reply to handshake packet"); - } - } - else - { - if (error_ptr) - error_ptr->SetErrorString("failed to send the handshake ack"); - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetEchoSupported () -{ - if (m_supports_qEcho == eLazyBoolCalculate) - { - GetRemoteQSupported(); - } - return m_supports_qEcho == eLazyBoolYes; -} +bool GDBRemoteCommunicationClient::HandshakeWithServer(Error *error_ptr) { + ResetDiscoverableSettings(false); + // Start the read thread after we send the handshake ack since if we + // fail to send the handshake ack, there is no reason to continue... + if (SendAck()) { + // Wait for any responses that might have been queued up in the remote + // GDB server and flush them all + StringExtractorGDBRemote response; + PacketResult packet_result = PacketResult::Success; + const uint32_t timeout_usec = 10 * 1000; // Wait for 10 ms for a response + while (packet_result == PacketResult::Success) + packet_result = ReadPacket(response, timeout_usec, false); -bool -GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported () -{ - if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) - { - GetRemoteQSupported(); + // The return value from QueryNoAckModeSupported() is true if the packet + // was sent and _any_ response (including UNIMPLEMENTED) was received), + // or false if no response was received. This quickly tells us if we have + // a live connection to a remote GDB server... + if (QueryNoAckModeSupported()) { + return true; + } else { + if (error_ptr) + error_ptr->SetErrorString("failed to get reply to handshake packet"); } - return m_supports_augmented_libraries_svr4_read == eLazyBoolYes; + } else { + if (error_ptr) + error_ptr->SetErrorString("failed to send the handshake ack"); + } + return false; } -bool -GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported () -{ - if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) - { - GetRemoteQSupported(); - } - return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes; +bool GDBRemoteCommunicationClient::GetEchoSupported() { + if (m_supports_qEcho == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qEcho == eLazyBoolYes; } -bool -GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported () -{ - if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) - { - GetRemoteQSupported(); - } - return m_supports_qXfer_libraries_read == eLazyBoolYes; +bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() { + if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_augmented_libraries_svr4_read == eLazyBoolYes; } -bool -GDBRemoteCommunicationClient::GetQXferAuxvReadSupported () -{ - if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) - { - GetRemoteQSupported(); - } - return m_supports_qXfer_auxv_read == eLazyBoolYes; +bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() { + if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes; } -bool -GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported () -{ - if (m_supports_qXfer_features_read == eLazyBoolCalculate) - { - GetRemoteQSupported(); - } - return m_supports_qXfer_features_read == eLazyBoolYes; +bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() { + if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qXfer_libraries_read == eLazyBoolYes; } -uint64_t -GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() -{ - if (m_max_packet_size == 0) - { - GetRemoteQSupported(); - } - return m_max_packet_size; +bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() { + if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qXfer_auxv_read == eLazyBoolYes; } -bool -GDBRemoteCommunicationClient::QueryNoAckModeSupported () -{ - if (m_supports_not_sending_acks == eLazyBoolCalculate) - { - m_send_acks = true; - m_supports_not_sending_acks = eLazyBoolNo; - - // This is the first real packet that we'll send in a debug session and it may take a little - // longer than normal to receive a reply. Wait at least 6 seconds for a reply to this packet. - - const uint32_t minimum_timeout = 6; - uint32_t old_timeout = GetPacketTimeoutInMicroSeconds() / lldb_private::TimeValue::MicroSecPerSec; - GDBRemoteCommunication::ScopedTimeout timeout (*this, std::max (old_timeout, minimum_timeout)); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_send_acks = false; - m_supports_not_sending_acks = eLazyBoolYes; - } - return true; - } - } - return false; +bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() { + if (m_supports_qXfer_features_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qXfer_features_read == eLazyBoolYes; } -void -GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported () -{ - if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) - { - m_supports_threads_in_stop_reply = eLazyBoolNo; - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - m_supports_threads_in_stop_reply = eLazyBoolYes; - } - } +uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() { + if (m_max_packet_size == 0) { + GetRemoteQSupported(); + } + return m_max_packet_size; } -bool -GDBRemoteCommunicationClient::GetVAttachOrWaitSupported () -{ - if (m_attach_or_wait_reply == eLazyBoolCalculate) - { - m_attach_or_wait_reply = eLazyBoolNo; - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - m_attach_or_wait_reply = eLazyBoolYes; - } - } - if (m_attach_or_wait_reply == eLazyBoolYes) - return true; - else - return false; -} +bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() { + if (m_supports_not_sending_acks == eLazyBoolCalculate) { + m_send_acks = true; + m_supports_not_sending_acks = eLazyBoolNo; -bool -GDBRemoteCommunicationClient::GetSyncThreadStateSupported () -{ - if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) - { - m_prepare_for_reg_writing_reply = eLazyBoolNo; - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - m_prepare_for_reg_writing_reply = eLazyBoolYes; - } - } - if (m_prepare_for_reg_writing_reply == eLazyBoolYes) - return true; - else - return false; -} + // This is the first real packet that we'll send in a debug session and it + // may take a little + // longer than normal to receive a reply. Wait at least 6 seconds for a + // reply to this packet. + const uint32_t minimum_timeout = 6; + uint32_t old_timeout = GetPacketTimeoutInMicroSeconds() / + lldb_private::TimeValue::MicroSecPerSec; + GDBRemoteCommunication::ScopedTimeout timeout( + *this, std::max(old_timeout, minimum_timeout)); -void -GDBRemoteCommunicationClient::ResetDiscoverableSettings (bool did_exec) -{ - if (did_exec == false) - { - // Hard reset everything, this is when we first connect to a GDB server - m_supports_not_sending_acks = eLazyBoolCalculate; - m_supports_thread_suffix = eLazyBoolCalculate; - m_supports_threads_in_stop_reply = eLazyBoolCalculate; - m_supports_vCont_c = eLazyBoolCalculate; - m_supports_vCont_C = eLazyBoolCalculate; - m_supports_vCont_s = eLazyBoolCalculate; - m_supports_vCont_S = eLazyBoolCalculate; - m_supports_p = eLazyBoolCalculate; - m_supports_x = eLazyBoolCalculate; - m_supports_QSaveRegisterState = eLazyBoolCalculate; - m_qHostInfo_is_valid = eLazyBoolCalculate; - m_curr_pid_is_valid = eLazyBoolCalculate; - m_qGDBServerVersion_is_valid = eLazyBoolCalculate; - m_supports_alloc_dealloc_memory = eLazyBoolCalculate; - m_supports_memory_region_info = eLazyBoolCalculate; - m_prepare_for_reg_writing_reply = eLazyBoolCalculate; - m_attach_or_wait_reply = eLazyBoolCalculate; - m_avoid_g_packets = eLazyBoolCalculate; - m_supports_qXfer_auxv_read = eLazyBoolCalculate; - m_supports_qXfer_libraries_read = eLazyBoolCalculate; - m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; - m_supports_qXfer_features_read = eLazyBoolCalculate; - m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; - m_supports_qProcessInfoPID = true; - m_supports_qfProcessInfo = true; - m_supports_qUserName = true; - m_supports_qGroupName = true; - m_supports_qThreadStopInfo = true; - m_supports_z0 = true; - m_supports_z1 = true; - m_supports_z2 = true; - m_supports_z3 = true; - m_supports_z4 = true; - m_supports_QEnvironment = true; - m_supports_QEnvironmentHexEncoded = true; - m_supports_qSymbol = true; - m_qSymbol_requests_done = false; - m_supports_qModuleInfo = true; - m_host_arch.Clear(); - m_os_version_major = UINT32_MAX; - m_os_version_minor = UINT32_MAX; - m_os_version_update = UINT32_MAX; - m_os_build.clear(); - m_os_kernel.clear(); - m_hostname.clear(); - m_gdb_server_name.clear(); - m_gdb_server_version = UINT32_MAX; - m_default_packet_timeout = 0; - m_max_packet_size = 0; - m_qSupported_response.clear(); - m_supported_async_json_packets_is_valid = false; - m_supported_async_json_packets_sp.reset(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_send_acks = false; + m_supports_not_sending_acks = eLazyBoolYes; + } + return true; } - - // These flags should be reset when we first connect to a GDB server - // and when our inferior process execs - m_qProcessInfo_is_valid = eLazyBoolCalculate; - m_process_arch.Clear(); + } + return false; } -void -GDBRemoteCommunicationClient::GetRemoteQSupported () -{ - // Clear out any capabilities we expect to see in the qSupported response - m_supports_qXfer_auxv_read = eLazyBoolNo; - m_supports_qXfer_libraries_read = eLazyBoolNo; - m_supports_qXfer_libraries_svr4_read = eLazyBoolNo; - m_supports_augmented_libraries_svr4_read = eLazyBoolNo; - m_supports_qXfer_features_read = eLazyBoolNo; - m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit - - // build the qSupported packet - std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"}; - StreamString packet; - packet.PutCString( "qSupported" ); - for ( uint32_t i = 0; i < features.size( ); ++i ) - { - packet.PutCString( i==0 ? ":" : ";"); - packet.PutCString( features[i].c_str( ) ); - } +void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() { + if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) { + m_supports_threads_in_stop_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetData(), - response, - /*send_async=*/false) == PacketResult::Success) - { - const char *response_cstr = response.GetStringRef().c_str(); - - // Hang on to the qSupported packet, so that platforms can do custom - // configuration of the transport before attaching/launching the - // process. - m_qSupported_response = response_cstr; - - if (::strstr (response_cstr, "qXfer:auxv:read+")) - m_supports_qXfer_auxv_read = eLazyBoolYes; - if (::strstr (response_cstr, "qXfer:libraries-svr4:read+")) - m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; - if (::strstr (response_cstr, "augmented-libraries-svr4-read")) - { - m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied - m_supports_augmented_libraries_svr4_read = eLazyBoolYes; - } - if (::strstr (response_cstr, "qXfer:libraries:read+")) - m_supports_qXfer_libraries_read = eLazyBoolYes; - if (::strstr (response_cstr, "qXfer:features:read+")) - m_supports_qXfer_features_read = eLazyBoolYes; - - - // Look for a list of compressions in the features list e.g. - // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma - const char *features_list = ::strstr (response_cstr, "qXfer:features:"); - if (features_list) - { - const char *compressions = ::strstr (features_list, "SupportedCompressions="); - if (compressions) - { - std::vector<std::string> supported_compressions; - compressions += sizeof ("SupportedCompressions=") - 1; - const char *end_of_compressions = strchr (compressions, ';'); - if (end_of_compressions == NULL) - { - end_of_compressions = strchr (compressions, '\0'); - } - const char *current_compression = compressions; - while (current_compression < end_of_compressions) - { - const char *next_compression_name = strchr (current_compression, ','); - const char *end_of_this_word = next_compression_name; - if (next_compression_name == NULL || end_of_compressions < next_compression_name) - { - end_of_this_word = end_of_compressions; - } - - if (end_of_this_word) - { - if (end_of_this_word == current_compression) - { - current_compression++; - } - else - { - std::string this_compression (current_compression, end_of_this_word - current_compression); - supported_compressions.push_back (this_compression); - current_compression = end_of_this_word + 1; - } - } - else - { - supported_compressions.push_back (current_compression); - current_compression = end_of_compressions; - } - } - - if (supported_compressions.size() > 0) - { - MaybeEnableCompression (supported_compressions); - } - } - } - - if (::strstr (response_cstr, "qEcho")) - m_supports_qEcho = eLazyBoolYes; - else - m_supports_qEcho = eLazyBoolNo; - - const char *packet_size_str = ::strstr (response_cstr, "PacketSize="); - if (packet_size_str) - { - StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize=")); - m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); - if (m_max_packet_size == 0) - { - m_max_packet_size = UINT64_MAX; // Must have been a garbled response - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - if (log) - log->Printf ("Garbled PacketSize spec in qSupported response"); - } - } + if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + m_supports_threads_in_stop_reply = eLazyBoolYes; } + } } -bool -GDBRemoteCommunicationClient::GetThreadSuffixSupported () -{ - if (m_supports_thread_suffix == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_thread_suffix = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - m_supports_thread_suffix = eLazyBoolYes; - } +bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() { + if (m_attach_or_wait_reply == eLazyBoolCalculate) { + m_attach_or_wait_reply = eLazyBoolNo; + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + m_attach_or_wait_reply = eLazyBoolYes; } - return m_supports_thread_suffix; + } + if (m_attach_or_wait_reply == eLazyBoolYes) + return true; + else + return false; } -bool -GDBRemoteCommunicationClient::GetVContSupported (char flavor) -{ - if (m_supports_vCont_c == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_vCont_any = eLazyBoolNo; - m_supports_vCont_all = eLazyBoolNo; - m_supports_vCont_c = eLazyBoolNo; - m_supports_vCont_C = eLazyBoolNo; - m_supports_vCont_s = eLazyBoolNo; - m_supports_vCont_S = eLazyBoolNo; - if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success) - { - const char *response_cstr = response.GetStringRef().c_str(); - if (::strstr (response_cstr, ";c")) - m_supports_vCont_c = eLazyBoolYes; - - if (::strstr (response_cstr, ";C")) - m_supports_vCont_C = eLazyBoolYes; - - if (::strstr (response_cstr, ";s")) - m_supports_vCont_s = eLazyBoolYes; - - if (::strstr (response_cstr, ";S")) - m_supports_vCont_S = eLazyBoolYes; - - if (m_supports_vCont_c == eLazyBoolYes && - m_supports_vCont_C == eLazyBoolYes && - m_supports_vCont_s == eLazyBoolYes && - m_supports_vCont_S == eLazyBoolYes) - { - m_supports_vCont_all = eLazyBoolYes; - } - - if (m_supports_vCont_c == eLazyBoolYes || - m_supports_vCont_C == eLazyBoolYes || - m_supports_vCont_s == eLazyBoolYes || - m_supports_vCont_S == eLazyBoolYes) - { - m_supports_vCont_any = eLazyBoolYes; - } - } - } - - switch (flavor) - { - case 'a': return m_supports_vCont_any; - case 'A': return m_supports_vCont_all; - case 'c': return m_supports_vCont_c; - case 'C': return m_supports_vCont_C; - case 's': return m_supports_vCont_s; - case 'S': return m_supports_vCont_S; - default: break; + +bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() { + if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) { + m_prepare_for_reg_writing_reply = eLazyBoolNo; + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + m_prepare_for_reg_writing_reply = eLazyBoolYes; } + } + if (m_prepare_for_reg_writing_reply == eLazyBoolYes) + return true; + else return false; } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(lldb::tid_t tid, StreamString &&payload, - StringExtractorGDBRemote &response, - bool send_async) -{ - Lock lock(*this, send_async); - if (!lock) - { - if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) - log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for %s packet.", __FUNCTION__, - payload.GetString().c_str()); - return PacketResult::ErrorNoSequenceLock; +void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { + if (did_exec == false) { + // Hard reset everything, this is when we first connect to a GDB server + m_supports_not_sending_acks = eLazyBoolCalculate; + m_supports_thread_suffix = eLazyBoolCalculate; + m_supports_threads_in_stop_reply = eLazyBoolCalculate; + m_supports_vCont_c = eLazyBoolCalculate; + m_supports_vCont_C = eLazyBoolCalculate; + m_supports_vCont_s = eLazyBoolCalculate; + m_supports_vCont_S = eLazyBoolCalculate; + m_supports_p = eLazyBoolCalculate; + m_supports_x = eLazyBoolCalculate; + m_supports_QSaveRegisterState = eLazyBoolCalculate; + m_qHostInfo_is_valid = eLazyBoolCalculate; + m_curr_pid_is_valid = eLazyBoolCalculate; + m_qGDBServerVersion_is_valid = eLazyBoolCalculate; + m_supports_alloc_dealloc_memory = eLazyBoolCalculate; + m_supports_memory_region_info = eLazyBoolCalculate; + m_prepare_for_reg_writing_reply = eLazyBoolCalculate; + m_attach_or_wait_reply = eLazyBoolCalculate; + m_avoid_g_packets = eLazyBoolCalculate; + m_supports_qXfer_auxv_read = eLazyBoolCalculate; + m_supports_qXfer_libraries_read = eLazyBoolCalculate; + m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; + m_supports_qXfer_features_read = eLazyBoolCalculate; + m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; + m_supports_qProcessInfoPID = true; + m_supports_qfProcessInfo = true; + m_supports_qUserName = true; + m_supports_qGroupName = true; + m_supports_qThreadStopInfo = true; + m_supports_z0 = true; + m_supports_z1 = true; + m_supports_z2 = true; + m_supports_z3 = true; + m_supports_z4 = true; + m_supports_QEnvironment = true; + m_supports_QEnvironmentHexEncoded = true; + m_supports_qSymbol = true; + m_qSymbol_requests_done = false; + m_supports_qModuleInfo = true; + m_host_arch.Clear(); + m_os_version_major = UINT32_MAX; + m_os_version_minor = UINT32_MAX; + m_os_version_update = UINT32_MAX; + m_os_build.clear(); + m_os_kernel.clear(); + m_hostname.clear(); + m_gdb_server_name.clear(); + m_gdb_server_version = UINT32_MAX; + m_default_packet_timeout = 0; + m_max_packet_size = 0; + m_qSupported_response.clear(); + m_supported_async_json_packets_is_valid = false; + m_supported_async_json_packets_sp.reset(); + } + + // These flags should be reset when we first connect to a GDB server + // and when our inferior process execs + m_qProcessInfo_is_valid = eLazyBoolCalculate; + m_process_arch.Clear(); +} + +void GDBRemoteCommunicationClient::GetRemoteQSupported() { + // Clear out any capabilities we expect to see in the qSupported response + m_supports_qXfer_auxv_read = eLazyBoolNo; + m_supports_qXfer_libraries_read = eLazyBoolNo; + m_supports_qXfer_libraries_svr4_read = eLazyBoolNo; + m_supports_augmented_libraries_svr4_read = eLazyBoolNo; + m_supports_qXfer_features_read = eLazyBoolNo; + m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if + // not, we assume no limit + + // build the qSupported packet + std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"}; + StreamString packet; + packet.PutCString("qSupported"); + for (uint32_t i = 0; i < features.size(); ++i) { + packet.PutCString(i == 0 ? ":" : ";"); + packet.PutCString(features[i].c_str()); + } + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), response, + /*send_async=*/false) == + PacketResult::Success) { + const char *response_cstr = response.GetStringRef().c_str(); + + // Hang on to the qSupported packet, so that platforms can do custom + // configuration of the transport before attaching/launching the + // process. + m_qSupported_response = response_cstr; + + if (::strstr(response_cstr, "qXfer:auxv:read+")) + m_supports_qXfer_auxv_read = eLazyBoolYes; + if (::strstr(response_cstr, "qXfer:libraries-svr4:read+")) + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; + if (::strstr(response_cstr, "augmented-libraries-svr4-read")) { + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied + m_supports_augmented_libraries_svr4_read = eLazyBoolYes; + } + if (::strstr(response_cstr, "qXfer:libraries:read+")) + m_supports_qXfer_libraries_read = eLazyBoolYes; + if (::strstr(response_cstr, "qXfer:features:read+")) + m_supports_qXfer_features_read = eLazyBoolYes; + + // Look for a list of compressions in the features list e.g. + // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma + const char *features_list = ::strstr(response_cstr, "qXfer:features:"); + if (features_list) { + const char *compressions = + ::strstr(features_list, "SupportedCompressions="); + if (compressions) { + std::vector<std::string> supported_compressions; + compressions += sizeof("SupportedCompressions=") - 1; + const char *end_of_compressions = strchr(compressions, ';'); + if (end_of_compressions == NULL) { + end_of_compressions = strchr(compressions, '\0'); + } + const char *current_compression = compressions; + while (current_compression < end_of_compressions) { + const char *next_compression_name = strchr(current_compression, ','); + const char *end_of_this_word = next_compression_name; + if (next_compression_name == NULL || + end_of_compressions < next_compression_name) { + end_of_this_word = end_of_compressions; + } + + if (end_of_this_word) { + if (end_of_this_word == current_compression) { + current_compression++; + } else { + std::string this_compression( + current_compression, end_of_this_word - current_compression); + supported_compressions.push_back(this_compression); + current_compression = end_of_this_word + 1; + } + } else { + supported_compressions.push_back(current_compression); + current_compression = end_of_compressions; + } + } + + if (supported_compressions.size() > 0) { + MaybeEnableCompression(supported_compressions); + } + } + } + + if (::strstr(response_cstr, "qEcho")) + m_supports_qEcho = eLazyBoolYes; + else + m_supports_qEcho = eLazyBoolNo; + + const char *packet_size_str = ::strstr(response_cstr, "PacketSize="); + if (packet_size_str) { + StringExtractorGDBRemote packet_response(packet_size_str + + strlen("PacketSize=")); + m_max_packet_size = + packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); + if (m_max_packet_size == 0) { + m_max_packet_size = UINT64_MAX; // Must have been a garbled response + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("Garbled PacketSize spec in qSupported response"); + } } + } +} - if (GetThreadSuffixSupported()) - payload.Printf(";thread:%4.4" PRIx64 ";", tid); - else - { - if (!SetCurrentThread(tid)) - return PacketResult::ErrorSendFailed; +bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() { + if (m_supports_thread_suffix == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_thread_suffix = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + m_supports_thread_suffix = eLazyBoolYes; } + } + return m_supports_thread_suffix; +} +bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { + if (m_supports_vCont_c == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_vCont_any = eLazyBoolNo; + m_supports_vCont_all = eLazyBoolNo; + m_supports_vCont_c = eLazyBoolNo; + m_supports_vCont_C = eLazyBoolNo; + m_supports_vCont_s = eLazyBoolNo; + m_supports_vCont_S = eLazyBoolNo; + if (SendPacketAndWaitForResponse("vCont?", response, false) == + PacketResult::Success) { + const char *response_cstr = response.GetStringRef().c_str(); + if (::strstr(response_cstr, ";c")) + m_supports_vCont_c = eLazyBoolYes; + + if (::strstr(response_cstr, ";C")) + m_supports_vCont_C = eLazyBoolYes; + + if (::strstr(response_cstr, ";s")) + m_supports_vCont_s = eLazyBoolYes; + + if (::strstr(response_cstr, ";S")) + m_supports_vCont_S = eLazyBoolYes; + + if (m_supports_vCont_c == eLazyBoolYes && + m_supports_vCont_C == eLazyBoolYes && + m_supports_vCont_s == eLazyBoolYes && + m_supports_vCont_S == eLazyBoolYes) { + m_supports_vCont_all = eLazyBoolYes; + } + + if (m_supports_vCont_c == eLazyBoolYes || + m_supports_vCont_C == eLazyBoolYes || + m_supports_vCont_s == eLazyBoolYes || + m_supports_vCont_S == eLazyBoolYes) { + m_supports_vCont_any = eLazyBoolYes; + } + } + } + + switch (flavor) { + case 'a': + return m_supports_vCont_any; + case 'A': + return m_supports_vCont_all; + case 'c': + return m_supports_vCont_c; + case 'C': + return m_supports_vCont_C; + case 's': + return m_supports_vCont_s; + case 'S': + return m_supports_vCont_S; + default: + break; + } + return false; +} - return SendPacketAndWaitForResponseNoLock(payload.GetString(), response); +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( + lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, + bool send_async) { + Lock lock(*this, send_async); + if (!lock) { + if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( + GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) + log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " + "for %s packet.", + __FUNCTION__, payload.GetString().c_str()); + return PacketResult::ErrorNoSequenceLock; + } + + if (GetThreadSuffixSupported()) + payload.Printf(";thread:%4.4" PRIx64 ";", tid); + else { + if (!SetCurrentThread(tid)) + return PacketResult::ErrorSendFailed; + } + + return SendPacketAndWaitForResponseNoLock(payload.GetString(), response); } // Check if the target supports 'p' packet. It sends out a 'p' @@ -621,3414 +539,3040 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(lldb::t // that support is available. // // Takes a valid thread ID because p needs to apply to a thread. -bool -GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid) -{ - if (m_supports_p == eLazyBoolCalculate) - { - m_supports_p = eLazyBoolNo; - StreamString payload; - payload.PutCString("p0"); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == - PacketResult::Success && - response.IsNormalResponse()) - { - m_supports_p = eLazyBoolYes; - } - } - return m_supports_p; -} - -StructuredData::ObjectSP -GDBRemoteCommunicationClient::GetThreadsInfo() -{ - // Get information on all threads at one using the "jThreadsInfo" packet - StructuredData::ObjectSP object_sp; - - if (m_supports_jThreadsInfo) - { - StringExtractorGDBRemote response; - response.SetResponseValidatorToJSON(); - if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - { - m_supports_jThreadsInfo = false; - } - else if (!response.Empty()) - { - object_sp = StructuredData::ParseJSON (response.GetStringRef()); - } - } +bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) { + if (m_supports_p == eLazyBoolCalculate) { + m_supports_p = eLazyBoolNo; + StreamString payload; + payload.PutCString("p0"); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), + response, false) == + PacketResult::Success && + response.IsNormalResponse()) { + m_supports_p = eLazyBoolYes; } - return object_sp; + } + return m_supports_p; } +StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { + // Get information on all threads at one using the "jThreadsInfo" packet + StructuredData::ObjectSP object_sp; -bool -GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported () -{ - if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_jThreadExtendedInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_supports_jThreadExtendedInfo = eLazyBoolYes; - } - } + if (m_supports_jThreadsInfo) { + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == + PacketResult::Success) { + if (response.IsUnsupportedResponse()) { + m_supports_jThreadsInfo = false; + } else if (!response.Empty()) { + object_sp = StructuredData::ParseJSON(response.GetStringRef()); + } } - return m_supports_jThreadExtendedInfo; + } + return object_sp; } -bool -GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported () -{ - if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; - } - } +bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { + if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_jThreadExtendedInfo = eLazyBoolNo; + if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_jThreadExtendedInfo = eLazyBoolYes; + } } - return m_supports_jLoadedDynamicLibrariesInfos; + } + return m_supports_jThreadExtendedInfo; } -bool -GDBRemoteCommunicationClient::GetSharedCacheInfoSupported () -{ - if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_jGetSharedCacheInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_supports_jGetSharedCacheInfo = eLazyBoolYes; - } - } +bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { + if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; + if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; + } } - return m_supports_jGetSharedCacheInfo; + } + return m_supports_jLoadedDynamicLibrariesInfos; } -bool -GDBRemoteCommunicationClient::GetxPacketSupported () -{ - if (m_supports_x == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_x = eLazyBoolNo; - char packet[256]; - snprintf (packet, sizeof (packet), "x0,0"); - if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - m_supports_x = eLazyBoolYes; - } +bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { + if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_jGetSharedCacheInfo = eLazyBoolNo; + if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_jGetSharedCacheInfo = eLazyBoolYes; + } } - return m_supports_x; + } + return m_supports_jGetSharedCacheInfo; } -GDBRemoteCommunicationClient::PacketResult -GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses -( - const char *payload_prefix, - std::string &response_string -) -{ - Lock lock(*this, false); - if (!lock) - { - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending packets with prefix '%s'", - payload_prefix); - return PacketResult::ErrorNoSequenceLock; - } - - response_string = ""; - std::string payload_prefix_str(payload_prefix); - unsigned int response_size = 0x1000; - if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet - response_size = GetRemoteMaxPacketSize(); - } - - for (unsigned int offset = 0; true; offset += response_size) - { - StringExtractorGDBRemote this_response; - // Construct payload - char sizeDescriptor[128]; - snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, response_size); - PacketResult result = SendPacketAndWaitForResponseNoLock(payload_prefix_str + sizeDescriptor, this_response); - if (result != PacketResult::Success) - return result; - - const std::string &this_string = this_response.GetStringRef(); - - // Check for m or l as first character; l seems to mean this is the last chunk - char first_char = *this_string.c_str(); - if (first_char != 'm' && first_char != 'l') - { - return PacketResult::ErrorReplyInvalid; - } - // Concatenate the result so far (skipping 'm' or 'l') - response_string.append(this_string, 1, std::string::npos); - if (first_char == 'l') - // We're done - return PacketResult::Success; +bool GDBRemoteCommunicationClient::GetxPacketSupported() { + if (m_supports_x == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_x = eLazyBoolNo; + char packet[256]; + snprintf(packet, sizeof(packet), "x0,0"); + if (SendPacketAndWaitForResponse(packet, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) + m_supports_x = eLazyBoolYes; } + } + return m_supports_x; } -lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy) -{ - if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) - return m_curr_pid; - - // First try to retrieve the pid via the qProcessInfo request. - GetCurrentProcessInfo (allow_lazy); - if (m_curr_pid_is_valid == eLazyBoolYes) - { - // We really got it. +GDBRemoteCommunicationClient::PacketResult +GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( + const char *payload_prefix, std::string &response_string) { + Lock lock(*this, false); + if (!lock) { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | + GDBR_LOG_PACKETS)); + if (log) + log->Printf("error: failed to get packet sequence mutex, not sending " + "packets with prefix '%s'", + payload_prefix); + return PacketResult::ErrorNoSequenceLock; + } + + response_string = ""; + std::string payload_prefix_str(payload_prefix); + unsigned int response_size = 0x1000; + if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet + response_size = GetRemoteMaxPacketSize(); + } + + for (unsigned int offset = 0; true; offset += response_size) { + StringExtractorGDBRemote this_response; + // Construct payload + char sizeDescriptor[128]; + snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, + response_size); + PacketResult result = SendPacketAndWaitForResponseNoLock( + payload_prefix_str + sizeDescriptor, this_response); + if (result != PacketResult::Success) + return result; + + const std::string &this_string = this_response.GetStringRef(); + + // Check for m or l as first character; l seems to mean this is the last + // chunk + char first_char = *this_string.c_str(); + if (first_char != 'm' && first_char != 'l') { + return PacketResult::ErrorReplyInvalid; + } + // Concatenate the result so far (skipping 'm' or 'l') + response_string.append(this_string, 1, std::string::npos); + if (first_char == 'l') + // We're done + return PacketResult::Success; + } +} + +lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { + if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) + return m_curr_pid; + + // First try to retrieve the pid via the qProcessInfo request. + GetCurrentProcessInfo(allow_lazy); + if (m_curr_pid_is_valid == eLazyBoolYes) { + // We really got it. + return m_curr_pid; + } else { + // If we don't get a response for qProcessInfo, check if $qC gives us a + // result. + // $qC only returns a real process id on older debugserver and lldb-platform + // stubs. + // The gdb remote protocol documents $qC as returning the thread id, which + // newer + // debugserver and lldb-gdbserver stubs return correctly. + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == + PacketResult::Success) { + if (response.GetChar() == 'Q') { + if (response.GetChar() == 'C') { + m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID); + if (m_curr_pid != LLDB_INVALID_PROCESS_ID) { + m_curr_pid_is_valid = eLazyBoolYes; + return m_curr_pid; + } + } + } + } + + // If we don't get a response for $qC, check if $qfThreadID gives us a + // result. + if (m_curr_pid == LLDB_INVALID_PROCESS_ID) { + std::vector<lldb::tid_t> thread_ids; + bool sequence_mutex_unavailable; + size_t size; + size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable); + if (size && sequence_mutex_unavailable == false) { + m_curr_pid = thread_ids.front(); + m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; + } } - else - { - // If we don't get a response for qProcessInfo, check if $qC gives us a result. - // $qC only returns a real process id on older debugserver and lldb-platform stubs. - // The gdb remote protocol documents $qC as returning the thread id, which newer - // debugserver and lldb-gdbserver stubs return correctly. - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == PacketResult::Success) - { - if (response.GetChar() == 'Q') - { - if (response.GetChar() == 'C') - { - m_curr_pid = response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID); - if (m_curr_pid != LLDB_INVALID_PROCESS_ID) - { - m_curr_pid_is_valid = eLazyBoolYes; - return m_curr_pid; - } - } - } - } + } - // If we don't get a response for $qC, check if $qfThreadID gives us a result. - if (m_curr_pid == LLDB_INVALID_PROCESS_ID) - { - std::vector<lldb::tid_t> thread_ids; - bool sequence_mutex_unavailable; - size_t size; - size = GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable); - if (size && sequence_mutex_unavailable == false) - { - m_curr_pid = thread_ids.front(); - m_curr_pid_is_valid = eLazyBoolYes; - return m_curr_pid; - } - } - } - - return LLDB_INVALID_PROCESS_ID; + return LLDB_INVALID_PROCESS_ID; } -bool -GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str) -{ - error_str.clear(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return true; - if (response.GetChar() == 'E') - { - // A string the describes what failed when launching... - error_str = response.GetStringRef().substr(1); - } - else - { - error_str.assign ("unknown error occurred launching process"); - } +bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { + error_str.clear(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), + response, false) == PacketResult::Success) { + if (response.IsOKResponse()) + return true; + if (response.GetChar() == 'E') { + // A string the describes what failed when launching... + error_str = response.GetStringRef().substr(1); + } else { + error_str.assign("unknown error occurred launching process"); + } + } else { + error_str.assign("timed out waiting for app to launch"); + } + return false; +} + +int GDBRemoteCommunicationClient::SendArgumentsPacket( + const ProcessLaunchInfo &launch_info) { + // Since we don't get the send argv0 separate from the executable path, we + // need to + // make sure to use the actual executable path found in the launch_info... + std::vector<const char *> argv; + FileSpec exe_file = launch_info.GetExecutableFile(); + std::string exe_path; + const char *arg = NULL; + const Args &launch_args = launch_info.GetArguments(); + if (exe_file) + exe_path = exe_file.GetPath(false); + else { + arg = launch_args.GetArgumentAtIndex(0); + if (arg) + exe_path = arg; + } + if (!exe_path.empty()) { + argv.push_back(exe_path.c_str()); + for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; + ++i) { + if (arg) + argv.push_back(arg); + } + } + if (!argv.empty()) { + StreamString packet; + packet.PutChar('A'); + for (size_t i = 0, n = argv.size(); i < n; ++i) { + arg = argv[i]; + const int arg_len = strlen(arg); + if (i > 0) + packet.PutChar(','); + packet.Printf("%i,%i,", arg_len * 2, (int)i); + packet.PutBytesAsRawHex8(arg, arg_len); } - else - { - error_str.assign ("timed out waiting for app to launch"); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - return false; + } + return -1; } -int -GDBRemoteCommunicationClient::SendArgumentsPacket (const ProcessLaunchInfo &launch_info) -{ - // Since we don't get the send argv0 separate from the executable path, we need to - // make sure to use the actual executable path found in the launch_info... - std::vector<const char *> argv; - FileSpec exe_file = launch_info.GetExecutableFile(); - std::string exe_path; - const char *arg = NULL; - const Args &launch_args = launch_info.GetArguments(); - if (exe_file) - exe_path = exe_file.GetPath(false); - else - { - arg = launch_args.GetArgumentAtIndex(0); - if (arg) - exe_path = arg; - } - if (!exe_path.empty()) - { - argv.push_back(exe_path.c_str()); - for (uint32_t i=1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; ++i) - { - if (arg) - argv.push_back(arg); +int GDBRemoteCommunicationClient::SendEnvironmentPacket( + char const *name_equal_value) { + if (name_equal_value && name_equal_value[0]) { + StreamString packet; + bool send_hex_encoding = false; + for (const char *p = name_equal_value; + *p != '\0' && send_hex_encoding == false; ++p) { + if (isprint(*p)) { + switch (*p) { + case '$': + case '#': + case '*': + case '}': + send_hex_encoding = true; + break; + default: + break; } + } else { + // We have non printable characters, lets hex encode this... + send_hex_encoding = true; + } } - if (!argv.empty()) - { - StreamString packet; - packet.PutChar('A'); - for (size_t i = 0, n = argv.size(); i < n; ++i) - { - arg = argv[i]; - const int arg_len = strlen(arg); - if (i > 0) - packet.PutChar(','); - packet.Printf("%i,%i,", arg_len * 2, (int)i); - packet.PutBytesAsRawHex8 (arg, arg_len); - } - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; + StringExtractorGDBRemote response; + if (send_hex_encoding) { + if (m_supports_QEnvironmentHexEncoded) { + packet.PutCString("QEnvironmentHexEncoded:"); + packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value)); + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; + if (response.IsUnsupportedResponse()) + m_supports_QEnvironmentHexEncoded = false; } - } - return -1; -} + } -int -GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value) -{ - if (name_equal_value && name_equal_value[0]) - { - StreamString packet; - bool send_hex_encoding = false; - for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p) - { - if (isprint(*p)) - { - switch (*p) - { - case '$': - case '#': - case '*': - case '}': - send_hex_encoding = true; - break; - default: - break; - } - } - else - { - // We have non printable characters, lets hex encode this... - send_hex_encoding = true; - } - } - - StringExtractorGDBRemote response; - if (send_hex_encoding) - { - if (m_supports_QEnvironmentHexEncoded) - { - packet.PutCString("QEnvironmentHexEncoded:"); - packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value)); - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - if (response.IsUnsupportedResponse()) - m_supports_QEnvironmentHexEncoded = false; - } - } - - } - else if (m_supports_QEnvironment) - { - packet.Printf("QEnvironment:%s", name_equal_value); - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - if (response.IsUnsupportedResponse()) - m_supports_QEnvironment = false; - } - } + } else if (m_supports_QEnvironment) { + packet.Printf("QEnvironment:%s", name_equal_value); + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; + if (response.IsUnsupportedResponse()) + m_supports_QEnvironment = false; + } } - return -1; + } + return -1; } -int -GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch) -{ - if (arch && arch[0]) - { - StreamString packet; - packet.Printf("QLaunchArch:%s", arch); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } +int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) { + if (arch && arch[0]) { + StreamString packet; + packet.Printf("QLaunchArch:%s", arch); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - return -1; + } + return -1; } -int -GDBRemoteCommunicationClient::SendLaunchEventDataPacket (char const *data, bool *was_supported) -{ - if (data && *data != '\0') - { - StreamString packet; - packet.Printf("QSetProcessEvent:%s", data); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - if (was_supported) - *was_supported = true; - return 0; - } - else if (response.IsUnsupportedResponse()) - { - if (was_supported) - *was_supported = false; - return -1; - } - else - { - uint8_t error = response.GetError(); - if (was_supported) - *was_supported = true; - if (error) - return error; - } - } +int GDBRemoteCommunicationClient::SendLaunchEventDataPacket( + char const *data, bool *was_supported) { + if (data && *data != '\0') { + StreamString packet; + packet.Printf("QSetProcessEvent:%s", data); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) { + if (was_supported) + *was_supported = true; + return 0; + } else if (response.IsUnsupportedResponse()) { + if (was_supported) + *was_supported = false; + return -1; + } else { + uint8_t error = response.GetError(); + if (was_supported) + *was_supported = true; + if (error) + return error; + } } - return -1; + } + return -1; } -bool -GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major, - uint32_t &minor, - uint32_t &update) -{ - if (GetHostInfo ()) - { - if (m_os_version_major != UINT32_MAX) - { - major = m_os_version_major; - minor = m_os_version_minor; - update = m_os_version_update; - return true; - } +bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major, + uint32_t &minor, + uint32_t &update) { + if (GetHostInfo()) { + if (m_os_version_major != UINT32_MAX) { + major = m_os_version_major; + minor = m_os_version_minor; + update = m_os_version_update; + return true; } - return false; + } + return false; } -bool -GDBRemoteCommunicationClient::GetOSBuildString (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_os_build.empty()) - { - s = m_os_build; - return true; - } +bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) { + if (GetHostInfo()) { + if (!m_os_build.empty()) { + s = m_os_build; + return true; } - s.clear(); - return false; + } + s.clear(); + return false; } - -bool -GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_os_kernel.empty()) - { - s = m_os_kernel; - return true; - } +bool GDBRemoteCommunicationClient::GetOSKernelDescription(std::string &s) { + if (GetHostInfo()) { + if (!m_os_kernel.empty()) { + s = m_os_kernel; + return true; } - s.clear(); - return false; + } + s.clear(); + return false; } -bool -GDBRemoteCommunicationClient::GetHostname (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_hostname.empty()) - { - s = m_hostname; - return true; - } +bool GDBRemoteCommunicationClient::GetHostname(std::string &s) { + if (GetHostInfo()) { + if (!m_hostname.empty()) { + s = m_hostname; + return true; } - s.clear(); - return false; + } + s.clear(); + return false; } -ArchSpec -GDBRemoteCommunicationClient::GetSystemArchitecture () -{ - if (GetHostInfo ()) - return m_host_arch; - return ArchSpec(); +ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() { + if (GetHostInfo()) + return m_host_arch; + return ArchSpec(); } const lldb_private::ArchSpec & -GDBRemoteCommunicationClient::GetProcessArchitecture () -{ - if (m_qProcessInfo_is_valid == eLazyBoolCalculate) - GetCurrentProcessInfo (); - return m_process_arch; +GDBRemoteCommunicationClient::GetProcessArchitecture() { + if (m_qProcessInfo_is_valid == eLazyBoolCalculate) + GetCurrentProcessInfo(); + return m_process_arch; } -bool -GDBRemoteCommunicationClient::GetGDBServerVersion() -{ - if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) - { - m_gdb_server_name.clear(); - m_gdb_server_version = 0; - m_qGDBServerVersion_is_valid = eLazyBoolNo; - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse ("qGDBServerVersion", response, false) == PacketResult::Success) - { - if (response.IsNormalResponse()) - { - llvm::StringRef name, value; - bool success = false; - while (response.GetNameColonValue(name, value)) - { - if (name.equals("name")) - { - success = true; - m_gdb_server_name = value; - } - else if (name.equals("version")) - { - llvm::StringRef major, minor; - std::tie(major, minor) = value.split('.'); - if (!major.getAsInteger(0, m_gdb_server_version)) - success = true; - } - } - if (success) - m_qGDBServerVersion_is_valid = eLazyBoolYes; - } - } - } - return m_qGDBServerVersion_is_valid == eLazyBoolYes; -} +bool GDBRemoteCommunicationClient::GetGDBServerVersion() { + if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { + m_gdb_server_name.clear(); + m_gdb_server_version = 0; + m_qGDBServerVersion_is_valid = eLazyBoolNo; -void -GDBRemoteCommunicationClient::MaybeEnableCompression (std::vector<std::string> supported_compressions) -{ - CompressionType avail_type = CompressionType::None; - std::string avail_name; - -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is available - if (compression_decode_buffer != NULL && avail_type == CompressionType::None) - { - for (auto compression : supported_compressions) - { - if (compression == "lzfse") - { - avail_type = CompressionType::LZFSE; - avail_name = compression; - break; - } - } - } + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) == + PacketResult::Success) { + if (response.IsNormalResponse()) { + llvm::StringRef name, value; + bool success = false; + while (response.GetNameColonValue(name, value)) { + if (name.equals("name")) { + success = true; + m_gdb_server_name = value; + } else if (name.equals("version")) { + llvm::StringRef major, minor; + std::tie(major, minor) = value.split('.'); + if (!major.getAsInteger(0, m_gdb_server_version)) + success = true; + } + } + if (success) + m_qGDBServerVersion_is_valid = eLazyBoolYes; + } + } + } + return m_qGDBServerVersion_is_valid == eLazyBoolYes; +} + +void GDBRemoteCommunicationClient::MaybeEnableCompression( + std::vector<std::string> supported_compressions) { + CompressionType avail_type = CompressionType::None; + std::string avail_name; + +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so test if compression_decode_buffer() is + // available + if (compression_decode_buffer != NULL && + avail_type == CompressionType::None) { + for (auto compression : supported_compressions) { + if (compression == "lzfse") { + avail_type = CompressionType::LZFSE; + avail_name = compression; + break; + } + } + } #endif -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is available - if (compression_decode_buffer != NULL && avail_type == CompressionType::None) - { - for (auto compression : supported_compressions) - { - if (compression == "zlib-deflate") - { - avail_type = CompressionType::ZlibDeflate; - avail_name = compression; - break; - } - } - } +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so test if compression_decode_buffer() is + // available + if (compression_decode_buffer != NULL && + avail_type == CompressionType::None) { + for (auto compression : supported_compressions) { + if (compression == "zlib-deflate") { + avail_type = CompressionType::ZlibDeflate; + avail_name = compression; + break; + } + } + } #endif -#if defined (HAVE_LIBZ) - if (avail_type == CompressionType::None) - { - for (auto compression : supported_compressions) - { - if (compression == "zlib-deflate") - { - avail_type = CompressionType::ZlibDeflate; - avail_name = compression; - break; - } - } +#if defined(HAVE_LIBZ) + if (avail_type == CompressionType::None) { + for (auto compression : supported_compressions) { + if (compression == "zlib-deflate") { + avail_type = CompressionType::ZlibDeflate; + avail_name = compression; + break; + } } + } #endif -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is available - if (compression_decode_buffer != NULL && avail_type == CompressionType::None) - { - for (auto compression : supported_compressions) - { - if (compression == "lz4") - { - avail_type = CompressionType::LZ4; - avail_name = compression; - break; - } - } - } +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so test if compression_decode_buffer() is + // available + if (compression_decode_buffer != NULL && + avail_type == CompressionType::None) { + for (auto compression : supported_compressions) { + if (compression == "lz4") { + avail_type = CompressionType::LZ4; + avail_name = compression; + break; + } + } + } #endif -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is available - if (compression_decode_buffer != NULL && avail_type == CompressionType::None) - { - for (auto compression : supported_compressions) - { - if (compression == "lzma") - { - avail_type = CompressionType::LZMA; - avail_name = compression; - break; - } - } - } +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so test if compression_decode_buffer() is + // available + if (compression_decode_buffer != NULL && + avail_type == CompressionType::None) { + for (auto compression : supported_compressions) { + if (compression == "lzma") { + avail_type = CompressionType::LZMA; + avail_name = compression; + break; + } + } + } #endif - if (avail_type != CompressionType::None) - { - StringExtractorGDBRemote response; - std::string packet = "QEnableCompression:type:" + avail_name + ";"; - if (SendPacketAndWaitForResponse (packet.c_str(), response, false) != PacketResult::Success) - return; - - if (response.IsOKResponse()) - { - m_compression_type = avail_type; - } - } -} + if (avail_type != CompressionType::None) { + StringExtractorGDBRemote response; + std::string packet = "QEnableCompression:type:" + avail_name + ";"; + if (SendPacketAndWaitForResponse(packet.c_str(), response, false) != + PacketResult::Success) + return; -const char * -GDBRemoteCommunicationClient::GetGDBServerProgramName() -{ - if (GetGDBServerVersion()) - { - if (!m_gdb_server_name.empty()) - return m_gdb_server_name.c_str(); + if (response.IsOKResponse()) { + m_compression_type = avail_type; } - return NULL; + } } -uint32_t -GDBRemoteCommunicationClient::GetGDBServerProgramVersion() -{ - if (GetGDBServerVersion()) - return m_gdb_server_version; - return 0; +const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() { + if (GetGDBServerVersion()) { + if (!m_gdb_server_name.empty()) + return m_gdb_server_name.c_str(); + } + return NULL; } -bool -GDBRemoteCommunicationClient::GetDefaultThreadId (lldb::tid_t &tid) -{ - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC",response,false) != PacketResult::Success) - return false; - - if (!response.IsNormalResponse()) - return false; - - if (response.GetChar() == 'Q' && response.GetChar() == 'C') - tid = response.GetHexMaxU32(true, -1); - - return true; +uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { + if (GetGDBServerVersion()) + return m_gdb_server_version; + return 0; } -bool -GDBRemoteCommunicationClient::GetHostInfo (bool force) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS)); - - if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) - { - m_qHostInfo_is_valid = eLazyBoolNo; - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse ("qHostInfo", response, false) == PacketResult::Success) - { - if (response.IsNormalResponse()) - { - llvm::StringRef name; - llvm::StringRef value; - uint32_t cpu = LLDB_INVALID_CPUTYPE; - uint32_t sub = 0; - std::string arch_name; - std::string os_name; - std::string vendor_name; - std::string triple; - std::string distribution_id; - uint32_t pointer_byte_size = 0; - ByteOrder byte_order = eByteOrderInvalid; - uint32_t num_keys_decoded = 0; - while (response.GetNameColonValue(name, value)) - { - if (name.equals("cputype")) - { - // exception type in big endian hex - if (!value.getAsInteger(0, cpu)) - ++num_keys_decoded; - } - else if (name.equals("cpusubtype")) - { - // exception count in big endian hex - if (!value.getAsInteger(0, sub)) - ++num_keys_decoded; - } - else if (name.equals("arch")) - { - arch_name = value; - ++num_keys_decoded; - } - else if (name.equals("triple")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (triple); - ++num_keys_decoded; - } - else if (name.equals("distribution_id")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (distribution_id); - ++num_keys_decoded; - } - else if (name.equals("os_build")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (m_os_build); - ++num_keys_decoded; - } - else if (name.equals("hostname")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (m_hostname); - ++num_keys_decoded; - } - else if (name.equals("os_kernel")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (m_os_kernel); - ++num_keys_decoded; - } - else if (name.equals("ostype")) - { - os_name = value; - ++num_keys_decoded; - } - else if (name.equals("vendor")) - { - vendor_name = value; - ++num_keys_decoded; - } - else if (name.equals("endian")) - { - byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) - .Case("little", eByteOrderLittle) - .Case("big", eByteOrderBig) - .Case("pdp", eByteOrderPDP) - .Default(eByteOrderInvalid); - if (byte_order != eByteOrderInvalid) - ++num_keys_decoded; - } - else if (name.equals("ptrsize")) - { - if (!value.getAsInteger(0, pointer_byte_size)) - ++num_keys_decoded; - } - else if (name.equals("os_version") || name.equals("version")) // Older debugserver binaries used the - // "version" key instead of - // "os_version"... - { - Args::StringToVersion(value.str().c_str(), m_os_version_major, m_os_version_minor, - m_os_version_update); - if (m_os_version_major != UINT32_MAX) - ++num_keys_decoded; - } - else if (name.equals("watchpoint_exceptions_received")) - { - m_watchpoints_trigger_after_instruction = llvm::StringSwitch<LazyBool>(value) - .Case("before", eLazyBoolNo) - .Case("after", eLazyBoolYes) - .Default(eLazyBoolCalculate); - if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate) - ++num_keys_decoded; - } - else if (name.equals("default_packet_timeout")) - { - if (!value.getAsInteger(0, m_default_packet_timeout)) - { - SetPacketTimeout(m_default_packet_timeout); - ++num_keys_decoded; - } - } +bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) { + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qC", response, false) != + PacketResult::Success) + return false; - } - - if (num_keys_decoded > 0) - m_qHostInfo_is_valid = eLazyBoolYes; - - if (triple.empty()) - { - if (arch_name.empty()) - { - if (cpu != LLDB_INVALID_CPUTYPE) - { - m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - - if (!vendor_name.empty()) - m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); - if (!os_name.empty()) - m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); - - } - } - else - { - std::string triple; - triple += arch_name; - if (!vendor_name.empty() || !os_name.empty()) - { - triple += '-'; - if (vendor_name.empty()) - triple += "unknown"; - else - triple += vendor_name; - triple += '-'; - if (os_name.empty()) - triple += "unknown"; - else - triple += os_name; - } - m_host_arch.SetTriple (triple.c_str()); - - llvm::Triple &host_triple = m_host_arch.GetTriple(); - if (host_triple.getVendor() == llvm::Triple::Apple && host_triple.getOS() == llvm::Triple::Darwin) - { - switch (m_host_arch.GetMachine()) - { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::thumb: - host_triple.setOS(llvm::Triple::IOS); - break; - default: - host_triple.setOS(llvm::Triple::MacOSX); - break; - } - } - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - - } - } - else - { - m_host_arch.SetTriple (triple.c_str()); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } + if (!response.IsNormalResponse()) + return false; - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s parsed host architecture as %s, triple as %s from triple text %s", __FUNCTION__, m_host_arch.GetArchitectureName () ? m_host_arch.GetArchitectureName () : "<null-arch-name>", m_host_arch.GetTriple ().getTriple ().c_str(), triple.c_str ()); - } - if (!distribution_id.empty ()) - m_host_arch.SetDistributionId (distribution_id.c_str ()); - } - } - } - return m_qHostInfo_is_valid == eLazyBoolYes; -} + if (response.GetChar() == 'Q' && response.GetChar() == 'C') + tid = response.GetHexMaxU32(true, -1); -int -GDBRemoteCommunicationClient::SendAttach -( - lldb::pid_t pid, - StringExtractorGDBRemote& response -) -{ - if (pid != LLDB_INVALID_PROCESS_ID) - { - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid); - assert (packet_len < (int)sizeof(packet)); - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsErrorResponse()) - return response.GetError(); - return 0; - } - } - return -1; + return true; } -int -GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len) -{ - StreamString packet; - packet.PutCString("I"); - packet.PutBytesAsRawHex8(data, data_len); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - return 0; - } - return response.GetError(); +bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS)); + if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) { + m_qHostInfo_is_valid = eLazyBoolNo; + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qHostInfo", response, false) == + PacketResult::Success) { + if (response.IsNormalResponse()) { + llvm::StringRef name; + llvm::StringRef value; + uint32_t cpu = LLDB_INVALID_CPUTYPE; + uint32_t sub = 0; + std::string arch_name; + std::string os_name; + std::string vendor_name; + std::string triple; + std::string distribution_id; + uint32_t pointer_byte_size = 0; + ByteOrder byte_order = eByteOrderInvalid; + uint32_t num_keys_decoded = 0; + while (response.GetNameColonValue(name, value)) { + if (name.equals("cputype")) { + // exception type in big endian hex + if (!value.getAsInteger(0, cpu)) + ++num_keys_decoded; + } else if (name.equals("cpusubtype")) { + // exception count in big endian hex + if (!value.getAsInteger(0, sub)) + ++num_keys_decoded; + } else if (name.equals("arch")) { + arch_name = value; + ++num_keys_decoded; + } else if (name.equals("triple")) { + StringExtractor extractor(value); + extractor.GetHexByteString(triple); + ++num_keys_decoded; + } else if (name.equals("distribution_id")) { + StringExtractor extractor(value); + extractor.GetHexByteString(distribution_id); + ++num_keys_decoded; + } else if (name.equals("os_build")) { + StringExtractor extractor(value); + extractor.GetHexByteString(m_os_build); + ++num_keys_decoded; + } else if (name.equals("hostname")) { + StringExtractor extractor(value); + extractor.GetHexByteString(m_hostname); + ++num_keys_decoded; + } else if (name.equals("os_kernel")) { + StringExtractor extractor(value); + extractor.GetHexByteString(m_os_kernel); + ++num_keys_decoded; + } else if (name.equals("ostype")) { + os_name = value; + ++num_keys_decoded; + } else if (name.equals("vendor")) { + vendor_name = value; + ++num_keys_decoded; + } else if (name.equals("endian")) { + byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) + .Case("little", eByteOrderLittle) + .Case("big", eByteOrderBig) + .Case("pdp", eByteOrderPDP) + .Default(eByteOrderInvalid); + if (byte_order != eByteOrderInvalid) + ++num_keys_decoded; + } else if (name.equals("ptrsize")) { + if (!value.getAsInteger(0, pointer_byte_size)) + ++num_keys_decoded; + } else if (name.equals("os_version") || + name.equals( + "version")) // Older debugserver binaries used the + // "version" key instead of + // "os_version"... + { + Args::StringToVersion(value.str().c_str(), m_os_version_major, + m_os_version_minor, m_os_version_update); + if (m_os_version_major != UINT32_MAX) + ++num_keys_decoded; + } else if (name.equals("watchpoint_exceptions_received")) { + m_watchpoints_trigger_after_instruction = + llvm::StringSwitch<LazyBool>(value) + .Case("before", eLazyBoolNo) + .Case("after", eLazyBoolYes) + .Default(eLazyBoolCalculate); + if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate) + ++num_keys_decoded; + } else if (name.equals("default_packet_timeout")) { + if (!value.getAsInteger(0, m_default_packet_timeout)) { + SetPacketTimeout(m_default_packet_timeout); + ++num_keys_decoded; + } + } + } + + if (num_keys_decoded > 0) + m_qHostInfo_is_valid = eLazyBoolYes; + + if (triple.empty()) { + if (arch_name.empty()) { + if (cpu != LLDB_INVALID_CPUTYPE) { + m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub); + if (pointer_byte_size) { + assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) { + assert(byte_order == m_host_arch.GetByteOrder()); + } + + if (!vendor_name.empty()) + m_host_arch.GetTriple().setVendorName( + llvm::StringRef(vendor_name)); + if (!os_name.empty()) + m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + } + } else { + std::string triple; + triple += arch_name; + if (!vendor_name.empty() || !os_name.empty()) { + triple += '-'; + if (vendor_name.empty()) + triple += "unknown"; + else + triple += vendor_name; + triple += '-'; + if (os_name.empty()) + triple += "unknown"; + else + triple += os_name; + } + m_host_arch.SetTriple(triple.c_str()); + + llvm::Triple &host_triple = m_host_arch.GetTriple(); + if (host_triple.getVendor() == llvm::Triple::Apple && + host_triple.getOS() == llvm::Triple::Darwin) { + switch (m_host_arch.GetMachine()) { + case llvm::Triple::aarch64: + case llvm::Triple::arm: + case llvm::Triple::thumb: + host_triple.setOS(llvm::Triple::IOS); + break; + default: + host_triple.setOS(llvm::Triple::MacOSX); + break; + } + } + if (pointer_byte_size) { + assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) { + assert(byte_order == m_host_arch.GetByteOrder()); + } + } + } else { + m_host_arch.SetTriple(triple.c_str()); + if (pointer_byte_size) { + assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) { + assert(byte_order == m_host_arch.GetByteOrder()); + } + + if (log) + log->Printf("GDBRemoteCommunicationClient::%s parsed host " + "architecture as %s, triple as %s from triple text %s", + __FUNCTION__, m_host_arch.GetArchitectureName() + ? m_host_arch.GetArchitectureName() + : "<null-arch-name>", + m_host_arch.GetTriple().getTriple().c_str(), + triple.c_str()); + } + if (!distribution_id.empty()) + m_host_arch.SetDistributionId(distribution_id.c_str()); + } + } + } + return m_qHostInfo_is_valid == eLazyBoolYes; +} + +int GDBRemoteCommunicationClient::SendAttach( + lldb::pid_t pid, StringExtractorGDBRemote &response) { + if (pid != LLDB_INVALID_PROCESS_ID) { + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid); + assert(packet_len < (int)sizeof(packet)); + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsErrorResponse()) + return response.GetError(); + return 0; + } + } + return -1; +} + +int GDBRemoteCommunicationClient::SendStdinNotification(const char *data, + size_t data_len) { + StreamString packet; + packet.PutCString("I"); + packet.PutBytesAsRawHex8(data, data_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, + false) == PacketResult::Success) { + return 0; + } + return response.GetError(); } const lldb_private::ArchSpec & -GDBRemoteCommunicationClient::GetHostArchitecture () -{ - if (m_qHostInfo_is_valid == eLazyBoolCalculate) - GetHostInfo (); - return m_host_arch; +GDBRemoteCommunicationClient::GetHostArchitecture() { + if (m_qHostInfo_is_valid == eLazyBoolCalculate) + GetHostInfo(); + return m_host_arch; } -uint32_t -GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout () -{ - if (m_qHostInfo_is_valid == eLazyBoolCalculate) - GetHostInfo (); - return m_default_packet_timeout; +uint32_t GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { + if (m_qHostInfo_is_valid == eLazyBoolCalculate) + GetHostInfo(); + return m_default_packet_timeout; } -addr_t -GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions) -{ - if (m_supports_alloc_dealloc_memory != eLazyBoolNo) - { - m_supports_alloc_dealloc_memory = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", - (uint64_t)size, - permissions & lldb::ePermissionsReadable ? "r" : "", - permissions & lldb::ePermissionsWritable ? "w" : "", - permissions & lldb::ePermissionsExecutable ? "x" : ""); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - m_supports_alloc_dealloc_memory = eLazyBoolNo; - else if (!response.IsErrorResponse()) - return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - } - else - { - m_supports_alloc_dealloc_memory = eLazyBoolNo; - } - } - return LLDB_INVALID_ADDRESS; +addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size, + uint32_t permissions) { + if (m_supports_alloc_dealloc_memory != eLazyBoolNo) { + m_supports_alloc_dealloc_memory = eLazyBoolYes; + char packet[64]; + const int packet_len = ::snprintf( + packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size, + permissions & lldb::ePermissionsReadable ? "r" : "", + permissions & lldb::ePermissionsWritable ? "w" : "", + permissions & lldb::ePermissionsExecutable ? "x" : ""); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsUnsupportedResponse()) + m_supports_alloc_dealloc_memory = eLazyBoolNo; + else if (!response.IsErrorResponse()) + return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); + } else { + m_supports_alloc_dealloc_memory = eLazyBoolNo; + } + } + return LLDB_INVALID_ADDRESS; +} + +bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) { + if (m_supports_alloc_dealloc_memory != eLazyBoolNo) { + m_supports_alloc_dealloc_memory = eLazyBoolYes; + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsUnsupportedResponse()) + m_supports_alloc_dealloc_memory = eLazyBoolNo; + else if (response.IsOKResponse()) + return true; + } else { + m_supports_alloc_dealloc_memory = eLazyBoolNo; + } + } + return false; +} + +Error GDBRemoteCommunicationClient::Detach(bool keep_stopped) { + Error error; + + if (keep_stopped) { + if (m_supports_detach_stay_stopped == eLazyBoolCalculate) { + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:"); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success && + response.IsOKResponse()) { + m_supports_detach_stay_stopped = eLazyBoolYes; + } else { + m_supports_detach_stay_stopped = eLazyBoolNo; + } + } + + if (m_supports_detach_stay_stopped == eLazyBoolNo) { + error.SetErrorString("Stays stopped not supported by this target."); + return error; + } else { + StringExtractorGDBRemote response; + PacketResult packet_result = + SendPacketAndWaitForResponse("D1", 2, response, false); + if (packet_result != PacketResult::Success) + error.SetErrorString("Sending extended disconnect packet failed."); + } + } else { + StringExtractorGDBRemote response; + PacketResult packet_result = + SendPacketAndWaitForResponse("D", 1, response, false); + if (packet_result != PacketResult::Success) + error.SetErrorString("Sending disconnect packet failed."); + } + return error; } -bool -GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr) -{ - if (m_supports_alloc_dealloc_memory != eLazyBoolNo) - { - m_supports_alloc_dealloc_memory = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - m_supports_alloc_dealloc_memory = eLazyBoolNo; - else if (response.IsOKResponse()) - return true; - } - else - { - m_supports_alloc_dealloc_memory = eLazyBoolNo; - } - } - return false; -} +Error GDBRemoteCommunicationClient::GetMemoryRegionInfo( + lldb::addr_t addr, lldb_private::MemoryRegionInfo ®ion_info) { + Error error; + region_info.Clear(); -Error -GDBRemoteCommunicationClient::Detach (bool keep_stopped) -{ - Error error; - - if (keep_stopped) - { - if (m_supports_detach_stay_stopped == eLazyBoolCalculate) - { - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:"); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success - && response.IsOKResponse()) - { - m_supports_detach_stay_stopped = eLazyBoolYes; - } + if (m_supports_memory_region_info != eLazyBoolNo) { + m_supports_memory_region_info = eLazyBoolYes; + char packet[64]; + const int packet_len = ::snprintf( + packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + llvm::StringRef name; + llvm::StringRef value; + addr_t addr_value = LLDB_INVALID_ADDRESS; + bool success = true; + bool saw_permissions = false; + while (success && response.GetNameColonValue(name, value)) { + if (name.equals("start")) { + if (!value.getAsInteger(16, addr_value)) + region_info.GetRange().SetRangeBase(addr_value); + } else if (name.equals("size")) { + if (!value.getAsInteger(16, addr_value)) + region_info.GetRange().SetByteSize(addr_value); + } else if (name.equals("permissions") && + region_info.GetRange().IsValid()) { + saw_permissions = true; + if (region_info.GetRange().Contains(addr)) { + if (value.find('r') != llvm::StringRef::npos) + region_info.SetReadable(MemoryRegionInfo::eYes); else - { - m_supports_detach_stay_stopped = eLazyBoolNo; - } - } + region_info.SetReadable(MemoryRegionInfo::eNo); - if (m_supports_detach_stay_stopped == eLazyBoolNo) - { - error.SetErrorString("Stays stopped not supported by this target."); - return error; - } - else - { - StringExtractorGDBRemote response; - PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false); - if (packet_result != PacketResult::Success) - error.SetErrorString ("Sending extended disconnect packet failed."); - } - } - else - { - StringExtractorGDBRemote response; - PacketResult packet_result = SendPacketAndWaitForResponse ("D", 1, response, false); - if (packet_result != PacketResult::Success) - error.SetErrorString ("Sending disconnect packet failed."); - } - return error; -} + if (value.find('w') != llvm::StringRef::npos) + region_info.SetWritable(MemoryRegionInfo::eYes); + else + region_info.SetWritable(MemoryRegionInfo::eNo); -Error -GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, - lldb_private::MemoryRegionInfo ®ion_info) -{ - Error error; + if (value.find('x') != llvm::StringRef::npos) + region_info.SetExecutable(MemoryRegionInfo::eYes); + else + region_info.SetExecutable(MemoryRegionInfo::eNo); + + region_info.SetMapped(MemoryRegionInfo::eYes); + } else { + // The reported region does not contain this address -- we're + // looking at an unmapped page + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + } + } else if (name.equals("name")) { + StringExtractorGDBRemote name_extractor(value); + std::string name; + name_extractor.GetHexByteString(name); + region_info.SetName(name.c_str()); + } else if (name.equals("error")) { + StringExtractorGDBRemote error_extractor(value); + std::string error_string; + // Now convert the HEX bytes into a string value + error_extractor.GetHexByteString(error_string); + error.SetErrorString(error_string.c_str()); + } + } + + // We got a valid address range back but no permissions -- which means + // this is an unmapped page + if (region_info.GetRange().IsValid() && saw_permissions == false) { + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + } + } else { + m_supports_memory_region_info = eLazyBoolNo; + } + } + + if (m_supports_memory_region_info == eLazyBoolNo) { + error.SetErrorString("qMemoryRegionInfo is not supported"); + } + if (error.Fail()) region_info.Clear(); - - if (m_supports_memory_region_info != eLazyBoolNo) - { - m_supports_memory_region_info = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - llvm::StringRef name; - llvm::StringRef value; - addr_t addr_value = LLDB_INVALID_ADDRESS; - bool success = true; - bool saw_permissions = false; - while (success && response.GetNameColonValue(name, value)) - { - if (name.equals("start")) - { - if (!value.getAsInteger(16, addr_value)) - region_info.GetRange().SetRangeBase(addr_value); - } - else if (name.equals("size")) - { - if (!value.getAsInteger(16, addr_value)) - region_info.GetRange().SetByteSize(addr_value); - } - else if (name.equals("permissions") && region_info.GetRange().IsValid()) - { - saw_permissions = true; - if (region_info.GetRange().Contains (addr)) - { - if (value.find('r') != llvm::StringRef::npos) - region_info.SetReadable (MemoryRegionInfo::eYes); - else - region_info.SetReadable (MemoryRegionInfo::eNo); - - if (value.find('w') != llvm::StringRef::npos) - region_info.SetWritable (MemoryRegionInfo::eYes); - else - region_info.SetWritable (MemoryRegionInfo::eNo); - - if (value.find('x') != llvm::StringRef::npos) - region_info.SetExecutable (MemoryRegionInfo::eYes); - else - region_info.SetExecutable (MemoryRegionInfo::eNo); - - region_info.SetMapped(MemoryRegionInfo::eYes); - } - else - { - // The reported region does not contain this address -- we're looking at an unmapped page - region_info.SetReadable (MemoryRegionInfo::eNo); - region_info.SetWritable (MemoryRegionInfo::eNo); - region_info.SetExecutable (MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - } - } - else if (name.equals("name")) - { - StringExtractorGDBRemote name_extractor(value); - std::string name; - name_extractor.GetHexByteString(name); - region_info.SetName(name.c_str()); - } - else if (name.equals("error")) - { - StringExtractorGDBRemote error_extractor(value); - std::string error_string; - // Now convert the HEX bytes into a string value - error_extractor.GetHexByteString(error_string); - error.SetErrorString(error_string.c_str()); - } - } - - // We got a valid address range back but no permissions -- which means this is an unmapped page - if (region_info.GetRange().IsValid() && saw_permissions == false) - { - region_info.SetReadable (MemoryRegionInfo::eNo); - region_info.SetWritable (MemoryRegionInfo::eNo); - region_info.SetExecutable (MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - } - } - else - { - m_supports_memory_region_info = eLazyBoolNo; - } - } - - if (m_supports_memory_region_info == eLazyBoolNo) - { - error.SetErrorString("qMemoryRegionInfo is not supported"); - } - if (error.Fail()) - region_info.Clear(); - return error; - + return error; } -Error -GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num) -{ - Error error; +Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { + Error error; - if (m_supports_watchpoint_support_info == eLazyBoolYes) - { - num = m_num_supported_hardware_watchpoints; - return error; - } + if (m_supports_watchpoint_support_info == eLazyBoolYes) { + num = m_num_supported_hardware_watchpoints; + return error; + } - // Set num to 0 first. - num = 0; - if (m_supports_watchpoint_support_info != eLazyBoolNo) - { - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:"); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - m_supports_watchpoint_support_info = eLazyBoolYes; - llvm::StringRef name; - llvm::StringRef value; - while (response.GetNameColonValue(name, value)) - { - if (name.equals("num")) - { - value.getAsInteger(0, m_num_supported_hardware_watchpoints); - num = m_num_supported_hardware_watchpoints; - } - } - } - else - { - m_supports_watchpoint_support_info = eLazyBoolNo; + // Set num to 0 first. + num = 0; + if (m_supports_watchpoint_support_info != eLazyBoolNo) { + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:"); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + m_supports_watchpoint_support_info = eLazyBoolYes; + llvm::StringRef name; + llvm::StringRef value; + while (response.GetNameColonValue(name, value)) { + if (name.equals("num")) { + value.getAsInteger(0, m_num_supported_hardware_watchpoints); + num = m_num_supported_hardware_watchpoints; } + } + } else { + m_supports_watchpoint_support_info = eLazyBoolNo; } + } - if (m_supports_watchpoint_support_info == eLazyBoolNo) - { - error.SetErrorString("qWatchpointSupportInfo is not supported"); - } - return error; - + if (m_supports_watchpoint_support_info == eLazyBoolNo) { + error.SetErrorString("qWatchpointSupportInfo is not supported"); + } + return error; } -lldb_private::Error -GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num, bool& after, const ArchSpec &arch) -{ - Error error(GetWatchpointSupportInfo(num)); - if (error.Success()) - error = GetWatchpointsTriggerAfterInstruction(after, arch); - return error; +lldb_private::Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo( + uint32_t &num, bool &after, const ArchSpec &arch) { + Error error(GetWatchpointSupportInfo(num)); + if (error.Success()) + error = GetWatchpointsTriggerAfterInstruction(after, arch); + return error; } lldb_private::Error -GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction (bool &after, const ArchSpec &arch) -{ - Error error; - llvm::Triple::ArchType atype = arch.GetMachine(); - - // we assume watchpoints will happen after running the relevant opcode - // and we only want to override this behavior if we have explicitly - // received a qHostInfo telling us otherwise - if (m_qHostInfo_is_valid != eLazyBoolYes) - { - // On targets like MIPS, watchpoint exceptions are always generated - // before the instruction is executed. The connected target may not - // support qHostInfo or qWatchpointSupportInfo packets. - if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel - || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el) - after = false; - else - after = true; - } +GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( + bool &after, const ArchSpec &arch) { + Error error; + llvm::Triple::ArchType atype = arch.GetMachine(); + + // we assume watchpoints will happen after running the relevant opcode + // and we only want to override this behavior if we have explicitly + // received a qHostInfo telling us otherwise + if (m_qHostInfo_is_valid != eLazyBoolYes) { + // On targets like MIPS, watchpoint exceptions are always generated + // before the instruction is executed. The connected target may not + // support qHostInfo or qWatchpointSupportInfo packets. + if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el) + after = false; else - { - // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo - // if it is not calculated before. - if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && - (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel - || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) - m_watchpoints_trigger_after_instruction = eLazyBoolNo; - - after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); - } - return error; -} - -int -GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) -{ - if (file_spec) - { - std::string path{file_spec.GetPath(false)}; - StreamString packet; - packet.PutCString("QSetSTDIN:"); - packet.PutCStringAsRawHex8(path.c_str()); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) -{ - if (file_spec) - { - std::string path{file_spec.GetPath(false)}; - StreamString packet; - packet.PutCString("QSetSTDOUT:"); - packet.PutCStringAsRawHex8(path.c_str()); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) -{ - if (file_spec) - { - std::string path{file_spec.GetPath(false)}; - StreamString packet; - packet.PutCString("QSetSTDERR:"); - packet.PutCStringAsRawHex8(path.c_str()); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} + after = true; + } else { + // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo + // if it is not calculated before. + if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && + (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) + m_watchpoints_trigger_after_instruction = eLazyBoolNo; + + after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); + } + return error; +} + +int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) { + if (file_spec) { + std::string path{file_spec.GetPath(false)}; + StreamString packet; + packet.PutCString("QSetSTDIN:"); + packet.PutCStringAsRawHex8(path.c_str()); -bool -GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) -{ StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - return false; - if (response.IsErrorResponse()) - return false; - std::string cwd; - response.GetHexByteString(cwd); - working_dir.SetFile(cwd, false, GetHostArchitecture()); - return !cwd.empty(); - } - return false; -} - -int -GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) -{ - if (working_dir) - { - std::string path{working_dir.GetPath(false)}; - StreamString packet; - packet.PutCString("QSetWorkingDir:"); - packet.PutCStringAsRawHex8(path.c_str()); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - return -1; + } + return -1; } -int -GDBRemoteCommunicationClient::SetDisableASLR (bool enable) -{ - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - return -1; -} +int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) { + if (file_spec) { + std::string path{file_spec.GetPath(false)}; + StreamString packet; + packet.PutCString("QSetSTDOUT:"); + packet.PutCStringAsRawHex8(path.c_str()); -int -GDBRemoteCommunicationClient::SetDetachOnError (bool enable) -{ - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDetachOnError:%i", enable ? 1 : 0); - assert (packet_len < (int)sizeof(packet)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - return -1; -} - - -bool -GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) -{ - if (response.IsNormalResponse()) - { - llvm::StringRef name; - llvm::StringRef value; - StringExtractor extractor; - - uint32_t cpu = LLDB_INVALID_CPUTYPE; - uint32_t sub = 0; - std::string vendor; - std::string os_type; - - while (response.GetNameColonValue(name, value)) - { - if (name.equals("pid")) - { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - value.getAsInteger(0, pid); - process_info.SetProcessID(pid); - } - else if (name.equals("ppid")) - { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - value.getAsInteger(0, pid); - process_info.SetParentProcessID(pid); - } - else if (name.equals("uid")) - { - uint32_t uid = UINT32_MAX; - value.getAsInteger(0, uid); - process_info.SetUserID(uid); - } - else if (name.equals("euid")) - { - uint32_t uid = UINT32_MAX; - value.getAsInteger(0, uid); - process_info.SetEffectiveGroupID(uid); - } - else if (name.equals("gid")) - { - uint32_t gid = UINT32_MAX; - value.getAsInteger(0, gid); - process_info.SetGroupID(gid); - } - else if (name.equals("egid")) - { - uint32_t gid = UINT32_MAX; - value.getAsInteger(0, gid); - process_info.SetEffectiveGroupID(gid); - } - else if (name.equals("triple")) - { - StringExtractor extractor(value); - std::string triple; - extractor.GetHexByteString(triple); - process_info.GetArchitecture().SetTriple(triple.c_str()); - } - else if (name.equals("name")) - { - StringExtractor extractor(value); - // The process name from ASCII hex bytes since we can't - // control the characters in a process name - std::string name; - extractor.GetHexByteString(name); - process_info.GetExecutableFile().SetFile(name.c_str(), false); - } - else if (name.equals("cputype")) - { - value.getAsInteger(0, cpu); - } - else if (name.equals("cpusubtype")) - { - value.getAsInteger(0, sub); - } - else if (name.equals("vendor")) - { - vendor = value; - } - else if (name.equals("ostype")) - { - os_type = value; - } - } - - if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) - { - if (vendor == "apple") - { - process_info.GetArchitecture().SetArchitecture (eArchTypeMachO, cpu, sub); - process_info.GetArchitecture().GetTriple().setVendorName (llvm::StringRef (vendor)); - process_info.GetArchitecture().GetTriple().setOSName (llvm::StringRef (os_type)); - } - } - - if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) - return true; - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.Clear(); - - if (m_supports_qProcessInfoPID) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - return DecodeProcessInfoResponse (response, process_info); - } - else - { - m_supports_qProcessInfoPID = false; - return false; - } + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - return false; + } + return -1; } -bool -GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - - if (allow_lazy) - { - if (m_qProcessInfo_is_valid == eLazyBoolYes) - return true; - if (m_qProcessInfo_is_valid == eLazyBoolNo) - return false; - } - - GetHostInfo (); +int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { + if (file_spec) { + std::string path{file_spec.GetPath(false)}; + StreamString packet; + packet.PutCString("QSetSTDERR:"); + packet.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse ("qProcessInfo", response, false) == PacketResult::Success) - { - if (response.IsNormalResponse()) - { - llvm::StringRef name; - llvm::StringRef value; - uint32_t cpu = LLDB_INVALID_CPUTYPE; - uint32_t sub = 0; - std::string arch_name; - std::string os_name; - std::string vendor_name; - std::string triple; - uint32_t pointer_byte_size = 0; - StringExtractor extractor; - ByteOrder byte_order = eByteOrderInvalid; - uint32_t num_keys_decoded = 0; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - while (response.GetNameColonValue(name, value)) - { - if (name.equals("cputype")) - { - if (!value.getAsInteger(16, cpu)) - ++num_keys_decoded; - } - else if (name.equals("cpusubtype")) - { - if (!value.getAsInteger(16, sub)) - ++num_keys_decoded; - } - else if (name.equals("triple")) - { - StringExtractor extractor(value); - extractor.GetHexByteString (triple); - ++num_keys_decoded; - } - else if (name.equals("ostype")) - { - os_name = value; - ++num_keys_decoded; - } - else if (name.equals("vendor")) - { - vendor_name = value; - ++num_keys_decoded; - } - else if (name.equals("endian")) - { - byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) - .Case("little", eByteOrderLittle) - .Case("big", eByteOrderBig) - .Case("pdp", eByteOrderPDP) - .Default(eByteOrderInvalid); - if (byte_order != eByteOrderInvalid) - ++num_keys_decoded; - } - else if (name.equals("ptrsize")) - { - if (!value.getAsInteger(16, pointer_byte_size)) - ++num_keys_decoded; - } - else if (name.equals("pid")) - { - if (!value.getAsInteger(16, pid)) - ++num_keys_decoded; - } - } - if (num_keys_decoded > 0) - m_qProcessInfo_is_valid = eLazyBoolYes; - if (pid != LLDB_INVALID_PROCESS_ID) - { - m_curr_pid_is_valid = eLazyBoolYes; - m_curr_pid = pid; - } - - // Set the ArchSpec from the triple if we have it. - if (!triple.empty ()) - { - m_process_arch.SetTriple (triple.c_str ()); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); - } - } - else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) - { - llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); - - assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); - switch (triple.getObjectFormat()) { - case llvm::Triple::MachO: - m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); - break; - case llvm::Triple::ELF: - m_process_arch.SetArchitecture (eArchTypeELF, cpu, sub); - break; - case llvm::Triple::COFF: - m_process_arch.SetArchitecture (eArchTypeCOFF, cpu, sub); - break; - case llvm::Triple::UnknownObjectFormat: - if (log) - log->Printf("error: failed to determine target architecture"); - return false; - } - - if (pointer_byte_size) - { - assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_process_arch.GetByteOrder()); - } - m_process_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); - m_process_arch.GetTriple().setOSName(llvm::StringRef (os_name)); - m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); - m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); - } - return true; - } - } - else - { - m_qProcessInfo_is_valid = eLazyBoolNo; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - - return false; + } + return -1; } +bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) { + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) == + PacketResult::Success) { + if (response.IsUnsupportedResponse()) + return false; + if (response.IsErrorResponse()) + return false; + std::string cwd; + response.GetHexByteString(cwd); + working_dir.SetFile(cwd, false, GetHostArchitecture()); + return !cwd.empty(); + } + return false; +} + +int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) { + if (working_dir) { + std::string path{working_dir.GetPath(false)}; + StreamString packet; + packet.PutCString("QSetWorkingDir:"); + packet.PutCStringAsRawHex8(path.c_str()); -uint32_t -GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) -{ - process_infos.Clear(); - - if (m_supports_qfProcessInfo) - { - StreamString packet; - packet.PutCString ("qfProcessInfo"); - if (!match_info.MatchAllProcesses()) - { - packet.PutChar (':'); - const char *name = match_info.GetProcessInfo().GetName(); - bool has_name_match = false; - if (name && name[0]) - { - has_name_match = true; - NameMatchType name_match_type = match_info.GetNameMatchType(); - switch (name_match_type) - { - case eNameMatchIgnore: - has_name_match = false; - break; - - case eNameMatchEquals: - packet.PutCString ("name_match:equals;"); - break; - - case eNameMatchContains: - packet.PutCString ("name_match:contains;"); - break; - - case eNameMatchStartsWith: - packet.PutCString ("name_match:starts_with;"); - break; - - case eNameMatchEndsWith: - packet.PutCString ("name_match:ends_with;"); - break; - - case eNameMatchRegularExpression: - packet.PutCString ("name_match:regex;"); - break; - } - if (has_name_match) - { - packet.PutCString ("name:"); - packet.PutBytesAsRawHex8(name, ::strlen(name)); - packet.PutChar (';'); - } - } - - if (match_info.GetProcessInfo().ProcessIDIsValid()) - packet.Printf("pid:%" PRIu64 ";",match_info.GetProcessInfo().GetProcessID()); - if (match_info.GetProcessInfo().ParentProcessIDIsValid()) - packet.Printf("parent_pid:%" PRIu64 ";",match_info.GetProcessInfo().GetParentProcessID()); - if (match_info.GetProcessInfo().UserIDIsValid()) - packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID()); - if (match_info.GetProcessInfo().GroupIDIsValid()) - packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID()); - if (match_info.GetProcessInfo().EffectiveUserIDIsValid()) - packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0); - if (match_info.GetProcessInfo().GetArchitecture().IsValid()) - { - const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); - const llvm::Triple &triple = match_arch.GetTriple(); - packet.PutCString("triple:"); - packet.PutCString(triple.getTriple().c_str()); - packet.PutChar (';'); - } - } - StringExtractorGDBRemote response; - // Increase timeout as the first qfProcessInfo packet takes a long time - // on Android. The value of 1min was arrived at empirically. - GDBRemoteCommunication::ScopedTimeout timeout (*this, 60); - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) - { - do - { - ProcessInstanceInfo process_info; - if (!DecodeProcessInfoResponse (response, process_info)) - break; - process_infos.Append(process_info); - response.GetStringRef().clear(); - response.SetFilePos(0); - } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false) == PacketResult::Success); - } - else - { - m_supports_qfProcessInfo = false; - return 0; - } - } - return process_infos.GetSize(); - -} - -bool -GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name) -{ - if (m_supports_qUserName) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsNormalResponse()) - { - // Make sure we parsed the right number of characters. The response is - // the hex encoded user name and should make up the entire packet. - // If there are any non-hex ASCII bytes, the length won't match below.. - if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) - return true; - } - } - else - { - m_supports_qUserName = false; - return false; - } + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; } - return false; - + } + return -1; } -bool -GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name) -{ - if (m_supports_qGroupName) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsNormalResponse()) - { - // Make sure we parsed the right number of characters. The response is - // the hex encoded group name and should make up the entire packet. - // If there are any non-hex ASCII bytes, the length won't match below.. - if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) - return true; - } - } - else - { - m_supports_qGroupName = false; - return false; - } - } - return false; +int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) { + char packet[32]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; + } + return -1; +} + +int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) { + char packet[32]; + const int packet_len = ::snprintf(packet, sizeof(packet), + "QSetDetachOnError:%i", enable ? 1 : 0); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) + return 0; + uint8_t error = response.GetError(); + if (error) + return error; + } + return -1; } -bool -GDBRemoteCommunicationClient::SetNonStopMode (const bool enable) -{ - // Form non-stop packet request +bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( + StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) { + if (response.IsNormalResponse()) { + llvm::StringRef name; + llvm::StringRef value; + StringExtractor extractor; + + uint32_t cpu = LLDB_INVALID_CPUTYPE; + uint32_t sub = 0; + std::string vendor; + std::string os_type; + + while (response.GetNameColonValue(name, value)) { + if (name.equals("pid")) { + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + value.getAsInteger(0, pid); + process_info.SetProcessID(pid); + } else if (name.equals("ppid")) { + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + value.getAsInteger(0, pid); + process_info.SetParentProcessID(pid); + } else if (name.equals("uid")) { + uint32_t uid = UINT32_MAX; + value.getAsInteger(0, uid); + process_info.SetUserID(uid); + } else if (name.equals("euid")) { + uint32_t uid = UINT32_MAX; + value.getAsInteger(0, uid); + process_info.SetEffectiveGroupID(uid); + } else if (name.equals("gid")) { + uint32_t gid = UINT32_MAX; + value.getAsInteger(0, gid); + process_info.SetGroupID(gid); + } else if (name.equals("egid")) { + uint32_t gid = UINT32_MAX; + value.getAsInteger(0, gid); + process_info.SetEffectiveGroupID(gid); + } else if (name.equals("triple")) { + StringExtractor extractor(value); + std::string triple; + extractor.GetHexByteString(triple); + process_info.GetArchitecture().SetTriple(triple.c_str()); + } else if (name.equals("name")) { + StringExtractor extractor(value); + // The process name from ASCII hex bytes since we can't + // control the characters in a process name + std::string name; + extractor.GetHexByteString(name); + process_info.GetExecutableFile().SetFile(name.c_str(), false); + } else if (name.equals("cputype")) { + value.getAsInteger(0, cpu); + } else if (name.equals("cpusubtype")) { + value.getAsInteger(0, sub); + } else if (name.equals("vendor")) { + vendor = value; + } else if (name.equals("ostype")) { + os_type = value; + } + } + + if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) { + if (vendor == "apple") { + process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu, + sub); + process_info.GetArchitecture().GetTriple().setVendorName( + llvm::StringRef(vendor)); + process_info.GetArchitecture().GetTriple().setOSName( + llvm::StringRef(os_type)); + } + } + + if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + } + return false; +} + +bool GDBRemoteCommunicationClient::GetProcessInfo( + lldb::pid_t pid, ProcessInstanceInfo &process_info) { + process_info.Clear(); + + if (m_supports_qProcessInfoPID) { char packet[32]; - const int packet_len = ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable); + const int packet_len = + ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid); assert(packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - // Send to target - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - if (response.IsOKResponse()) - return true; - - // Failed or not supported - return false; - -} - -static void -MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, uint32_t recv_size) -{ - packet.Clear(); - packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); - uint32_t bytes_left = send_size; - while (bytes_left > 0) - { - if (bytes_left >= 26) - { - packet.PutCString("abcdefghijklmnopqrstuvwxyz"); - bytes_left -= 26; - } - else - { - packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); - bytes_left = 0; - } - } -} - -template<typename T> -T calculate_standard_deviation(const std::vector<T> &v) -{ - T sum = std::accumulate(std::begin(v), std::end(v), T(0)); - T mean = sum / (T)v.size(); - T accum = T(0); - std::for_each (std::begin(v), std::end(v), [&](const T d) { - T delta = d - mean; - accum += delta * delta; - }); - - T stdev = sqrt(accum / (v.size()-1)); - return stdev; -} - -void -GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm) -{ - uint32_t i; - TimeValue start_time, end_time; - uint64_t total_time_nsec; - if (SendSpeedTestPacket (0, 0)) - { - StreamString packet; - if (json) - strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n \"results\" : [", num_packets); - else - strm.Printf("Testing sending %u packets of various sizes:\n", num_packets); - strm.Flush(); - - uint32_t result_idx = 0; - uint32_t send_size; - std::vector<float> packet_times; - - for (send_size = 0; send_size <= max_send; send_size ? send_size *= 2 : send_size = 4) - { - for (uint32_t recv_size = 0; recv_size <= max_recv; recv_size ? recv_size *= 2 : recv_size = 4) - { - MakeSpeedTestPacket (packet, send_size, recv_size); - - packet_times.clear(); - // Test how long it takes to send 'num_packets' packets - start_time = TimeValue::Now(); - for (i=0; i<num_packets; ++i) - { - TimeValue packet_start_time = TimeValue::Now(); - StringExtractorGDBRemote response; - SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); - TimeValue packet_end_time = TimeValue::Now(); - uint64_t packet_time_nsec = packet_end_time.GetAsNanoSecondsSinceJan1_1970() - packet_start_time.GetAsNanoSecondsSinceJan1_1970(); - packet_times.push_back((float)packet_time_nsec); - } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - - float packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - float total_ms = (float)total_time_nsec/(float)TimeValue::NanoSecPerMilliSec; - float average_ms_per_packet = total_ms / num_packets; - const float standard_deviation = calculate_standard_deviation<float>(packet_times); - if (json) - { - strm.Printf ("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 ", \"standard_deviation_nsec\" : %9" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, total_time_nsec, (uint64_t)standard_deviation); - ++result_idx; - } - else - { - strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " sec for %9.2f packets/sec (%10.6f ms per packet) with standard deviation of %10.6f ms\n", - send_size, - recv_size, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second, - average_ms_per_packet, - standard_deviation/(float)TimeValue::NanoSecPerMilliSec); - } - strm.Flush(); - } - } - - const uint64_t k_recv_amount = 4*1024*1024; // Receive amount in bytes - - const float k_recv_amount_mb = (float)k_recv_amount/(1024.0f*1024.0f); - if (json) - strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" : %" PRIu64 ",\n \"results\" : [", k_recv_amount); - else - strm.Printf("Testing receiving %2.1fMB of data using varying receive packet sizes:\n", k_recv_amount_mb); - strm.Flush(); - send_size = 0; - result_idx = 0; - for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) - { - MakeSpeedTestPacket (packet, send_size, recv_size); - - // If we have a receive size, test how long it takes to receive 4MB of data - if (recv_size > 0) - { - start_time = TimeValue::Now(); - uint32_t bytes_read = 0; - uint32_t packet_count = 0; - while (bytes_read < k_recv_amount) - { - StringExtractorGDBRemote response; - SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); - bytes_read += recv_size; - ++packet_count; - } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (1024.0*1024.0); - float packets_per_second = (((float)packet_count)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - float total_ms = (float)total_time_nsec/(float)TimeValue::NanoSecPerMilliSec; - float average_ms_per_packet = total_ms / packet_count; - - if (json) - { - strm.Printf ("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, total_time_nsec); - ++result_idx; - } - else - { - strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to receive %2.1fMB in %" PRIu64 ".%9.9" PRIu64 " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per packet)\n", - send_size, - recv_size, - packet_count, - k_recv_amount_mb, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - mb_second, - packets_per_second, - average_ms_per_packet); - } - strm.Flush(); - } - } - if (json) - strm.Printf("\n ]\n }\n}\n"); - else - strm.EOL(); - } -} - -bool -GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size) -{ + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + return DecodeProcessInfoResponse(response, process_info); + } else { + m_supports_qProcessInfoPID = false; + return false; + } + } + return false; +} + +bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | + GDBR_LOG_PACKETS)); + + if (allow_lazy) { + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + } + + GetHostInfo(); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qProcessInfo", response, false) == + PacketResult::Success) { + if (response.IsNormalResponse()) { + llvm::StringRef name; + llvm::StringRef value; + uint32_t cpu = LLDB_INVALID_CPUTYPE; + uint32_t sub = 0; + std::string arch_name; + std::string os_name; + std::string vendor_name; + std::string triple; + uint32_t pointer_byte_size = 0; + StringExtractor extractor; + ByteOrder byte_order = eByteOrderInvalid; + uint32_t num_keys_decoded = 0; + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + while (response.GetNameColonValue(name, value)) { + if (name.equals("cputype")) { + if (!value.getAsInteger(16, cpu)) + ++num_keys_decoded; + } else if (name.equals("cpusubtype")) { + if (!value.getAsInteger(16, sub)) + ++num_keys_decoded; + } else if (name.equals("triple")) { + StringExtractor extractor(value); + extractor.GetHexByteString(triple); + ++num_keys_decoded; + } else if (name.equals("ostype")) { + os_name = value; + ++num_keys_decoded; + } else if (name.equals("vendor")) { + vendor_name = value; + ++num_keys_decoded; + } else if (name.equals("endian")) { + byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) + .Case("little", eByteOrderLittle) + .Case("big", eByteOrderBig) + .Case("pdp", eByteOrderPDP) + .Default(eByteOrderInvalid); + if (byte_order != eByteOrderInvalid) + ++num_keys_decoded; + } else if (name.equals("ptrsize")) { + if (!value.getAsInteger(16, pointer_byte_size)) + ++num_keys_decoded; + } else if (name.equals("pid")) { + if (!value.getAsInteger(16, pid)) + ++num_keys_decoded; + } + } + if (num_keys_decoded > 0) + m_qProcessInfo_is_valid = eLazyBoolYes; + if (pid != LLDB_INVALID_PROCESS_ID) { + m_curr_pid_is_valid = eLazyBoolYes; + m_curr_pid = pid; + } + + // Set the ArchSpec from the triple if we have it. + if (!triple.empty()) { + m_process_arch.SetTriple(triple.c_str()); + if (pointer_byte_size) { + assert(pointer_byte_size == m_process_arch.GetAddressByteSize()); + } + } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && + !vendor_name.empty()) { + llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); + + assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); + switch (triple.getObjectFormat()) { + case llvm::Triple::MachO: + m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub); + break; + case llvm::Triple::ELF: + m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub); + break; + case llvm::Triple::COFF: + m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub); + break; + case llvm::Triple::UnknownObjectFormat: + if (log) + log->Printf("error: failed to determine target architecture"); + return false; + } + + if (pointer_byte_size) { + assert(pointer_byte_size == m_process_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) { + assert(byte_order == m_process_arch.GetByteOrder()); + } + m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); + m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); + m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + } + return true; + } + } else { + m_qProcessInfo_is_valid = eLazyBoolNo; + } + + return false; +} + +uint32_t GDBRemoteCommunicationClient::FindProcesses( + const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + process_infos.Clear(); + + if (m_supports_qfProcessInfo) { StreamString packet; - packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); - uint32_t bytes_left = send_size; - while (bytes_left > 0) - { - if (bytes_left >= 26) - { - packet.PutCString("abcdefghijklmnopqrstuvwxyz"); - bytes_left -= 26; - } - else - { - packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); - bytes_left = 0; - } + packet.PutCString("qfProcessInfo"); + if (!match_info.MatchAllProcesses()) { + packet.PutChar(':'); + const char *name = match_info.GetProcessInfo().GetName(); + bool has_name_match = false; + if (name && name[0]) { + has_name_match = true; + NameMatchType name_match_type = match_info.GetNameMatchType(); + switch (name_match_type) { + case eNameMatchIgnore: + has_name_match = false; + break; + + case eNameMatchEquals: + packet.PutCString("name_match:equals;"); + break; + + case eNameMatchContains: + packet.PutCString("name_match:contains;"); + break; + + case eNameMatchStartsWith: + packet.PutCString("name_match:starts_with;"); + break; + + case eNameMatchEndsWith: + packet.PutCString("name_match:ends_with;"); + break; + + case eNameMatchRegularExpression: + packet.PutCString("name_match:regex;"); + break; + } + if (has_name_match) { + packet.PutCString("name:"); + packet.PutBytesAsRawHex8(name, ::strlen(name)); + packet.PutChar(';'); + } + } + + if (match_info.GetProcessInfo().ProcessIDIsValid()) + packet.Printf("pid:%" PRIu64 ";", + match_info.GetProcessInfo().GetProcessID()); + if (match_info.GetProcessInfo().ParentProcessIDIsValid()) + packet.Printf("parent_pid:%" PRIu64 ";", + match_info.GetProcessInfo().GetParentProcessID()); + if (match_info.GetProcessInfo().UserIDIsValid()) + packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID()); + if (match_info.GetProcessInfo().GroupIDIsValid()) + packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID()); + if (match_info.GetProcessInfo().EffectiveUserIDIsValid()) + packet.Printf("euid:%u;", + match_info.GetProcessInfo().GetEffectiveUserID()); + if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) + packet.Printf("egid:%u;", + match_info.GetProcessInfo().GetEffectiveGroupID()); + if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) + packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); + if (match_info.GetProcessInfo().GetArchitecture().IsValid()) { + const ArchSpec &match_arch = + match_info.GetProcessInfo().GetArchitecture(); + const llvm::Triple &triple = match_arch.GetTriple(); + packet.PutCString("triple:"); + packet.PutCString(triple.getTriple().c_str()); + packet.PutChar(';'); + } } - StringExtractorGDBRemote response; - return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success; -} - -bool -GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname, - lldb::pid_t &pid, - uint16_t &port, - std::string &socket_name) -{ - pid = LLDB_INVALID_PROCESS_ID; - port = 0; - socket_name.clear(); - + // Increase timeout as the first qfProcessInfo packet takes a long time + // on Android. The value of 1min was arrived at empirically. + GDBRemoteCommunication::ScopedTimeout timeout(*this, 60); + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, + false) == PacketResult::Success) { + do { + ProcessInstanceInfo process_info; + if (!DecodeProcessInfoResponse(response, process_info)) + break; + process_infos.Append(process_info); + response.GetStringRef().clear(); + response.SetFilePos(0); + } while (SendPacketAndWaitForResponse("qsProcessInfo", + strlen("qsProcessInfo"), response, + false) == PacketResult::Success); + } else { + m_supports_qfProcessInfo = false; + return 0; + } + } + return process_infos.GetSize(); +} + +bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid, + std::string &name) { + if (m_supports_qUserName) { + char packet[32]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "qUserName:%i", uid); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsNormalResponse()) { + // Make sure we parsed the right number of characters. The response is + // the hex encoded user name and should make up the entire packet. + // If there are any non-hex ASCII bytes, the length won't match below.. + if (response.GetHexByteString(name) * 2 == + response.GetStringRef().size()) + return true; + } + } else { + m_supports_qUserName = false; + return false; + } + } + return false; +} + +bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid, + std::string &name) { + if (m_supports_qGroupName) { + char packet[32]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid); + assert(packet_len < (int)sizeof(packet)); StringExtractorGDBRemote response; - StreamString stream; - stream.PutCString("qLaunchGDBServer;"); - std::string hostname; - if (remote_accept_hostname && remote_accept_hostname[0]) - hostname = remote_accept_hostname; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsNormalResponse()) { + // Make sure we parsed the right number of characters. The response is + // the hex encoded group name and should make up the entire packet. + // If there are any non-hex ASCII bytes, the length won't match below.. + if (response.GetHexByteString(name) * 2 == + response.GetStringRef().size()) + return true; + } + } else { + m_supports_qGroupName = false; + return false; + } + } + return false; +} + +bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) { + // Form non-stop packet request + char packet[32]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable); + assert(packet_len < (int)sizeof(packet)); + + StringExtractorGDBRemote response; + // Send to target + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) + if (response.IsOKResponse()) + return true; + + // Failed or not supported + return false; +} + +static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, + uint32_t recv_size) { + packet.Clear(); + packet.Printf("qSpeedTest:response_size:%i;data:", recv_size); + uint32_t bytes_left = send_size; + while (bytes_left > 0) { + if (bytes_left >= 26) { + packet.PutCString("abcdefghijklmnopqrstuvwxyz"); + bytes_left -= 26; + } else { + packet.Printf("%*.*s;", bytes_left, bytes_left, + "abcdefghijklmnopqrstuvwxyz"); + bytes_left = 0; + } + } +} + +template <typename T> T calculate_standard_deviation(const std::vector<T> &v) { + T sum = std::accumulate(std::begin(v), std::end(v), T(0)); + T mean = sum / (T)v.size(); + T accum = T(0); + std::for_each(std::begin(v), std::end(v), [&](const T d) { + T delta = d - mean; + accum += delta * delta; + }); + + T stdev = sqrt(accum / (v.size() - 1)); + return stdev; +} + +void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, + uint32_t max_send, + uint32_t max_recv, bool json, + Stream &strm) { + uint32_t i; + TimeValue start_time, end_time; + uint64_t total_time_nsec; + if (SendSpeedTestPacket(0, 0)) { + StreamString packet; + if (json) + strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n " + "\"results\" : [", + num_packets); else - { - if (HostInfo::GetHostname(hostname)) - { - // Make the GDB server we launch only accept connections from this host - stream.Printf("host:%s;", hostname.c_str()); - } - else - { - // Make the GDB server we launch accept connections from any host since we can't figure out the hostname - stream.Printf("host:*;"); + strm.Printf("Testing sending %u packets of various sizes:\n", + num_packets); + strm.Flush(); + + uint32_t result_idx = 0; + uint32_t send_size; + std::vector<float> packet_times; + + for (send_size = 0; send_size <= max_send; + send_size ? send_size *= 2 : send_size = 4) { + for (uint32_t recv_size = 0; recv_size <= max_recv; + recv_size ? recv_size *= 2 : recv_size = 4) { + MakeSpeedTestPacket(packet, send_size, recv_size); + + packet_times.clear(); + // Test how long it takes to send 'num_packets' packets + start_time = TimeValue::Now(); + for (i = 0; i < num_packets; ++i) { + TimeValue packet_start_time = TimeValue::Now(); + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, false); + TimeValue packet_end_time = TimeValue::Now(); + uint64_t packet_time_nsec = + packet_end_time.GetAsNanoSecondsSinceJan1_1970() - + packet_start_time.GetAsNanoSecondsSinceJan1_1970(); + packet_times.push_back((float)packet_time_nsec); + } + end_time = TimeValue::Now(); + total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - + start_time.GetAsNanoSecondsSinceJan1_1970(); + + float packets_per_second = + (((float)num_packets) / (float)total_time_nsec) * + (float)TimeValue::NanoSecPerSec; + float total_ms = + (float)total_time_nsec / (float)TimeValue::NanoSecPerMilliSec; + float average_ms_per_packet = total_ms / num_packets; + const float standard_deviation = + calculate_standard_deviation<float>(packet_times); + if (json) { + strm.Printf("%s\n {\"send_size\" : %6" PRIu32 + ", \"recv_size\" : %6" PRIu32 + ", \"total_time_nsec\" : %12" PRIu64 + ", \"standard_deviation_nsec\" : %9" PRIu64 " }", + result_idx > 0 ? "," : "", send_size, recv_size, + total_time_nsec, (uint64_t)standard_deviation); + ++result_idx; + } else { + strm.Printf( + "qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 + " sec for %9.2f packets/sec (%10.6f ms per packet) with standard " + "deviation of %10.6f ms\n", + send_size, recv_size, total_time_nsec / TimeValue::NanoSecPerSec, + total_time_nsec % TimeValue::NanoSecPerSec, packets_per_second, + average_ms_per_packet, + standard_deviation / (float)TimeValue::NanoSecPerMilliSec); } + strm.Flush(); + } } - // give the process a few seconds to startup - GDBRemoteCommunication::ScopedTimeout timeout (*this, 10); - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) - { - llvm::StringRef name; - llvm::StringRef value; - while (response.GetNameColonValue(name, value)) - { - if (name.equals("port")) - value.getAsInteger(0, port); - else if (name.equals("pid")) - value.getAsInteger(0, pid); - else if (name.compare("socket_name") == 0) - { - StringExtractor extractor(value); - extractor.GetHexByteString(socket_name); - } + const uint64_t k_recv_amount = 4 * 1024 * 1024; // Receive amount in bytes + + const float k_recv_amount_mb = (float)k_recv_amount / (1024.0f * 1024.0f); + if (json) + strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" " + ": %" PRIu64 ",\n \"results\" : [", + k_recv_amount); + else + strm.Printf("Testing receiving %2.1fMB of data using varying receive " + "packet sizes:\n", + k_recv_amount_mb); + strm.Flush(); + send_size = 0; + result_idx = 0; + for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) { + MakeSpeedTestPacket(packet, send_size, recv_size); + + // If we have a receive size, test how long it takes to receive 4MB of + // data + if (recv_size > 0) { + start_time = TimeValue::Now(); + uint32_t bytes_read = 0; + uint32_t packet_count = 0; + while (bytes_read < k_recv_amount) { + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, false); + bytes_read += recv_size; + ++packet_count; + } + end_time = TimeValue::Now(); + total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - + start_time.GetAsNanoSecondsSinceJan1_1970(); + float mb_second = ((((float)k_recv_amount) / (float)total_time_nsec) * + (float)TimeValue::NanoSecPerSec) / + (1024.0 * 1024.0); + float packets_per_second = + (((float)packet_count) / (float)total_time_nsec) * + (float)TimeValue::NanoSecPerSec; + float total_ms = + (float)total_time_nsec / (float)TimeValue::NanoSecPerMilliSec; + float average_ms_per_packet = total_ms / packet_count; + + if (json) { + strm.Printf("%s\n {\"send_size\" : %6" PRIu32 + ", \"recv_size\" : %6" PRIu32 + ", \"total_time_nsec\" : %12" PRIu64 " }", + result_idx > 0 ? "," : "", send_size, recv_size, + total_time_nsec); + ++result_idx; + } else { + strm.Printf("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to " + "receive %2.1fMB in %" PRIu64 ".%9.9" PRIu64 + " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per " + "packet)\n", + send_size, recv_size, packet_count, k_recv_amount_mb, + total_time_nsec / TimeValue::NanoSecPerSec, + total_time_nsec % TimeValue::NanoSecPerSec, mb_second, + packets_per_second, average_ms_per_packet); } - return true; + strm.Flush(); + } } - return false; + if (json) + strm.Printf("\n ]\n }\n}\n"); + else + strm.EOL(); + } +} + +bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size, + uint32_t recv_size) { + StreamString packet; + packet.Printf("qSpeedTest:response_size:%i;data:", recv_size); + uint32_t bytes_left = send_size; + while (bytes_left > 0) { + if (bytes_left >= 26) { + packet.PutCString("abcdefghijklmnopqrstuvwxyz"); + bytes_left -= 26; + } else { + packet.Printf("%*.*s;", bytes_left, bytes_left, + "abcdefghijklmnopqrstuvwxyz"); + bytes_left = 0; + } + } + + StringExtractorGDBRemote response; + return SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), + response, false) == PacketResult::Success; +} + +bool GDBRemoteCommunicationClient::LaunchGDBServer( + const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port, + std::string &socket_name) { + pid = LLDB_INVALID_PROCESS_ID; + port = 0; + socket_name.clear(); + + StringExtractorGDBRemote response; + StreamString stream; + stream.PutCString("qLaunchGDBServer;"); + std::string hostname; + if (remote_accept_hostname && remote_accept_hostname[0]) + hostname = remote_accept_hostname; + else { + if (HostInfo::GetHostname(hostname)) { + // Make the GDB server we launch only accept connections from this host + stream.Printf("host:%s;", hostname.c_str()); + } else { + // Make the GDB server we launch accept connections from any host since we + // can't figure out the hostname + stream.Printf("host:*;"); + } + } + // give the process a few seconds to startup + GDBRemoteCommunication::ScopedTimeout timeout(*this, 10); + + if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + PacketResult::Success) { + llvm::StringRef name; + llvm::StringRef value; + while (response.GetNameColonValue(name, value)) { + if (name.equals("port")) + value.getAsInteger(0, port); + else if (name.equals("pid")) + value.getAsInteger(0, pid); + else if (name.compare("socket_name") == 0) { + StringExtractor extractor(value); + extractor.GetHexByteString(socket_name); + } + } + return true; + } + return false; } -size_t -GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls) -{ - connection_urls.clear(); +size_t GDBRemoteCommunicationClient::QueryGDBServer( + std::vector<std::pair<uint16_t, std::string>> &connection_urls) { + connection_urls.clear(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success) - return 0; + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != + PacketResult::Success) + return 0; - StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef()); - if (!data) - return 0; + StructuredData::ObjectSP data = + StructuredData::ParseJSON(response.GetStringRef()); + if (!data) + return 0; - StructuredData::Array* array = data->GetAsArray(); - if (!array) - return 0; + StructuredData::Array *array = data->GetAsArray(); + if (!array) + return 0; - for (size_t i = 0, count = array->GetSize(); i < count; ++i) - { - StructuredData::Dictionary* element = nullptr; - if (!array->GetItemAtIndexAsDictionary(i, element)) - continue; + for (size_t i = 0, count = array->GetSize(); i < count; ++i) { + StructuredData::Dictionary *element = nullptr; + if (!array->GetItemAtIndexAsDictionary(i, element)) + continue; - uint16_t port = 0; - if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port"))) - port = port_osp->GetIntegerValue(0); + uint16_t port = 0; + if (StructuredData::ObjectSP port_osp = + element->GetValueForKey(llvm::StringRef("port"))) + port = port_osp->GetIntegerValue(0); - std::string socket_name; - if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name"))) - socket_name = socket_name_osp->GetStringValue(); + std::string socket_name; + if (StructuredData::ObjectSP socket_name_osp = + element->GetValueForKey(llvm::StringRef("socket_name"))) + socket_name = socket_name_osp->GetStringValue(); - if (port != 0 || !socket_name.empty()) - connection_urls.emplace_back(port, socket_name); - } - return connection_urls.size(); + if (port != 0 || !socket_name.empty()) + connection_urls.emplace_back(port, socket_name); + } + return connection_urls.size(); } -bool -GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid) -{ - StreamString stream; - stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid); - const char *packet = stream.GetData(); - int packet_len = stream.GetSize(); +bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { + StreamString stream; + stream.Printf("qKillSpawnedProcess:%" PRId64, pid); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - return true; - } - return false; + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) + return true; + } + return false; } -bool -GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid) -{ - if (m_curr_tid == tid) - return true; - - char packet[32]; - int packet_len; - if (tid == UINT64_MAX) - packet_len = ::snprintf (packet, sizeof(packet), "Hg-1"); - else - packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid); - assert (packet_len + 1 < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_curr_tid = tid; - return true; - } +bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) { + if (m_curr_tid == tid) + return true; - /* - * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet. - * The reply from '?' packet could be as simple as 'S05'. There is no packet which can - * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ - if (response.IsUnsupportedResponse() && IsConnected()) - { - m_curr_tid = 1; - return true; - } - } - return false; -} + char packet[32]; + int packet_len; + if (tid == UINT64_MAX) + packet_len = ::snprintf(packet, sizeof(packet), "Hg-1"); + else + packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid); + assert(packet_len + 1 < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_curr_tid = tid; + return true; + } + + /* + * Connected bare-iron target (like YAMON gdb-stub) may not have support for + * Hg packet. + * The reply from '?' packet could be as simple as 'S05'. There is no packet + * which can + * give us pid and/or tid. Assume pid=tid=1 in such cases. + */ + if (response.IsUnsupportedResponse() && IsConnected()) { + m_curr_tid = 1; + return true; + } + } + return false; +} + +bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) { + if (m_curr_tid_run == tid) + return true; -bool -GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid) -{ - if (m_curr_tid_run == tid) + char packet[32]; + int packet_len; + if (tid == UINT64_MAX) + packet_len = ::snprintf(packet, sizeof(packet), "Hc-1"); + else + packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid); + + assert(packet_len + 1 < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_curr_tid_run = tid; + return true; + } + + /* + * Connected bare-iron target (like YAMON gdb-stub) may not have support for + * Hc packet. + * The reply from '?' packet could be as simple as 'S05'. There is no packet + * which can + * give us pid and/or tid. Assume pid=tid=1 in such cases. + */ + if (response.IsUnsupportedResponse() && IsConnected()) { + m_curr_tid_run = 1; + return true; + } + } + return false; +} + +bool GDBRemoteCommunicationClient::GetStopReply( + StringExtractorGDBRemote &response) { + if (SendPacketAndWaitForResponse("?", 1, response, false) == + PacketResult::Success) + return response.IsNormalResponse(); + return false; +} + +bool GDBRemoteCommunicationClient::GetThreadStopInfo( + lldb::tid_t tid, StringExtractorGDBRemote &response) { + if (m_supports_qThreadStopInfo) { + char packet[256]; + int packet_len = + ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid); + assert(packet_len < (int)sizeof(packet)); + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.IsUnsupportedResponse()) + m_supports_qThreadStopInfo = false; + else if (response.IsNormalResponse()) return true; - - char packet[32]; - int packet_len; - if (tid == UINT64_MAX) - packet_len = ::snprintf (packet, sizeof(packet), "Hc-1"); - else - packet_len = ::snprintf (packet, sizeof(packet), "Hc%" PRIx64, tid); - - assert (packet_len + 1 < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - m_curr_tid_run = tid; - return true; - } - - /* - * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet. - * The reply from '?' packet could be as simple as 'S05'. There is no packet which can - * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ - if (response.IsUnsupportedResponse() && IsConnected()) - { - m_curr_tid_run = 1; - return true; - } - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response) -{ - if (SendPacketAndWaitForResponse("?", 1, response, false) == PacketResult::Success) - return response.IsNormalResponse(); - return false; -} - -bool -GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtractorGDBRemote &response) -{ - if (m_supports_qThreadStopInfo) - { - char packet[256]; - int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid); - assert (packet_len < (int)sizeof(packet)); - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.IsUnsupportedResponse()) - m_supports_qThreadStopInfo = false; - else if (response.IsNormalResponse()) - return true; - else - return false; - } - else - { - m_supports_qThreadStopInfo = false; - } + else + return false; + } else { + m_supports_qThreadStopInfo = false; } - return false; + } + return false; } +uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( + GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, + __FUNCTION__, insert ? "add" : "remove", addr); -uint8_t -GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, - __FUNCTION__, insert ? "add" : "remove", addr); - - // Check if the stub is known not to support this breakpoint type - if (!SupportsGDBStoppointPacket(type)) + // Check if the stub is known not to support this breakpoint type + if (!SupportsGDBStoppointPacket(type)) + return UINT8_MAX; + // Construct the breakpoint packet + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x", + insert ? 'Z' : 'z', type, addr, length); + // Check we haven't overwritten the end of the packet buffer + assert(packet_len + 1 < (int)sizeof(packet)); + StringExtractorGDBRemote response; + // Make sure the response is either "OK", "EXX" where XX are two hex digits, + // or "" (unsupported) + response.SetResponseValidatorToOKErrorNotSupported(); + // Try to send the breakpoint packet, and check that it was correctly sent + if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == + PacketResult::Success) { + // Receive and OK packet when the breakpoint successfully placed + if (response.IsOKResponse()) + return 0; + + // Error while setting breakpoint, send back specific error + if (response.IsErrorResponse()) + return response.GetError(); + + // Empty packet informs us that breakpoint is not supported + if (response.IsUnsupportedResponse()) { + // Disable this breakpoint type since it is unsupported + switch (type) { + case eBreakpointSoftware: + m_supports_z0 = false; + break; + case eBreakpointHardware: + m_supports_z1 = false; + break; + case eWatchpointWrite: + m_supports_z2 = false; + break; + case eWatchpointRead: + m_supports_z3 = false; + break; + case eWatchpointReadWrite: + m_supports_z4 = false; + break; + case eStoppointInvalid: return UINT8_MAX; - // Construct the breakpoint packet - char packet[64]; - const int packet_len = ::snprintf (packet, - sizeof(packet), - "%c%i,%" PRIx64 ",%x", - insert ? 'Z' : 'z', - type, - addr, - length); - // Check we haven't overwritten the end of the packet buffer - assert (packet_len + 1 < (int)sizeof(packet)); - StringExtractorGDBRemote response; - // Make sure the response is either "OK", "EXX" where XX are two hex digits, or "" (unsupported) - response.SetResponseValidatorToOKErrorNotSupported(); - // Try to send the breakpoint packet, and check that it was correctly sent - if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success) - { - // Receive and OK packet when the breakpoint successfully placed - if (response.IsOKResponse()) - return 0; - - // Error while setting breakpoint, send back specific error - if (response.IsErrorResponse()) - return response.GetError(); - - // Empty packet informs us that breakpoint is not supported - if (response.IsUnsupportedResponse()) - { - // Disable this breakpoint type since it is unsupported - switch (type) - { - case eBreakpointSoftware: m_supports_z0 = false; break; - case eBreakpointHardware: m_supports_z1 = false; break; - case eWatchpointWrite: m_supports_z2 = false; break; - case eWatchpointRead: m_supports_z3 = false; break; - case eWatchpointReadWrite: m_supports_z4 = false; break; - case eStoppointInvalid: return UINT8_MAX; - } - } + } } - // Signal generic failure - return UINT8_MAX; + } + // Signal generic failure + return UINT8_MAX; } -size_t -GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids, - bool &sequence_mutex_unavailable) -{ - thread_ids.clear(); +size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( + std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) { + thread_ids.clear(); - Lock lock(*this, false); - if (lock) - { - sequence_mutex_unavailable = false; - StringExtractorGDBRemote response; - - PacketResult packet_result; - for (packet_result = SendPacketAndWaitForResponseNoLock("qfThreadInfo", response); - packet_result == PacketResult::Success && response.IsNormalResponse(); - packet_result = SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) - { - char ch = response.GetChar(); - if (ch == 'l') - break; - if (ch == 'm') - { - do - { - tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); - - if (tid != LLDB_INVALID_THREAD_ID) - { - thread_ids.push_back (tid); - } - ch = response.GetChar(); // Skip the command separator - } while (ch == ','); // Make sure we got a comma separator - } - } + Lock lock(*this, false); + if (lock) { + sequence_mutex_unavailable = false; + StringExtractorGDBRemote response; - /* - * Connected bare-iron target (like YAMON gdb-stub) may not have support for - * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could - * be as simple as 'S05'. There is no packet which can give us pid and/or tid. - * Assume pid=tid=1 in such cases. - */ - if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected()) - { - thread_ids.push_back (1); - } - } - else - { -#if defined (LLDB_CONFIGURATION_DEBUG) - // assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex"); + PacketResult packet_result; + for (packet_result = + SendPacketAndWaitForResponseNoLock("qfThreadInfo", response); + packet_result == PacketResult::Success && response.IsNormalResponse(); + packet_result = + SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) { + char ch = response.GetChar(); + if (ch == 'l') + break; + if (ch == 'm') { + do { + tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); + + if (tid != LLDB_INVALID_THREAD_ID) { + thread_ids.push_back(tid); + } + ch = response.GetChar(); // Skip the command separator + } while (ch == ','); // Make sure we got a comma separator + } + } + + /* + * Connected bare-iron target (like YAMON gdb-stub) may not have support for + * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet + * could + * be as simple as 'S05'. There is no packet which can give us pid and/or + * tid. + * Assume pid=tid=1 in such cases. + */ + if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && + IsConnected()) { + thread_ids.push_back(1); + } + } else { +#if defined(LLDB_CONFIGURATION_DEBUG) +// assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the +// sequence mutex"); #else - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'"); + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | + GDBR_LOG_PACKETS)); + if (log) + log->Printf("error: failed to get packet sequence mutex, not sending " + "packet 'qfThreadInfo'"); #endif - sequence_mutex_unavailable = true; - } - return thread_ids.size(); -} - -lldb::addr_t -GDBRemoteCommunicationClient::GetShlibInfoAddr() -{ - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) != PacketResult::Success || !response.IsNormalResponse()) - return LLDB_INVALID_ADDRESS; - return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); -} - -lldb_private::Error -GDBRemoteCommunicationClient::RunShellCommand(const char *command, // Shouldn't be NULL - const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory - int *status_ptr, // Pass NULL if you don't want the process exit status - int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit - std::string *command_output, // Pass NULL if you don't want the command output - uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish -{ - lldb_private::StreamString stream; - stream.PutCString("qPlatform_shell:"); - stream.PutBytesAsRawHex8(command, strlen(command)); - stream.PutChar(','); - stream.PutHex32(timeout_sec); - if (working_dir) - { - std::string path{working_dir.GetPath(false)}; - stream.PutChar(','); - stream.PutCStringAsRawHex8(path.c_str()); - } - const char *packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - return Error("malformed reply"); - if (response.GetChar() != ',') - return Error("malformed reply"); - uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX); - if (exitcode == UINT32_MAX) - return Error("unable to run remote process"); - else if (status_ptr) - *status_ptr = exitcode; - if (response.GetChar() != ',') - return Error("malformed reply"); - uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX); - if (signo_ptr) - *signo_ptr = signo; - if (response.GetChar() != ',') - return Error("malformed reply"); - std::string output; - response.GetEscapedBinaryData(output); - if (command_output) - command_output->assign(output); - return Error(); - } - return Error("unable to send packet"); -} - -Error -GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, - uint32_t file_permissions) -{ - std::string path{file_spec.GetPath(false)}; - lldb_private::StreamString stream; - stream.PutCString("qPlatform_mkdir:"); - stream.PutHex32(file_permissions); - stream.PutChar(','); - stream.PutCStringAsRawHex8(path.c_str()); - const char *packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != PacketResult::Success) - return Error("failed to send '%s' packet", packet); - - if (response.GetChar() != 'F') - return Error("invalid response to '%s' packet", packet); - - return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); + sequence_mutex_unavailable = true; + } + return thread_ids.size(); } -Error -GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, - uint32_t file_permissions) -{ - std::string path{file_spec.GetPath(false)}; - lldb_private::StreamString stream; - stream.PutCString("qPlatform_chmod:"); - stream.PutHex32(file_permissions); +lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() { + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) != + PacketResult::Success || + !response.IsNormalResponse()) + return LLDB_INVALID_ADDRESS; + return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); +} + +lldb_private::Error GDBRemoteCommunicationClient::RunShellCommand( + const char *command, // Shouldn't be NULL + const FileSpec & + working_dir, // Pass empty FileSpec to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the + // process to exit + std::string + *command_output, // Pass NULL if you don't want the command output + uint32_t + timeout_sec) // Timeout in seconds to wait for shell program to finish +{ + lldb_private::StreamString stream; + stream.PutCString("qPlatform_shell:"); + stream.PutBytesAsRawHex8(command, strlen(command)); + stream.PutChar(','); + stream.PutHex32(timeout_sec); + if (working_dir) { + std::string path{working_dir.GetPath(false)}; stream.PutChar(','); stream.PutCStringAsRawHex8(path.c_str()); - const char *packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != PacketResult::Success) - return Error("failed to send '%s' packet", packet); - - if (response.GetChar() != 'F') - return Error("invalid response to '%s' packet", packet); - - return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); -} - -static uint64_t -ParseHostIOPacketResponse (StringExtractorGDBRemote &response, - uint64_t fail_result, - Error &error) -{ - response.SetFilePos(0); + } + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { if (response.GetChar() != 'F') - return fail_result; - int32_t result = response.GetS32 (-2); - if (result == -2) - return fail_result; - if (response.GetChar() == ',') - { - int result_errno = response.GetS32 (-2); - if (result_errno != -2) - error.SetError(result_errno, eErrorTypePOSIX); - else - error.SetError(-1, eErrorTypeGeneric); - } + return Error("malformed reply"); + if (response.GetChar() != ',') + return Error("malformed reply"); + uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX); + if (exitcode == UINT32_MAX) + return Error("unable to run remote process"); + else if (status_ptr) + *status_ptr = exitcode; + if (response.GetChar() != ',') + return Error("malformed reply"); + uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX); + if (signo_ptr) + *signo_ptr = signo; + if (response.GetChar() != ',') + return Error("malformed reply"); + std::string output; + response.GetEscapedBinaryData(output); + if (command_output) + command_output->assign(output); + return Error(); + } + return Error("unable to send packet"); +} + +Error GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { + std::string path{file_spec.GetPath(false)}; + lldb_private::StreamString stream; + stream.PutCString("qPlatform_mkdir:"); + stream.PutHex32(file_permissions); + stream.PutChar(','); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != + PacketResult::Success) + return Error("failed to send '%s' packet", packet); + + if (response.GetChar() != 'F') + return Error("invalid response to '%s' packet", packet); + + return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); +} + +Error GDBRemoteCommunicationClient::SetFilePermissions( + const FileSpec &file_spec, uint32_t file_permissions) { + std::string path{file_spec.GetPath(false)}; + lldb_private::StreamString stream; + stream.PutCString("qPlatform_chmod:"); + stream.PutHex32(file_permissions); + stream.PutChar(','); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != + PacketResult::Success) + return Error("failed to send '%s' packet", packet); + + if (response.GetChar() != 'F') + return Error("invalid response to '%s' packet", packet); + + return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX); +} + +static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, + uint64_t fail_result, Error &error) { + response.SetFilePos(0); + if (response.GetChar() != 'F') + return fail_result; + int32_t result = response.GetS32(-2); + if (result == -2) + return fail_result; + if (response.GetChar() == ',') { + int result_errno = response.GetS32(-2); + if (result_errno != -2) + error.SetError(result_errno, eErrorTypePOSIX); else - error.Clear(); - return result; + error.SetError(-1, eErrorTypeGeneric); + } else + error.Clear(); + return result; } lldb::user_id_t -GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec, - uint32_t flags, - mode_t mode, - Error &error) -{ - std::string path(file_spec.GetPath(false)); - lldb_private::StreamString stream; - stream.PutCString("vFile:open:"); - if (path.empty()) - return UINT64_MAX; - stream.PutCStringAsRawHex8(path.c_str()); - stream.PutChar(','); - stream.PutHex32(flags); - stream.PutChar(','); - stream.PutHex32(mode); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - return ParseHostIOPacketResponse (response, UINT64_MAX, error); - } +GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, + uint32_t flags, mode_t mode, + Error &error) { + std::string path(file_spec.GetPath(false)); + lldb_private::StreamString stream; + stream.PutCString("vFile:open:"); + if (path.empty()) return UINT64_MAX; -} - -bool -GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd, - Error &error) -{ - lldb_private::StreamString stream; - stream.Printf("vFile:close:%i", (int)fd); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - return ParseHostIOPacketResponse (response, -1, error) == 0; - } - return false; + stream.PutCStringAsRawHex8(path.c_str()); + stream.PutChar(','); + stream.PutHex32(flags); + stream.PutChar(','); + stream.PutHex32(mode); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + return ParseHostIOPacketResponse(response, UINT64_MAX, error); + } + return UINT64_MAX; +} + +bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, Error &error) { + lldb_private::StreamString stream; + stream.Printf("vFile:close:%i", (int)fd); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + return ParseHostIOPacketResponse(response, -1, error) == 0; + } + return false; } // Extension of host I/O packets to get the file size. -lldb::user_id_t -GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec) -{ - std::string path(file_spec.GetPath(false)); - lldb_private::StreamString stream; - stream.PutCString("vFile:size:"); - stream.PutCStringAsRawHex8(path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - return UINT64_MAX; - uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX); - return retcode; - } - return UINT64_MAX; -} - -Error -GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, - uint32_t &file_permissions) -{ - std::string path{file_spec.GetPath(false)}; - Error error; - lldb_private::StreamString stream; - stream.PutCString("vFile:mode:"); - stream.PutCStringAsRawHex8(path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - { - error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet); - } - else - { - const uint32_t mode = response.GetS32(-1); - if (static_cast<int32_t>(mode) == -1) - { - if (response.GetChar() == ',') - { - int response_errno = response.GetS32(-1); - if (response_errno > 0) - error.SetError(response_errno, lldb::eErrorTypePOSIX); - else - error.SetErrorToGenericError(); - } - else - error.SetErrorToGenericError(); - } - else - { - file_permissions = mode & (S_IRWXU|S_IRWXG|S_IRWXO); - } - } - } - else - { - error.SetErrorStringWithFormat ("failed to send '%s' packet", packet); - } - return error; -} - -uint64_t -GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd, - uint64_t offset, - void *dst, - uint64_t dst_len, - Error &error) -{ - lldb_private::StreamString stream; - stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - return 0; - uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX); - if (retcode == UINT32_MAX) - return retcode; - const char next = (response.Peek() ? *response.Peek() : 0); - if (next == ',') - return 0; - if (next == ';') - { - response.GetChar(); // skip the semicolon - std::string buffer; - if (response.GetEscapedBinaryData(buffer)) - { - const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size()); - if (data_to_write > 0) - memcpy(dst, &buffer[0], data_to_write); - return data_to_write; - } - } - } - return 0; -} - -uint64_t -GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd, - uint64_t offset, - const void* src, - uint64_t src_len, - Error &error) -{ - lldb_private::StreamGDBRemote stream; - stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); - stream.PutEscapedBytes(src, src_len); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - { - error.SetErrorStringWithFormat("write file failed"); - return 0; - } - uint64_t bytes_written = response.GetU64(UINT64_MAX); - if (bytes_written == UINT64_MAX) - { +lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( + const lldb_private::FileSpec &file_spec) { + std::string path(file_spec.GetPath(false)); + lldb_private::StreamString stream; + stream.PutCString("vFile:size:"); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') + return UINT64_MAX; + uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX); + return retcode; + } + return UINT64_MAX; +} + +Error GDBRemoteCommunicationClient::GetFilePermissions( + const FileSpec &file_spec, uint32_t &file_permissions) { + std::string path{file_spec.GetPath(false)}; + Error error; + lldb_private::StreamString stream; + stream.PutCString("vFile:mode:"); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') { + error.SetErrorStringWithFormat("invalid response to '%s' packet", packet); + } else { + const uint32_t mode = response.GetS32(-1); + if (static_cast<int32_t>(mode) == -1) { + if (response.GetChar() == ',') { + int response_errno = response.GetS32(-1); + if (response_errno > 0) + error.SetError(response_errno, lldb::eErrorTypePOSIX); + else error.SetErrorToGenericError(); - if (response.GetChar() == ',') - { - int response_errno = response.GetS32(-1); - if (response_errno > 0) - error.SetError(response_errno, lldb::eErrorTypePOSIX); - } - return 0; - } - return bytes_written; - } - else - { - error.SetErrorString ("failed to send vFile:pwrite packet"); - } - return 0; -} - -Error -GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, const FileSpec &dst) -{ - std::string src_path{src.GetPath(false)}, - dst_path{dst.GetPath(false)}; - Error error; - lldb_private::StreamGDBRemote stream; - stream.PutCString("vFile:symlink:"); - // the unix symlink() command reverses its parameters where the dst if first, - // so we follow suit here - stream.PutCStringAsRawHex8(dst_path.c_str()); - stream.PutChar(','); - stream.PutCStringAsRawHex8(src_path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() == 'F') - { - uint32_t result = response.GetU32(UINT32_MAX); - if (result != 0) - { - error.SetErrorToGenericError(); - if (response.GetChar() == ',') - { - int response_errno = response.GetS32(-1); - if (response_errno > 0) - error.SetError(response_errno, lldb::eErrorTypePOSIX); - } - } - } - else - { - // Should have returned with 'F<result>[,<errno>]' - error.SetErrorStringWithFormat("symlink failed"); - } - } - else - { - error.SetErrorString ("failed to send vFile:symlink packet"); - } - return error; -} - -Error -GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) -{ - std::string path{file_spec.GetPath(false)}; - Error error; - lldb_private::StreamGDBRemote stream; - stream.PutCString("vFile:unlink:"); - // the unix symlink() command reverses its parameters where the dst if first, - // so we follow suit here - stream.PutCStringAsRawHex8(path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() == 'F') - { - uint32_t result = response.GetU32(UINT32_MAX); - if (result != 0) - { - error.SetErrorToGenericError(); - if (response.GetChar() == ',') - { - int response_errno = response.GetS32(-1); - if (response_errno > 0) - error.SetError(response_errno, lldb::eErrorTypePOSIX); - } - } - } - else - { - // Should have returned with 'F<result>[,<errno>]' - error.SetErrorStringWithFormat("unlink failed"); - } - } - else - { - error.SetErrorString ("failed to send vFile:unlink packet"); - } - return error; + } else + error.SetErrorToGenericError(); + } else { + file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + } + } else { + error.SetErrorStringWithFormat("failed to send '%s' packet", packet); + } + return error; +} + +uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd, + uint64_t offset, void *dst, + uint64_t dst_len, + Error &error) { + lldb_private::StreamString stream; + stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, + offset); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') + return 0; + uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX); + if (retcode == UINT32_MAX) + return retcode; + const char next = (response.Peek() ? *response.Peek() : 0); + if (next == ',') + return 0; + if (next == ';') { + response.GetChar(); // skip the semicolon + std::string buffer; + if (response.GetEscapedBinaryData(buffer)) { + const uint64_t data_to_write = + std::min<uint64_t>(dst_len, buffer.size()); + if (data_to_write > 0) + memcpy(dst, &buffer[0], data_to_write); + return data_to_write; + } + } + } + return 0; +} + +uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, + uint64_t offset, + const void *src, + uint64_t src_len, + Error &error) { + lldb_private::StreamGDBRemote stream; + stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); + stream.PutEscapedBytes(src, src_len); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') { + error.SetErrorStringWithFormat("write file failed"); + return 0; + } + uint64_t bytes_written = response.GetU64(UINT64_MAX); + if (bytes_written == UINT64_MAX) { + error.SetErrorToGenericError(); + if (response.GetChar() == ',') { + int response_errno = response.GetS32(-1); + if (response_errno > 0) + error.SetError(response_errno, lldb::eErrorTypePOSIX); + } + return 0; + } + return bytes_written; + } else { + error.SetErrorString("failed to send vFile:pwrite packet"); + } + return 0; +} + +Error GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, + const FileSpec &dst) { + std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)}; + Error error; + lldb_private::StreamGDBRemote stream; + stream.PutCString("vFile:symlink:"); + // the unix symlink() command reverses its parameters where the dst if first, + // so we follow suit here + stream.PutCStringAsRawHex8(dst_path.c_str()); + stream.PutChar(','); + stream.PutCStringAsRawHex8(src_path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() == 'F') { + uint32_t result = response.GetU32(UINT32_MAX); + if (result != 0) { + error.SetErrorToGenericError(); + if (response.GetChar() == ',') { + int response_errno = response.GetS32(-1); + if (response_errno > 0) + error.SetError(response_errno, lldb::eErrorTypePOSIX); + } + } + } else { + // Should have returned with 'F<result>[,<errno>]' + error.SetErrorStringWithFormat("symlink failed"); + } + } else { + error.SetErrorString("failed to send vFile:symlink packet"); + } + return error; +} + +Error GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { + std::string path{file_spec.GetPath(false)}; + Error error; + lldb_private::StreamGDBRemote stream; + stream.PutCString("vFile:unlink:"); + // the unix symlink() command reverses its parameters where the dst if first, + // so we follow suit here + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() == 'F') { + uint32_t result = response.GetU32(UINT32_MAX); + if (result != 0) { + error.SetErrorToGenericError(); + if (response.GetChar() == ',') { + int response_errno = response.GetS32(-1); + if (response_errno > 0) + error.SetError(response_errno, lldb::eErrorTypePOSIX); + } + } + } else { + // Should have returned with 'F<result>[,<errno>]' + error.SetErrorStringWithFormat("unlink failed"); + } + } else { + error.SetErrorString("failed to send vFile:unlink packet"); + } + return error; } // Extension of host I/O packets to get whether a file exists. -bool -GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec) -{ - std::string path(file_spec.GetPath(false)); - lldb_private::StreamString stream; - stream.PutCString("vFile:exists:"); - stream.PutCStringAsRawHex8(path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - return false; - if (response.GetChar() != ',') - return false; - bool retcode = (response.GetChar() != '0'); - return retcode; - } +bool GDBRemoteCommunicationClient::GetFileExists( + const lldb_private::FileSpec &file_spec) { + std::string path(file_spec.GetPath(false)); + lldb_private::StreamString stream; + stream.PutCString("vFile:exists:"); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') + return false; + if (response.GetChar() != ',') + return false; + bool retcode = (response.GetChar() != '0'); + return retcode; + } + return false; +} + +bool GDBRemoteCommunicationClient::CalculateMD5( + const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) { + std::string path(file_spec.GetPath(false)); + lldb_private::StreamString stream; + stream.PutCString("vFile:MD5:"); + stream.PutCStringAsRawHex8(path.c_str()); + const char *packet = stream.GetData(); + int packet_len = stream.GetSize(); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == + PacketResult::Success) { + if (response.GetChar() != 'F') + return false; + if (response.GetChar() != ',') + return false; + if (response.Peek() && *response.Peek() == 'x') + return false; + low = response.GetHexMaxU64(false, UINT64_MAX); + high = response.GetHexMaxU64(false, UINT64_MAX); + return true; + } + return false; +} + +bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) { + // Some targets have issues with g/G packets and we need to avoid using them + if (m_avoid_g_packets == eLazyBoolCalculate) { + if (process) { + m_avoid_g_packets = eLazyBoolNo; + const ArchSpec &arch = process->GetTarget().GetArchitecture(); + if (arch.IsValid() && + arch.GetTriple().getVendor() == llvm::Triple::Apple && + arch.GetTriple().getOS() == llvm::Triple::IOS && + arch.GetTriple().getArch() == llvm::Triple::aarch64) { + m_avoid_g_packets = eLazyBoolYes; + uint32_t gdb_server_version = GetGDBServerProgramVersion(); + if (gdb_server_version != 0) { + const char *gdb_server_name = GetGDBServerProgramName(); + if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) { + if (gdb_server_version >= 310) + m_avoid_g_packets = eLazyBoolNo; + } + } + } + } + } + return m_avoid_g_packets == eLazyBoolYes; +} + +DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, + uint32_t reg) { + StreamString payload; + payload.Printf("p%x", reg); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response, false) != PacketResult::Success || + !response.IsNormalResponse()) + return nullptr; + + DataBufferSP buffer_sp( + new DataBufferHeap(response.GetStringRef().size() / 2, 0)); + response.GetHexBytes(buffer_sp->GetData(), '\xcc'); + return buffer_sp; +} + +DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) { + StreamString payload; + payload.PutChar('g'); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response, false) != PacketResult::Success || + !response.IsNormalResponse()) + return nullptr; + + DataBufferSP buffer_sp( + new DataBufferHeap(response.GetStringRef().size() / 2, 0)); + response.GetHexBytes(buffer_sp->GetData(), '\xcc'); + return buffer_sp; +} + +bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, + uint32_t reg_num, + llvm::ArrayRef<uint8_t> data) { + StreamString payload; + payload.Printf("P%x=", reg_num); + payload.PutBytesAsRawHex8(data.data(), data.size(), + endian::InlHostByteOrder(), + endian::InlHostByteOrder()); + StringExtractorGDBRemote response; + return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), + response, false) == + PacketResult::Success && + response.IsOKResponse(); +} + +bool GDBRemoteCommunicationClient::WriteAllRegisters( + lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) { + StreamString payload; + payload.PutChar('G'); + payload.PutBytesAsRawHex8(data.data(), data.size(), + endian::InlHostByteOrder(), + endian::InlHostByteOrder()); + StringExtractorGDBRemote response; + return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), + response, false) == + PacketResult::Success && + response.IsOKResponse(); +} + +bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid, + uint32_t &save_id) { + save_id = 0; // Set to invalid save ID + if (m_supports_QSaveRegisterState == eLazyBoolNo) return false; -} -bool -GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_spec, - uint64_t &high, - uint64_t &low) -{ - std::string path(file_spec.GetPath(false)); - lldb_private::StreamString stream; - stream.PutCString("vFile:MD5:"); - stream.PutCStringAsRawHex8(path.c_str()); - const char* packet = stream.GetData(); - int packet_len = stream.GetSize(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) - { - if (response.GetChar() != 'F') - return false; - if (response.GetChar() != ',') - return false; - if (response.Peek() && *response.Peek() == 'x') - return false; - low = response.GetHexMaxU64(false, UINT64_MAX); - high = response.GetHexMaxU64(false, UINT64_MAX); - return true; - } + m_supports_QSaveRegisterState = eLazyBoolYes; + StreamString payload; + payload.PutCString("QSaveRegisterState"); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response, false) != PacketResult::Success) return false; -} -bool -GDBRemoteCommunicationClient::AvoidGPackets (ProcessGDBRemote *process) -{ - // Some targets have issues with g/G packets and we need to avoid using them - if (m_avoid_g_packets == eLazyBoolCalculate) - { - if (process) - { - m_avoid_g_packets = eLazyBoolNo; - const ArchSpec &arch = process->GetTarget().GetArchitecture(); - if (arch.IsValid() - && arch.GetTriple().getVendor() == llvm::Triple::Apple - && arch.GetTriple().getOS() == llvm::Triple::IOS - && arch.GetTriple().getArch() == llvm::Triple::aarch64) - { - m_avoid_g_packets = eLazyBoolYes; - uint32_t gdb_server_version = GetGDBServerProgramVersion(); - if (gdb_server_version != 0) - { - const char *gdb_server_name = GetGDBServerProgramName(); - if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) - { - if (gdb_server_version >= 310) - m_avoid_g_packets = eLazyBoolNo; - } - } - } - } - } - return m_avoid_g_packets == eLazyBoolYes; -} + if (response.IsUnsupportedResponse()) + m_supports_QSaveRegisterState = eLazyBoolNo; -DataBufferSP -GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg) -{ - StreamString payload; - payload.Printf("p%x", reg); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success || - !response.IsNormalResponse()) - return nullptr; + const uint32_t response_save_id = response.GetU32(0); + if (response_save_id == 0) + return false; - DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0)); - response.GetHexBytes(buffer_sp->GetData(), '\xcc'); - return buffer_sp; + save_id = response_save_id; + return true; } -DataBufferSP -GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) -{ - StreamString payload; - payload.PutChar('g'); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success || - !response.IsNormalResponse()) - return nullptr; +bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid, + uint32_t save_id) { + // We use the "m_supports_QSaveRegisterState" variable here because the + // QSaveRegisterState and QRestoreRegisterState packets must both be supported + // in + // order to be useful + if (m_supports_QSaveRegisterState == eLazyBoolNo) + return false; - DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0)); - response.GetHexBytes(buffer_sp->GetData(), '\xcc'); - return buffer_sp; -} + StreamString payload; + payload.Printf("QRestoreRegisterState:%u", save_id); + StringExtractorGDBRemote response; + if (SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response, false) != PacketResult::Success) + return false; -bool -GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::ArrayRef<uint8_t> data) -{ - StreamString payload; - payload.Printf("P%x=", reg_num); - payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder()); - StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == - PacketResult::Success && - response.IsOKResponse(); -} + if (response.IsOKResponse()) + return true; -bool -GDBRemoteCommunicationClient::WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) -{ - StreamString payload; - payload.PutChar('G'); - payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder()); - StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == - PacketResult::Success && - response.IsOKResponse(); + if (response.IsUnsupportedResponse()) + m_supports_QSaveRegisterState = eLazyBoolNo; + return false; } -bool -GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save_id) -{ - save_id = 0; // Set to invalid save ID - if (m_supports_QSaveRegisterState == eLazyBoolNo) - return false; - - m_supports_QSaveRegisterState = eLazyBoolYes; - StreamString payload; - payload.PutCString("QSaveRegisterState"); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success) - return false; - - if (response.IsUnsupportedResponse()) - m_supports_QSaveRegisterState = eLazyBoolNo; - - const uint32_t response_save_id = response.GetU32(0); - if (response_save_id == 0) - return false; +bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { + if (!GetSyncThreadStateSupported()) + return false; - save_id = response_save_id; - return true; + StreamString packet; + StringExtractorGDBRemote response; + packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid); + return SendPacketAndWaitForResponse(packet.GetString(), response, false) == + GDBRemoteCommunication::PacketResult::Success && + response.IsOKResponse(); } -bool -GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t save_id) -{ - // We use the "m_supports_QSaveRegisterState" variable here because the - // QSaveRegisterState and QRestoreRegisterState packets must both be supported in - // order to be useful - if (m_supports_QSaveRegisterState == eLazyBoolNo) - return false; +bool GDBRemoteCommunicationClient::GetModuleInfo( + const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, + ModuleSpec &module_spec) { + if (!m_supports_qModuleInfo) + return false; - StreamString payload; - payload.Printf("QRestoreRegisterState:%u", save_id); - StringExtractorGDBRemote response; - if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success) - return false; + std::string module_path = module_file_spec.GetPath(false); + if (module_path.empty()) + return false; - if (response.IsOKResponse()) - return true; + StreamString packet; + packet.PutCString("qModuleInfo:"); + packet.PutCStringAsRawHex8(module_path.c_str()); + packet.PutCString(";"); + const auto &triple = arch_spec.GetTriple().getTriple(); + packet.PutCStringAsRawHex8(triple.c_str()); - if (response.IsUnsupportedResponse()) - m_supports_QSaveRegisterState = eLazyBoolNo; + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, + false) != PacketResult::Success) return false; -} -bool -GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) -{ - if (!GetSyncThreadStateSupported()) - return false; + if (response.IsErrorResponse()) + return false; - StreamString packet; - StringExtractorGDBRemote response; - packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid); - return SendPacketAndWaitForResponse(packet.GetString(), response, false) == - GDBRemoteCommunication::PacketResult::Success && - response.IsOKResponse(); + if (response.IsUnsupportedResponse()) { + m_supports_qModuleInfo = false; + return false; + } + + llvm::StringRef name; + llvm::StringRef value; + + module_spec.Clear(); + module_spec.GetFileSpec() = module_file_spec; + + while (response.GetNameColonValue(name, value)) { + if (name == "uuid" || name == "md5") { + StringExtractor extractor(value); + std::string uuid; + extractor.GetHexByteString(uuid); + module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2); + } else if (name == "triple") { + StringExtractor extractor(value); + std::string triple; + extractor.GetHexByteString(triple); + module_spec.GetArchitecture().SetTriple(triple.c_str()); + } else if (name == "file_offset") { + uint64_t ival = 0; + if (!value.getAsInteger(16, ival)) + module_spec.SetObjectOffset(ival); + } else if (name == "file_size") { + uint64_t ival = 0; + if (!value.getAsInteger(16, ival)) + module_spec.SetObjectSize(ival); + } else if (name == "file_path") { + StringExtractor extractor(value); + std::string path; + extractor.GetHexByteString(path); + module_spec.GetFileSpec() = FileSpec(path.c_str(), false, arch_spec); + } + } + + return true; } -bool -GDBRemoteCommunicationClient::GetModuleInfo(const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, - ModuleSpec &module_spec) -{ - if (!m_supports_qModuleInfo) - return false; - - std::string module_path = module_file_spec.GetPath (false); - if (module_path.empty ()) - return false; - - StreamString packet; - packet.PutCString("qModuleInfo:"); - packet.PutCStringAsRawHex8(module_path.c_str()); - packet.PutCString(";"); - const auto& triple = arch_spec.GetTriple().getTriple(); - packet.PutCStringAsRawHex8(triple.c_str()); +// query the target remote for extended information using the qXfer packet +// +// example: object='features', annex='target.xml', out=<xml output> +// return: 'true' on success +// 'false' on failure (err set) +bool GDBRemoteCommunicationClient::ReadExtFeature( + const lldb_private::ConstString object, + const lldb_private::ConstString annex, std::string &out, + lldb_private::Error &err) { - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success) - return false; + std::stringstream output; + StringExtractorGDBRemote chunk; - if (response.IsErrorResponse ()) - return false; + uint64_t size = GetRemoteMaxPacketSize(); + if (size == 0) + size = 0x1000; + size = size - 1; // Leave space for the 'm' or 'l' character in the response + int offset = 0; + bool active = true; - if (response.IsUnsupportedResponse ()) - { - m_supports_qModuleInfo = false; - return false; - } + // loop until all data has been read + while (active) { - llvm::StringRef name; - llvm::StringRef value; + // send query extended feature packet + std::stringstream packet; + packet << "qXfer:" << object.AsCString("") + << ":read:" << annex.AsCString("") << ":" << std::hex << offset + << "," << std::hex << size; - module_spec.Clear (); - module_spec.GetFileSpec () = module_file_spec; + GDBRemoteCommunication::PacketResult res = + SendPacketAndWaitForResponse(packet.str().c_str(), chunk, false); - while (response.GetNameColonValue (name, value)) - { - if (name == "uuid" || name == "md5") - { - StringExtractor extractor(value); - std::string uuid; - extractor.GetHexByteString(uuid); - module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2); - } - else if (name == "triple") - { - StringExtractor extractor(value); - std::string triple; - extractor.GetHexByteString(triple); - module_spec.GetArchitecture().SetTriple(triple.c_str()); - } - else if (name == "file_offset") - { - uint64_t ival = 0; - if (!value.getAsInteger(16, ival)) - module_spec.SetObjectOffset (ival); - } - else if (name == "file_size") - { - uint64_t ival = 0; - if (!value.getAsInteger(16, ival)) - module_spec.SetObjectSize (ival); - } - else if (name == "file_path") - { - StringExtractor extractor(value); - std::string path; - extractor.GetHexByteString(path); - module_spec.GetFileSpec() = FileSpec(path.c_str(), false, arch_spec); - } + if (res != GDBRemoteCommunication::PacketResult::Success) { + err.SetErrorString("Error sending $qXfer packet"); + return false; } - return true; -} + const std::string &str = chunk.GetStringRef(); + if (str.length() == 0) { + // should have some data in chunk + err.SetErrorString("Empty response from $qXfer packet"); + return false; + } -// query the target remote for extended information using the qXfer packet -// -// example: object='features', annex='target.xml', out=<xml output> -// return: 'true' on success -// 'false' on failure (err set) -bool -GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString object, - const lldb_private::ConstString annex, - std::string & out, - lldb_private::Error & err) { - - std::stringstream output; - StringExtractorGDBRemote chunk; - - uint64_t size = GetRemoteMaxPacketSize(); - if (size == 0) - size = 0x1000; - size = size - 1; // Leave space for the 'm' or 'l' character in the response - int offset = 0; - bool active = true; - - // loop until all data has been read - while ( active ) { - - // send query extended feature packet - std::stringstream packet; - packet << "qXfer:" - << object.AsCString("") << ":read:" - << annex.AsCString("") << ":" - << std::hex << offset << "," - << std::hex << size; - - GDBRemoteCommunication::PacketResult res = - SendPacketAndWaitForResponse( packet.str().c_str(), - chunk, - false ); - - if ( res != GDBRemoteCommunication::PacketResult::Success ) { - err.SetErrorString( "Error sending $qXfer packet" ); - return false; - } + // check packet code + switch (str[0]) { + // last chunk + case ('l'): + active = false; + LLVM_FALLTHROUGH; - const std::string & str = chunk.GetStringRef( ); - if ( str.length() == 0 ) { - // should have some data in chunk - err.SetErrorString( "Empty response from $qXfer packet" ); - return false; - } + // more chunks + case ('m'): + if (str.length() > 1) + output << &str[1]; + offset += size; + break; - // check packet code - switch ( str[0] ) { - // last chunk - case ( 'l' ): - active = false; - LLVM_FALLTHROUGH; - - // more chunks - case ( 'm' ) : - if ( str.length() > 1 ) - output << &str[1]; - offset += size; - break; - - // unknown chunk - default: - err.SetErrorString( "Invalid continuation code from $qXfer packet" ); - return false; - } + // unknown chunk + default: + err.SetErrorString("Invalid continuation code from $qXfer packet"); + return false; } + } - out = output.str( ); - err.Success( ); - return true; + out = output.str(); + err.Success(); + return true; } // Notify the target that gdb is prepared to serve symbol lookup requests. // packet: "qSymbol::" // reply: // OK The target does not need to look up any (more) symbols. -// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex encoded). -// LLDB may provide the value by sending another qSymbol packet +// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex +// encoded). +// LLDB may provide the value by sending another qSymbol +// packet // in the form of"qSymbol:<sym_value>:<sym_name>". // // Three examples: // // lldb sends: qSymbol:: // lldb receives: OK -// Remote gdb stub does not need to know the addresses of any symbols, lldb does not +// Remote gdb stub does not need to know the addresses of any symbols, lldb +// does not // need to ask again in this session. // // lldb sends: qSymbol:: // lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473 // lldb sends: qSymbol::64697370617463685f71756575655f6f666673657473 // lldb receives: OK -// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does not know -// the address at this time. lldb needs to send qSymbol:: again when it has more +// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does +// not know +// the address at this time. lldb needs to send qSymbol:: again when it has +// more // solibs loaded. // // lldb sends: qSymbol:: // lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473 // lldb sends: qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473 // lldb receives: OK -// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says that it -// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it does not +// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says +// that it +// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it +// does not // need any more symbols. lldb does not need to ask again in this session. -void -GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process) -{ - // Set to true once we've resolved a symbol to an address for the remote stub. - // If we get an 'OK' response after this, the remote stub doesn't need any more - // symbols and we can stop asking. - bool symbol_response_provided = false; - - // Is this the initial qSymbol:: packet? - bool first_qsymbol_query = true; - - if (m_supports_qSymbol && m_qSymbol_requests_done == false) - { - Lock lock(*this, false); - if (lock) - { - StreamString packet; - packet.PutCString ("qSymbol::"); - StringExtractorGDBRemote response; - while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) == PacketResult::Success) - { - if (response.IsOKResponse()) - { - if (symbol_response_provided || first_qsymbol_query) - { - m_qSymbol_requests_done = true; - } +void GDBRemoteCommunicationClient::ServeSymbolLookups( + lldb_private::Process *process) { + // Set to true once we've resolved a symbol to an address for the remote stub. + // If we get an 'OK' response after this, the remote stub doesn't need any + // more + // symbols and we can stop asking. + bool symbol_response_provided = false; - // We are done serving symbols requests - return; - } - first_qsymbol_query = false; + // Is this the initial qSymbol:: packet? + bool first_qsymbol_query = true; - if (response.IsUnsupportedResponse()) - { - // qSymbol is not supported by the current GDB server we are connected to - m_supports_qSymbol = false; - return; - } - else - { - llvm::StringRef response_str(response.GetStringRef()); - if (response_str.startswith("qSymbol:")) - { - response.SetFilePos(strlen("qSymbol:")); - std::string symbol_name; - if (response.GetHexByteString(symbol_name)) - { - if (symbol_name.empty()) - return; - - addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; - lldb_private::SymbolContextList sc_list; - if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) - { - const size_t num_scs = sc_list.GetSize(); - for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(sc_idx, sc)) - { - if (sc.symbol) - { - switch (sc.symbol->GetType()) - { - case eSymbolTypeInvalid: - case eSymbolTypeAbsolute: - case eSymbolTypeUndefined: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeVariable: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeTrampoline: - break; - - case eSymbolTypeCode: - case eSymbolTypeResolver: - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeException: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - case eSymbolTypeReExported: - symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); - break; - } - } - } - } - } - // This is the normal path where our symbol lookup was successful and we want - // to send a packet with the new symbol value and see if another lookup needs to be - // done. - - // Change "packet" to contain the requested symbol value and name - packet.Clear(); - packet.PutCString("qSymbol:"); - if (symbol_load_addr != LLDB_INVALID_ADDRESS) - { - packet.Printf("%" PRIx64, symbol_load_addr); - symbol_response_provided = true; - } - else - { - symbol_response_provided = false; - } - packet.PutCString(":"); - packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); - continue; // go back to the while loop and send "packet" and wait for another response - } + if (m_supports_qSymbol && m_qSymbol_requests_done == false) { + Lock lock(*this, false); + if (lock) { + StreamString packet; + packet.PutCString("qSymbol::"); + StringExtractorGDBRemote response; + while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) == + PacketResult::Success) { + if (response.IsOKResponse()) { + if (symbol_response_provided || first_qsymbol_query) { + m_qSymbol_requests_done = true; + } + + // We are done serving symbols requests + return; + } + first_qsymbol_query = false; + + if (response.IsUnsupportedResponse()) { + // qSymbol is not supported by the current GDB server we are connected + // to + m_supports_qSymbol = false; + return; + } else { + llvm::StringRef response_str(response.GetStringRef()); + if (response_str.startswith("qSymbol:")) { + response.SetFilePos(strlen("qSymbol:")); + std::string symbol_name; + if (response.GetHexByteString(symbol_name)) { + if (symbol_name.empty()) + return; + + addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + lldb_private::SymbolContextList sc_list; + if (process->GetTarget().GetImages().FindSymbolsWithNameAndType( + ConstString(symbol_name), eSymbolTypeAny, sc_list)) { + const size_t num_scs = sc_list.GetSize(); + for (size_t sc_idx = 0; + sc_idx < num_scs && + symbol_load_addr == LLDB_INVALID_ADDRESS; + ++sc_idx) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(sc_idx, sc)) { + if (sc.symbol) { + switch (sc.symbol->GetType()) { + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeUndefined: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeVariable: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeTrampoline: + break; + + case eSymbolTypeCode: + case eSymbolTypeResolver: + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeException: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + case eSymbolTypeReExported: + symbol_load_addr = + sc.symbol->GetLoadAddress(&process->GetTarget()); + break; + } } + } } - } - // If we make it here, the symbol request packet response wasn't valid or - // our symbol lookup failed so we must abort - return; - - } - else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) - { - log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", __FUNCTION__); - } + } + // This is the normal path where our symbol lookup was successful + // and we want + // to send a packet with the new symbol value and see if another + // lookup needs to be + // done. + + // Change "packet" to contain the requested symbol value and name + packet.Clear(); + packet.PutCString("qSymbol:"); + if (symbol_load_addr != LLDB_INVALID_ADDRESS) { + packet.Printf("%" PRIx64, symbol_load_addr); + symbol_response_provided = true; + } else { + symbol_response_provided = false; + } + packet.PutCString(":"); + packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); + continue; // go back to the while loop and send "packet" and wait + // for another response + } + } + } + } + // If we make it here, the symbol request packet response wasn't valid or + // our symbol lookup failed so we must abort + return; + + } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( + GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) { + log->Printf( + "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", + __FUNCTION__); + } + } +} + +StructuredData::Array * +GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { + if (!m_supported_async_json_packets_is_valid) { + // Query the server for the array of supported asynchronous JSON + // packets. + m_supported_async_json_packets_is_valid = true; + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + + // Poll it now. + StringExtractorGDBRemote response; + const bool send_async = false; + if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, + send_async) == PacketResult::Success) { + m_supported_async_json_packets_sp = + StructuredData::ParseJSON(response.GetStringRef()); + if (m_supported_async_json_packets_sp && + !m_supported_async_json_packets_sp->GetAsArray()) { + // We were returned something other than a JSON array. This + // is invalid. Clear it out. + if (log) + log->Printf("GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets returned invalid " + "result: %s", + __FUNCTION__, response.GetStringRef().c_str()); + m_supported_async_json_packets_sp.reset(); + } + } else { + if (log) + log->Printf("GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets unsupported", + __FUNCTION__); } -} -StructuredData::Array* -GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() -{ - if (!m_supported_async_json_packets_is_valid) - { - // Query the server for the array of supported asynchronous JSON - // packets. - m_supported_async_json_packets_is_valid = true; - - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( - GDBR_LOG_PROCESS)); - - // Poll it now. - StringExtractorGDBRemote response; - const bool send_async = false; - if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, - send_async) == PacketResult::Success) - { - m_supported_async_json_packets_sp = StructuredData::ParseJSON( - response.GetStringRef()); - if (m_supported_async_json_packets_sp && - !m_supported_async_json_packets_sp->GetAsArray()) - { - // We were returned something other than a JSON array. This - // is invalid. Clear it out. - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets returned invalid " - "result: %s", __FUNCTION__, - response.GetStringRef().c_str()); - m_supported_async_json_packets_sp.reset(); - } - } - else - { - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets unsupported", - __FUNCTION__); - } - - if (log && m_supported_async_json_packets_sp) - { - StreamString stream; - m_supported_async_json_packets_sp->Dump(stream); - log->Printf("GDBRemoteCommunicationClient::%s(): supported async " - "JSON packets: %s", __FUNCTION__, - stream.GetString().c_str()); - } + if (log && m_supported_async_json_packets_sp) { + StreamString stream; + m_supported_async_json_packets_sp->Dump(stream); + log->Printf("GDBRemoteCommunicationClient::%s(): supported async " + "JSON packets: %s", + __FUNCTION__, stream.GetString().c_str()); } + } - return m_supported_async_json_packets_sp - ? m_supported_async_json_packets_sp->GetAsArray() - : nullptr; + return m_supported_async_json_packets_sp + ? m_supported_async_json_packets_sp->GetAsArray() + : nullptr; } -Error -GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( - const ConstString &type_name, - const StructuredData::ObjectSP &config_sp) -{ - Error error; - - if (type_name.GetLength() == 0) - { - error.SetErrorString("invalid type_name argument"); - return error; - } - - // Build command: Configure{type_name}: serialized config - // data. - StreamGDBRemote stream; - stream.PutCString("QConfigure"); - stream.PutCString(type_name.AsCString()); - stream.PutChar(':'); - if (config_sp) - { - // Gather the plain-text version of the configuration data. - StreamString unescaped_stream; - config_sp->Dump(unescaped_stream); - unescaped_stream.Flush(); - - // Add it to the stream in escaped fashion. - stream.PutEscapedBytes(unescaped_stream.GetData(), - unescaped_stream.GetSize()); - } - stream.Flush(); +Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( + const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { + Error error; - // Send the packet. - const bool send_async = false; - StringExtractorGDBRemote response; - auto result = SendPacketAndWaitForResponse(stream.GetString().c_str(), - response, send_async); - if (result == PacketResult::Success) - { - // We failed if the config result comes back other than OK. - if (strcmp(response.GetStringRef().c_str(), "OK") == 0) - { - // Okay! - error.Clear(); - } - else - { - error.SetErrorStringWithFormat("configuring StructuredData feature " - "%s failed with error %s", - type_name.AsCString(), - response.GetStringRef().c_str()); - } - } - else - { - // Can we get more data here on the failure? - error.SetErrorStringWithFormat("configuring StructuredData feature %s " - "failed when sending packet: " - "PacketResult=%d", type_name.AsCString(), - result); - } + if (type_name.GetLength() == 0) { + error.SetErrorString("invalid type_name argument"); return error; -} - -void -GDBRemoteCommunicationClient::OnRunPacketSent(bool first) -{ - GDBRemoteClientBase::OnRunPacketSent(first); - m_curr_tid = LLDB_INVALID_THREAD_ID; + } + + // Build command: Configure{type_name}: serialized config + // data. + StreamGDBRemote stream; + stream.PutCString("QConfigure"); + stream.PutCString(type_name.AsCString()); + stream.PutChar(':'); + if (config_sp) { + // Gather the plain-text version of the configuration data. + StreamString unescaped_stream; + config_sp->Dump(unescaped_stream); + unescaped_stream.Flush(); + + // Add it to the stream in escaped fashion. + stream.PutEscapedBytes(unescaped_stream.GetData(), + unescaped_stream.GetSize()); + } + stream.Flush(); + + // Send the packet. + const bool send_async = false; + StringExtractorGDBRemote response; + auto result = SendPacketAndWaitForResponse(stream.GetString().c_str(), + response, send_async); + if (result == PacketResult::Success) { + // We failed if the config result comes back other than OK. + if (strcmp(response.GetStringRef().c_str(), "OK") == 0) { + // Okay! + error.Clear(); + } else { + error.SetErrorStringWithFormat("configuring StructuredData feature " + "%s failed with error %s", + type_name.AsCString(), + response.GetStringRef().c_str()); + } + } else { + // Can we get more data here on the failure? + error.SetErrorStringWithFormat("configuring StructuredData feature %s " + "failed when sending packet: " + "PacketResult=%d", + type_name.AsCString(), result); + } + return error; +} + +void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) { + GDBRemoteClientBase::OnRunPacketSent(first); + m_curr_tid = LLDB_INVALID_THREAD_ID; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index eeeecb53992..e40c08cc681 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -29,667 +29,552 @@ namespace lldb_private { namespace process_gdb_remote { -class GDBRemoteCommunicationClient : public GDBRemoteClientBase -{ +class GDBRemoteCommunicationClient : public GDBRemoteClientBase { public: - GDBRemoteCommunicationClient(); - - ~GDBRemoteCommunicationClient() override; - - //------------------------------------------------------------------ - // After connecting, send the handshake to the server to make sure - // we are communicating with it. - //------------------------------------------------------------------ - bool - HandshakeWithServer (Error *error_ptr); - - // For packets which specify a range of output to be returned, - // return all of the output via a series of request packets of the form - // <prefix>0,<size> - // <prefix><size>,<size> - // <prefix><size>*2,<size> - // <prefix><size>*3,<size> - // ... - // until a "$l..." packet is received, indicating the end. - // (size is in hex; this format is used by a standard gdbserver to - // return the given portion of the output specified by <prefix>; - // for example, "qXfer:libraries-svr4:read::fff,1000" means - // "return a chunk of the xml description file for shared - // library load addresses, where the chunk starts at offset 0xfff - // and continues for 0x1000 bytes"). - // Concatenate the resulting server response packets together and - // return in response_string. If any packet fails, the return value - // indicates that failure and the returned string value is undefined. - PacketResult - SendPacketsAndConcatenateResponses (const char *send_payload_prefix, - std::string &response_string); - - bool - GetThreadSuffixSupported(); - - // This packet is usually sent first and the boolean return value - // indicates if the packet was send and any response was received - // even in the response is UNIMPLEMENTED. If the packet failed to - // get a response, then false is returned. This quickly tells us - // if we were able to connect and communicate with the remote GDB - // server - bool - QueryNoAckModeSupported (); - - void - GetListThreadsInStopReplySupported (); - - lldb::pid_t - GetCurrentProcessID (bool allow_lazy = true); - - bool - GetLaunchSuccess (std::string &error_str); - - bool - LaunchGDBServer (const char *remote_accept_hostname, - lldb::pid_t &pid, - uint16_t &port, - std::string &socket_name); - - size_t - QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls); - - bool - KillSpawnedProcess (lldb::pid_t pid); - - //------------------------------------------------------------------ - /// Sends a GDB remote protocol 'A' packet that delivers program - /// arguments to the remote server. - /// - /// @param[in] argv - /// A NULL terminated array of const C strings to use as the - /// arguments. - /// - /// @return - /// Zero if the response was "OK", a positive value if the - /// the response was "Exx" where xx are two hex digits, or - /// -1 if the call is unsupported or any other unexpected - /// response was received. - //------------------------------------------------------------------ - int - SendArgumentsPacket (const ProcessLaunchInfo &launch_info); - - //------------------------------------------------------------------ - /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the - /// environment that will get used when launching an application - /// in conjunction with the 'A' packet. This function can be called - /// multiple times in a row in order to pass on the desired - /// environment that the inferior should be launched with. - /// - /// @param[in] name_equal_value - /// A NULL terminated C string that contains a single environment - /// in the format "NAME=VALUE". - /// - /// @return - /// Zero if the response was "OK", a positive value if the - /// the response was "Exx" where xx are two hex digits, or - /// -1 if the call is unsupported or any other unexpected - /// response was received. - //------------------------------------------------------------------ - int - SendEnvironmentPacket (char const *name_equal_value); - - int - SendLaunchArchPacket (const char *arch); - - int - SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr); - - //------------------------------------------------------------------ - /// Sends a "vAttach:PID" where PID is in hex. - /// - /// @param[in] pid - /// A process ID for the remote gdb server to attach to. - /// - /// @param[out] response - /// The response received from the gdb server. If the return - /// value is zero, \a response will contain a stop reply - /// packet. - /// - /// @return - /// Zero if the attach was successful, or an error indicating - /// an error code. - //------------------------------------------------------------------ - int - SendAttach (lldb::pid_t pid, - StringExtractorGDBRemote& response); - - //------------------------------------------------------------------ - /// Sends a GDB remote protocol 'I' packet that delivers stdin - /// data to the remote process. - /// - /// @param[in] data - /// A pointer to stdin data. - /// - /// @param[in] data_len - /// The number of bytes available at \a data. - /// - /// @return - /// Zero if the attach was successful, or an error indicating - /// an error code. - //------------------------------------------------------------------ - int - SendStdinNotification(const char* data, size_t data_len); - - //------------------------------------------------------------------ - /// Sets the path to use for stdin/out/err for a process - /// that will be launched with the 'A' packet. - /// - /// @param[in] path - /// The path to use for stdin/out/err - /// - /// @return - /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ - int - SetSTDIN(const FileSpec &file_spec); - int - SetSTDOUT(const FileSpec &file_spec); - int - SetSTDERR(const FileSpec &file_spec); - - //------------------------------------------------------------------ - /// Sets the disable ASLR flag to \a enable for a process that will - /// be launched with the 'A' packet. - /// - /// @param[in] enable - /// A boolean value indicating whether to disable ASLR or not. - /// - /// @return - /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ - int - SetDisableASLR (bool enable); - - //------------------------------------------------------------------ - /// Sets the DetachOnError flag to \a enable for the process controlled by the stub. - /// - /// @param[in] enable - /// A boolean value indicating whether to detach on error or not. - /// - /// @return - /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ - int - SetDetachOnError (bool enable); - - //------------------------------------------------------------------ - /// Sets the working directory to \a path for a process that will - /// be launched with the 'A' packet for non platform based - /// connections. If this packet is sent to a GDB server that - /// implements the platform, it will change the current working - /// directory for the platform process. - /// - /// @param[in] working_dir - /// The path to a directory to use when launching our process - /// - /// @return - /// Zero if the for success, or an error code for failure. - //------------------------------------------------------------------ - int - SetWorkingDir(const FileSpec &working_dir); - - //------------------------------------------------------------------ - /// Gets the current working directory of a remote platform GDB - /// server. - /// - /// @param[out] working_dir - /// The current working directory on the remote platform. - /// - /// @return - /// Boolean for success - //------------------------------------------------------------------ - bool - GetWorkingDir(FileSpec &working_dir); - - lldb::addr_t - AllocateMemory (size_t size, uint32_t permissions); - - bool - DeallocateMemory (lldb::addr_t addr); - - Error - Detach (bool keep_stopped); - - Error - GetMemoryRegionInfo (lldb::addr_t addr, MemoryRegionInfo &range_info); - - Error - GetWatchpointSupportInfo (uint32_t &num); - - Error - GetWatchpointSupportInfo (uint32_t &num, bool& after, const ArchSpec &arch); - - Error - GetWatchpointsTriggerAfterInstruction (bool &after, const ArchSpec &arch); - - const ArchSpec & - GetHostArchitecture (); - - uint32_t - GetHostDefaultPacketTimeout(); - - const ArchSpec & - GetProcessArchitecture (); - - void - GetRemoteQSupported(); - - bool - GetVContSupported (char flavor); - - bool - GetpPacketSupported (lldb::tid_t tid); - - bool - GetxPacketSupported (); - - bool - GetVAttachOrWaitSupported (); - - bool - GetSyncThreadStateSupported(); - - void - ResetDiscoverableSettings (bool did_exec); - - bool - GetHostInfo (bool force = false); - - bool - GetDefaultThreadId (lldb::tid_t &tid); - - bool - GetOSVersion (uint32_t &major, - uint32_t &minor, - uint32_t &update); - - bool - GetOSBuildString (std::string &s); - - bool - GetOSKernelDescription (std::string &s); - - ArchSpec - GetSystemArchitecture (); - - bool - GetHostname (std::string &s); - - lldb::addr_t - GetShlibInfoAddr(); - - bool - GetSupportsThreadSuffix (); - - bool - GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info); - - uint32_t - FindProcesses (const ProcessInstanceInfoMatch &process_match_info, - ProcessInstanceInfoList &process_infos); - - bool - GetUserName (uint32_t uid, std::string &name); - - bool - GetGroupName (uint32_t gid, std::string &name); - - bool - HasFullVContSupport () - { - return GetVContSupported ('A'); - } + GDBRemoteCommunicationClient(); + + ~GDBRemoteCommunicationClient() override; + + //------------------------------------------------------------------ + // After connecting, send the handshake to the server to make sure + // we are communicating with it. + //------------------------------------------------------------------ + bool HandshakeWithServer(Error *error_ptr); + + // For packets which specify a range of output to be returned, + // return all of the output via a series of request packets of the form + // <prefix>0,<size> + // <prefix><size>,<size> + // <prefix><size>*2,<size> + // <prefix><size>*3,<size> + // ... + // until a "$l..." packet is received, indicating the end. + // (size is in hex; this format is used by a standard gdbserver to + // return the given portion of the output specified by <prefix>; + // for example, "qXfer:libraries-svr4:read::fff,1000" means + // "return a chunk of the xml description file for shared + // library load addresses, where the chunk starts at offset 0xfff + // and continues for 0x1000 bytes"). + // Concatenate the resulting server response packets together and + // return in response_string. If any packet fails, the return value + // indicates that failure and the returned string value is undefined. + PacketResult + SendPacketsAndConcatenateResponses(const char *send_payload_prefix, + std::string &response_string); + + bool GetThreadSuffixSupported(); + + // This packet is usually sent first and the boolean return value + // indicates if the packet was send and any response was received + // even in the response is UNIMPLEMENTED. If the packet failed to + // get a response, then false is returned. This quickly tells us + // if we were able to connect and communicate with the remote GDB + // server + bool QueryNoAckModeSupported(); + + void GetListThreadsInStopReplySupported(); + + lldb::pid_t GetCurrentProcessID(bool allow_lazy = true); + + bool GetLaunchSuccess(std::string &error_str); + + bool LaunchGDBServer(const char *remote_accept_hostname, lldb::pid_t &pid, + uint16_t &port, std::string &socket_name); + + size_t QueryGDBServer( + std::vector<std::pair<uint16_t, std::string>> &connection_urls); + + bool KillSpawnedProcess(lldb::pid_t pid); + + //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'A' packet that delivers program + /// arguments to the remote server. + /// + /// @param[in] argv + /// A NULL terminated array of const C strings to use as the + /// arguments. + /// + /// @return + /// Zero if the response was "OK", a positive value if the + /// the response was "Exx" where xx are two hex digits, or + /// -1 if the call is unsupported or any other unexpected + /// response was received. + //------------------------------------------------------------------ + int SendArgumentsPacket(const ProcessLaunchInfo &launch_info); + + //------------------------------------------------------------------ + /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the + /// environment that will get used when launching an application + /// in conjunction with the 'A' packet. This function can be called + /// multiple times in a row in order to pass on the desired + /// environment that the inferior should be launched with. + /// + /// @param[in] name_equal_value + /// A NULL terminated C string that contains a single environment + /// in the format "NAME=VALUE". + /// + /// @return + /// Zero if the response was "OK", a positive value if the + /// the response was "Exx" where xx are two hex digits, or + /// -1 if the call is unsupported or any other unexpected + /// response was received. + //------------------------------------------------------------------ + int SendEnvironmentPacket(char const *name_equal_value); + + int SendLaunchArchPacket(const char *arch); + + int SendLaunchEventDataPacket(const char *data, + bool *was_supported = nullptr); + + //------------------------------------------------------------------ + /// Sends a "vAttach:PID" where PID is in hex. + /// + /// @param[in] pid + /// A process ID for the remote gdb server to attach to. + /// + /// @param[out] response + /// The response received from the gdb server. If the return + /// value is zero, \a response will contain a stop reply + /// packet. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int SendAttach(lldb::pid_t pid, StringExtractorGDBRemote &response); + + //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'I' packet that delivers stdin + /// data to the remote process. + /// + /// @param[in] data + /// A pointer to stdin data. + /// + /// @param[in] data_len + /// The number of bytes available at \a data. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int SendStdinNotification(const char *data, size_t data_len); + + //------------------------------------------------------------------ + /// Sets the path to use for stdin/out/err for a process + /// that will be launched with the 'A' packet. + /// + /// @param[in] path + /// The path to use for stdin/out/err + /// + /// @return + /// Zero if the for success, or an error code for failure. + //------------------------------------------------------------------ + int SetSTDIN(const FileSpec &file_spec); + int SetSTDOUT(const FileSpec &file_spec); + int SetSTDERR(const FileSpec &file_spec); + + //------------------------------------------------------------------ + /// Sets the disable ASLR flag to \a enable for a process that will + /// be launched with the 'A' packet. + /// + /// @param[in] enable + /// A boolean value indicating whether to disable ASLR or not. + /// + /// @return + /// Zero if the for success, or an error code for failure. + //------------------------------------------------------------------ + int SetDisableASLR(bool enable); + + //------------------------------------------------------------------ + /// Sets the DetachOnError flag to \a enable for the process controlled by the + /// stub. + /// + /// @param[in] enable + /// A boolean value indicating whether to detach on error or not. + /// + /// @return + /// Zero if the for success, or an error code for failure. + //------------------------------------------------------------------ + int SetDetachOnError(bool enable); + + //------------------------------------------------------------------ + /// Sets the working directory to \a path for a process that will + /// be launched with the 'A' packet for non platform based + /// connections. If this packet is sent to a GDB server that + /// implements the platform, it will change the current working + /// directory for the platform process. + /// + /// @param[in] working_dir + /// The path to a directory to use when launching our process + /// + /// @return + /// Zero if the for success, or an error code for failure. + //------------------------------------------------------------------ + int SetWorkingDir(const FileSpec &working_dir); + + //------------------------------------------------------------------ + /// Gets the current working directory of a remote platform GDB + /// server. + /// + /// @param[out] working_dir + /// The current working directory on the remote platform. + /// + /// @return + /// Boolean for success + //------------------------------------------------------------------ + bool GetWorkingDir(FileSpec &working_dir); + + lldb::addr_t AllocateMemory(size_t size, uint32_t permissions); + + bool DeallocateMemory(lldb::addr_t addr); + + Error Detach(bool keep_stopped); + + Error GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); + + Error GetWatchpointSupportInfo(uint32_t &num); + + Error GetWatchpointSupportInfo(uint32_t &num, bool &after, + const ArchSpec &arch); + + Error GetWatchpointsTriggerAfterInstruction(bool &after, + const ArchSpec &arch); + + const ArchSpec &GetHostArchitecture(); + + uint32_t GetHostDefaultPacketTimeout(); + + const ArchSpec &GetProcessArchitecture(); + + void GetRemoteQSupported(); - bool - HasAnyVContSupport () - { - return GetVContSupported ('a'); - } - - bool - GetStopReply (StringExtractorGDBRemote &response); - - bool - GetThreadStopInfo (lldb::tid_t tid, - StringExtractorGDBRemote &response); - - bool - SupportsGDBStoppointPacket (GDBStoppointType type) - { - switch (type) - { - case eBreakpointSoftware: return m_supports_z0; - case eBreakpointHardware: return m_supports_z1; - case eWatchpointWrite: return m_supports_z2; - case eWatchpointRead: return m_supports_z3; - case eWatchpointReadWrite: return m_supports_z4; - default: return false; - } - } + bool GetVContSupported(char flavor); - uint8_t - SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint - bool insert, // Insert or remove? - lldb::addr_t addr, // Address of breakpoint or watchpoint - uint32_t length); // Byte Size of breakpoint or watchpoint - - bool - SetNonStopMode (const bool enable); - - void - TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm); - - // This packet is for testing the speed of the interface only. Both - // the client and server need to support it, but this allows us to - // measure the packet speed without any other work being done on the - // other end and avoids any of that work affecting the packet send - // and response times. - bool - SendSpeedTestPacket (uint32_t send_size, - uint32_t recv_size); - - bool - SetCurrentThread (uint64_t tid); - - bool - SetCurrentThreadForRun (uint64_t tid); - - bool - GetQXferAuxvReadSupported (); - - bool - GetQXferLibrariesReadSupported (); - - bool - GetQXferLibrariesSVR4ReadSupported (); - - uint64_t - GetRemoteMaxPacketSize(); - - bool - GetEchoSupported (); - - bool - GetAugmentedLibrariesSVR4ReadSupported (); - - bool - GetQXferFeaturesReadSupported (); - - LazyBool - SupportsAllocDeallocMemory () // const - { - // Uncomment this to have lldb pretend the debug server doesn't respond to alloc/dealloc memory packets. - // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo; - return m_supports_alloc_dealloc_memory; - } + bool GetpPacketSupported(lldb::tid_t tid); + + bool GetxPacketSupported(); + + bool GetVAttachOrWaitSupported(); + + bool GetSyncThreadStateSupported(); + + void ResetDiscoverableSettings(bool did_exec); + + bool GetHostInfo(bool force = false); + + bool GetDefaultThreadId(lldb::tid_t &tid); + + bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + + bool GetOSBuildString(std::string &s); + + bool GetOSKernelDescription(std::string &s); + + ArchSpec GetSystemArchitecture(); + + bool GetHostname(std::string &s); + + lldb::addr_t GetShlibInfoAddr(); + + bool GetSupportsThreadSuffix(); + + bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info); - size_t - GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids, - bool &sequence_mutex_unavailable); - - lldb::user_id_t - OpenFile (const FileSpec& file_spec, uint32_t flags, mode_t mode, Error &error); - - bool - CloseFile (lldb::user_id_t fd, Error &error); - - lldb::user_id_t - GetFileSize (const FileSpec& file_spec); - - Error - GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions); - - Error - SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions); - - uint64_t - ReadFile (lldb::user_id_t fd, - uint64_t offset, - void *dst, - uint64_t dst_len, - Error &error); - - uint64_t - WriteFile (lldb::user_id_t fd, - uint64_t offset, - const void* src, - uint64_t src_len, - Error &error); - - Error - CreateSymlink(const FileSpec &src, - const FileSpec &dst); - - Error - Unlink(const FileSpec &file_spec); - - Error - MakeDirectory(const FileSpec &file_spec, uint32_t mode); - - bool - GetFileExists (const FileSpec& file_spec); - - Error - RunShellCommand(const char *command, // Shouldn't be nullptr - const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory - int *status_ptr, // Pass nullptr if you don't want the process exit status - int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit - std::string *command_output, // Pass nullptr if you don't want the command output - uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish - - bool - CalculateMD5 (const FileSpec& file_spec, uint64_t &high, uint64_t &low); - - lldb::DataBufferSP - ReadRegister(lldb::tid_t tid, - uint32_t reg_num); // Must be the eRegisterKindProcessPlugin register number - - lldb::DataBufferSP - ReadAllRegisters(lldb::tid_t tid); - - bool - WriteRegister(lldb::tid_t tid, uint32_t reg_num, // eRegisterKindProcessPlugin register number - llvm::ArrayRef<uint8_t> data); - - bool - WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data); - - bool - SaveRegisterState(lldb::tid_t tid, uint32_t &save_id); - - bool - RestoreRegisterState (lldb::tid_t tid, uint32_t save_id); - - bool - SyncThreadState(lldb::tid_t tid); - - const char * - GetGDBServerProgramName(); - - uint32_t - GetGDBServerProgramVersion(); - - bool - AvoidGPackets(ProcessGDBRemote *process); - - StructuredData::ObjectSP - GetThreadsInfo(); - - bool - GetThreadExtendedInfoSupported(); - - bool - GetLoadedDynamicLibrariesInfosSupported(); - - bool - GetSharedCacheInfoSupported(); - - bool - GetModuleInfo (const FileSpec& module_file_spec, - const ArchSpec& arch_spec, - ModuleSpec &module_spec); - - bool - ReadExtFeature (const lldb_private::ConstString object, - const lldb_private::ConstString annex, - std::string & out, - lldb_private::Error & err); - - void - ServeSymbolLookups(lldb_private::Process *process); - - //------------------------------------------------------------------ - /// Return the feature set supported by the gdb-remote server. - /// - /// This method returns the remote side's response to the qSupported - /// packet. The response is the complete string payload returned - /// to the client. - /// - /// @return - /// The string returned by the server to the qSupported query. - //------------------------------------------------------------------ - const std::string& - GetServerSupportedFeatures() const - { - return m_qSupported_response; + uint32_t FindProcesses(const ProcessInstanceInfoMatch &process_match_info, + ProcessInstanceInfoList &process_infos); + + bool GetUserName(uint32_t uid, std::string &name); + + bool GetGroupName(uint32_t gid, std::string &name); + + bool HasFullVContSupport() { return GetVContSupported('A'); } + + bool HasAnyVContSupport() { return GetVContSupported('a'); } + + bool GetStopReply(StringExtractorGDBRemote &response); + + bool GetThreadStopInfo(lldb::tid_t tid, StringExtractorGDBRemote &response); + + bool SupportsGDBStoppointPacket(GDBStoppointType type) { + switch (type) { + case eBreakpointSoftware: + return m_supports_z0; + case eBreakpointHardware: + return m_supports_z1; + case eWatchpointWrite: + return m_supports_z2; + case eWatchpointRead: + return m_supports_z3; + case eWatchpointReadWrite: + return m_supports_z4; + default: + return false; } + } + + uint8_t SendGDBStoppointTypePacket( + GDBStoppointType type, // Type of breakpoint or watchpoint + bool insert, // Insert or remove? + lldb::addr_t addr, // Address of breakpoint or watchpoint + uint32_t length); // Byte Size of breakpoint or watchpoint + + bool SetNonStopMode(const bool enable); + + void TestPacketSpeed(const uint32_t num_packets, uint32_t max_send, + uint32_t max_recv, bool json, Stream &strm); + + // This packet is for testing the speed of the interface only. Both + // the client and server need to support it, but this allows us to + // measure the packet speed without any other work being done on the + // other end and avoids any of that work affecting the packet send + // and response times. + bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size); + + bool SetCurrentThread(uint64_t tid); + + bool SetCurrentThreadForRun(uint64_t tid); + + bool GetQXferAuxvReadSupported(); + + bool GetQXferLibrariesReadSupported(); + + bool GetQXferLibrariesSVR4ReadSupported(); + + uint64_t GetRemoteMaxPacketSize(); + + bool GetEchoSupported(); + + bool GetAugmentedLibrariesSVR4ReadSupported(); + + bool GetQXferFeaturesReadSupported(); + + LazyBool SupportsAllocDeallocMemory() // const + { + // Uncomment this to have lldb pretend the debug server doesn't respond to + // alloc/dealloc memory packets. + // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo; + return m_supports_alloc_dealloc_memory; + } + + size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids, + bool &sequence_mutex_unavailable); + + lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, + mode_t mode, Error &error); + + bool CloseFile(lldb::user_id_t fd, Error &error); + + lldb::user_id_t GetFileSize(const FileSpec &file_spec); + + Error GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions); + + Error SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions); + + uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, + uint64_t dst_len, Error &error); + + uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, + uint64_t src_len, Error &error); + + Error CreateSymlink(const FileSpec &src, const FileSpec &dst); + + Error Unlink(const FileSpec &file_spec); + + Error MakeDirectory(const FileSpec &file_spec, uint32_t mode); + + bool GetFileExists(const FileSpec &file_spec); + + Error RunShellCommand( + const char *command, // Shouldn't be nullptr + const FileSpec &working_dir, // Pass empty FileSpec to use the current + // working directory + int *status_ptr, // Pass nullptr if you don't want the process exit status + int *signo_ptr, // Pass nullptr if you don't want the signal that caused + // the process to exit + std::string + *command_output, // Pass nullptr if you don't want the command output + uint32_t timeout_sec); // Timeout in seconds to wait for shell program to + // finish + + bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low); + + lldb::DataBufferSP ReadRegister( + lldb::tid_t tid, + uint32_t + reg_num); // Must be the eRegisterKindProcessPlugin register number + + lldb::DataBufferSP ReadAllRegisters(lldb::tid_t tid); + + bool + WriteRegister(lldb::tid_t tid, + uint32_t reg_num, // eRegisterKindProcessPlugin register number + llvm::ArrayRef<uint8_t> data); + + bool WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data); + + bool SaveRegisterState(lldb::tid_t tid, uint32_t &save_id); + + bool RestoreRegisterState(lldb::tid_t tid, uint32_t save_id); + + bool SyncThreadState(lldb::tid_t tid); + + const char *GetGDBServerProgramName(); + + uint32_t GetGDBServerProgramVersion(); + + bool AvoidGPackets(ProcessGDBRemote *process); + + StructuredData::ObjectSP GetThreadsInfo(); + + bool GetThreadExtendedInfoSupported(); + + bool GetLoadedDynamicLibrariesInfosSupported(); + + bool GetSharedCacheInfoSupported(); + + bool GetModuleInfo(const FileSpec &module_file_spec, + const ArchSpec &arch_spec, ModuleSpec &module_spec); + + bool ReadExtFeature(const lldb_private::ConstString object, + const lldb_private::ConstString annex, std::string &out, + lldb_private::Error &err); + + void ServeSymbolLookups(lldb_private::Process *process); + + //------------------------------------------------------------------ + /// Return the feature set supported by the gdb-remote server. + /// + /// This method returns the remote side's response to the qSupported + /// packet. The response is the complete string payload returned + /// to the client. + /// + /// @return + /// The string returned by the server to the qSupported query. + //------------------------------------------------------------------ + const std::string &GetServerSupportedFeatures() const { + return m_qSupported_response; + } + + //------------------------------------------------------------------ + /// Return the array of async JSON packet types supported by the remote. + /// + /// This method returns the remote side's array of supported JSON + /// packet types as a list of type names. Each of the results are + /// expected to have an Enable{type_name} command to enable and configure + /// the related feature. Each type_name for an enabled feature will + /// possibly send async-style packets that contain a payload of a + /// binhex-encoded JSON dictionary. The dictionary will have a + /// string field named 'type', that contains the type_name of the + /// supported packet type. + /// + /// There is a Plugin category called structured-data plugins. + /// A plugin indicates whether it knows how to handle a type_name. + /// If so, it can be used to process the async JSON packet. + /// + /// @return + /// The string returned by the server to the qSupported query. + //------------------------------------------------------------------ + lldb_private::StructuredData::Array *GetSupportedStructuredDataPlugins(); - //------------------------------------------------------------------ - /// Return the array of async JSON packet types supported by the remote. - /// - /// This method returns the remote side's array of supported JSON - /// packet types as a list of type names. Each of the results are - /// expected to have an Enable{type_name} command to enable and configure - /// the related feature. Each type_name for an enabled feature will - /// possibly send async-style packets that contain a payload of a - /// binhex-encoded JSON dictionary. The dictionary will have a - /// string field named 'type', that contains the type_name of the - /// supported packet type. - /// - /// There is a Plugin category called structured-data plugins. - /// A plugin indicates whether it knows how to handle a type_name. - /// If so, it can be used to process the async JSON packet. - /// - /// @return - /// The string returned by the server to the qSupported query. - //------------------------------------------------------------------ - lldb_private::StructuredData::Array* - GetSupportedStructuredDataPlugins(); - - //------------------------------------------------------------------ - /// Configure a StructuredData feature on the remote end. - /// - /// @see \b Process::ConfigureStructuredData(...) for details. - //------------------------------------------------------------------ - Error - ConfigureRemoteStructuredData(const ConstString &type_name, - const StructuredData::ObjectSP &config_sp); + //------------------------------------------------------------------ + /// Configure a StructuredData feature on the remote end. + /// + /// @see \b Process::ConfigureStructuredData(...) for details. + //------------------------------------------------------------------ + Error + ConfigureRemoteStructuredData(const ConstString &type_name, + const StructuredData::ObjectSP &config_sp); protected: - LazyBool m_supports_not_sending_acks; - LazyBool m_supports_thread_suffix; - LazyBool m_supports_threads_in_stop_reply; - LazyBool m_supports_vCont_all; - LazyBool m_supports_vCont_any; - LazyBool m_supports_vCont_c; - LazyBool m_supports_vCont_C; - LazyBool m_supports_vCont_s; - LazyBool m_supports_vCont_S; - LazyBool m_qHostInfo_is_valid; - LazyBool m_curr_pid_is_valid; - LazyBool m_qProcessInfo_is_valid; - LazyBool m_qGDBServerVersion_is_valid; - LazyBool m_supports_alloc_dealloc_memory; - LazyBool m_supports_memory_region_info; - LazyBool m_supports_watchpoint_support_info; - LazyBool m_supports_detach_stay_stopped; - LazyBool m_watchpoints_trigger_after_instruction; - LazyBool m_attach_or_wait_reply; - LazyBool m_prepare_for_reg_writing_reply; - LazyBool m_supports_p; - LazyBool m_supports_x; - LazyBool m_avoid_g_packets; - LazyBool m_supports_QSaveRegisterState; - LazyBool m_supports_qXfer_auxv_read; - LazyBool m_supports_qXfer_libraries_read; - LazyBool m_supports_qXfer_libraries_svr4_read; - LazyBool m_supports_qXfer_features_read; - LazyBool m_supports_augmented_libraries_svr4_read; - LazyBool m_supports_jThreadExtendedInfo; - LazyBool m_supports_jLoadedDynamicLibrariesInfos; - LazyBool m_supports_jGetSharedCacheInfo; - - bool - m_supports_qProcessInfoPID:1, - m_supports_qfProcessInfo:1, - m_supports_qUserName:1, - m_supports_qGroupName:1, - m_supports_qThreadStopInfo:1, - m_supports_z0:1, - m_supports_z1:1, - m_supports_z2:1, - m_supports_z3:1, - m_supports_z4:1, - m_supports_QEnvironment:1, - m_supports_QEnvironmentHexEncoded:1, - m_supports_qSymbol:1, - m_qSymbol_requests_done:1, - m_supports_qModuleInfo:1, - m_supports_jThreadsInfo:1; - - lldb::pid_t m_curr_pid; - lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations - lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc - - uint32_t m_num_supported_hardware_watchpoints; - - ArchSpec m_host_arch; - ArchSpec m_process_arch; - uint32_t m_os_version_major; - uint32_t m_os_version_minor; - uint32_t m_os_version_update; - std::string m_os_build; - std::string m_os_kernel; - std::string m_hostname; - std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if qGDBServerVersion is not supported - uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if qGDBServerVersion is not supported - uint32_t m_default_packet_timeout; - uint64_t m_max_packet_size; // as returned by qSupported - std::string m_qSupported_response; // the complete response to qSupported - - bool m_supported_async_json_packets_is_valid; - lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp; - - bool - GetCurrentProcessInfo (bool allow_lazy_pid = true); - - bool - GetGDBServerVersion(); - - // Given the list of compression types that the remote debug stub can support, - // possibly enable compression if we find an encoding we can handle. - void - MaybeEnableCompression (std::vector<std::string> supported_compressions); - - bool - DecodeProcessInfoResponse (StringExtractorGDBRemote &response, - ProcessInstanceInfo &process_info); - - void - OnRunPacketSent(bool first) override; - - PacketResult - SendThreadSpecificPacketAndWaitForResponse(lldb::tid_t tid, StreamString &&payload, - StringExtractorGDBRemote &response, bool send_async); + LazyBool m_supports_not_sending_acks; + LazyBool m_supports_thread_suffix; + LazyBool m_supports_threads_in_stop_reply; + LazyBool m_supports_vCont_all; + LazyBool m_supports_vCont_any; + LazyBool m_supports_vCont_c; + LazyBool m_supports_vCont_C; + LazyBool m_supports_vCont_s; + LazyBool m_supports_vCont_S; + LazyBool m_qHostInfo_is_valid; + LazyBool m_curr_pid_is_valid; + LazyBool m_qProcessInfo_is_valid; + LazyBool m_qGDBServerVersion_is_valid; + LazyBool m_supports_alloc_dealloc_memory; + LazyBool m_supports_memory_region_info; + LazyBool m_supports_watchpoint_support_info; + LazyBool m_supports_detach_stay_stopped; + LazyBool m_watchpoints_trigger_after_instruction; + LazyBool m_attach_or_wait_reply; + LazyBool m_prepare_for_reg_writing_reply; + LazyBool m_supports_p; + LazyBool m_supports_x; + LazyBool m_avoid_g_packets; + LazyBool m_supports_QSaveRegisterState; + LazyBool m_supports_qXfer_auxv_read; + LazyBool m_supports_qXfer_libraries_read; + LazyBool m_supports_qXfer_libraries_svr4_read; + LazyBool m_supports_qXfer_features_read; + LazyBool m_supports_augmented_libraries_svr4_read; + LazyBool m_supports_jThreadExtendedInfo; + LazyBool m_supports_jLoadedDynamicLibrariesInfos; + LazyBool m_supports_jGetSharedCacheInfo; + + bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, + m_supports_qUserName : 1, m_supports_qGroupName : 1, + m_supports_qThreadStopInfo : 1, m_supports_z0 : 1, m_supports_z1 : 1, + m_supports_z2 : 1, m_supports_z3 : 1, m_supports_z4 : 1, + m_supports_QEnvironment : 1, m_supports_QEnvironmentHexEncoded : 1, + m_supports_qSymbol : 1, m_qSymbol_requests_done : 1, + m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1; + + lldb::pid_t m_curr_pid; + lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all + // other operations + lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for + // continue, step, etc + + uint32_t m_num_supported_hardware_watchpoints; + + ArchSpec m_host_arch; + ArchSpec m_process_arch; + uint32_t m_os_version_major; + uint32_t m_os_version_minor; + uint32_t m_os_version_update; + std::string m_os_build; + std::string m_os_kernel; + std::string m_hostname; + std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if + // qGDBServerVersion is not supported + uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if + // qGDBServerVersion is not supported + uint32_t m_default_packet_timeout; + uint64_t m_max_packet_size; // as returned by qSupported + std::string m_qSupported_response; // the complete response to qSupported + + bool m_supported_async_json_packets_is_valid; + lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp; + + bool GetCurrentProcessInfo(bool allow_lazy_pid = true); + + bool GetGDBServerVersion(); + + // Given the list of compression types that the remote debug stub can support, + // possibly enable compression if we find an encoding we can handle. + void MaybeEnableCompression(std::vector<std::string> supported_compressions); + + bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response, + ProcessInstanceInfo &process_info); + + void OnRunPacketSent(bool first) override; + + PacketResult SendThreadSpecificPacketAndWaitForResponse( + lldb::tid_t tid, StreamString &&payload, + StringExtractorGDBRemote &response, bool send_async); private: - DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient); + DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 58cb7760cbf..8ccab36ce83 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -25,114 +25,99 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(const char *comm_name, - const char *listener_name) : - GDBRemoteCommunication (comm_name, listener_name), - m_exit_now (false) -{ -} +GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( + const char *comm_name, const char *listener_name) + : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {} -GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() -{ -} +GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} void GDBRemoteCommunicationServer::RegisterPacketHandler( - StringExtractorGDBRemote::ServerPacketType packet_type, - PacketHandler handler) -{ - m_packet_handlers[packet_type] = std::move(handler); + StringExtractorGDBRemote::ServerPacketType packet_type, + PacketHandler handler) { + m_packet_handlers[packet_type] = std::move(handler); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, - Error &error, - bool &interrupt, - bool &quit) -{ - StringExtractorGDBRemote packet; - - PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec, false); - if (packet_result == PacketResult::Success) - { - const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); - switch (packet_type) - { - case StringExtractorGDBRemote::eServerPacketType_nack: - case StringExtractorGDBRemote::eServerPacketType_ack: - break; - - case StringExtractorGDBRemote::eServerPacketType_invalid: - error.SetErrorString("invalid packet"); - quit = true; - break; - - case StringExtractorGDBRemote::eServerPacketType_unimplemented: - packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); - break; - - default: - auto handler_it = m_packet_handlers.find(packet_type); - if (handler_it == m_packet_handlers.end()) - packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); - else - packet_result = handler_it->second (packet, error, interrupt, quit); - break; - } +GDBRemoteCommunicationServer::GetPacketAndSendResponse(uint32_t timeout_usec, + Error &error, + bool &interrupt, + bool &quit) { + StringExtractorGDBRemote packet; + + PacketResult packet_result = + WaitForPacketWithTimeoutMicroSecondsNoLock(packet, timeout_usec, false); + if (packet_result == PacketResult::Success) { + const StringExtractorGDBRemote::ServerPacketType packet_type = + packet.GetServerPacketType(); + switch (packet_type) { + case StringExtractorGDBRemote::eServerPacketType_nack: + case StringExtractorGDBRemote::eServerPacketType_ack: + break; + + case StringExtractorGDBRemote::eServerPacketType_invalid: + error.SetErrorString("invalid packet"); + quit = true; + break; + + case StringExtractorGDBRemote::eServerPacketType_unimplemented: + packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str()); + break; + + default: + auto handler_it = m_packet_handlers.find(packet_type); + if (handler_it == m_packet_handlers.end()) + packet_result = + SendUnimplementedResponse(packet.GetStringRef().c_str()); + else + packet_result = handler_it->second(packet, error, interrupt, quit); + break; } - else - { - if (!IsConnected()) - { - error.SetErrorString("lost connection"); - quit = true; - } - else - { - error.SetErrorString("timeout"); - } + } else { + if (!IsConnected()) { + error.SetErrorString("lost connection"); + quit = true; + } else { + error.SetErrorString("timeout"); } + } - // Check if anything occurred that would force us to want to exit. - if (m_exit_now) - quit = true; + // Check if anything occurred that would force us to want to exit. + if (m_exit_now) + quit = true; - return packet_result; + return packet_result; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) -{ - // TODO: Log the packet we aren't handling... - return SendPacketNoLock (""); +GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) { + // TODO: Log the packet we aren't handling... + return SendPacketNoLock(""); } - GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) -{ - char packet[16]; - int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); - assert (packet_len < (int)sizeof(packet)); - return SendPacketNoLock (llvm::StringRef(packet, packet_len)); +GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { + char packet[16]; + int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err); + assert(packet_len < (int)sizeof(packet)); + return SendPacketNoLock(llvm::StringRef(packet, packet_len)); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::SendIllFormedResponse (const StringExtractorGDBRemote &failed_packet, const char *message) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : ""); - return SendErrorResponse (0x03); +GDBRemoteCommunicationServer::SendIllFormedResponse( + const StringExtractorGDBRemote &failed_packet, const char *message) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + if (log) + log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", + __FUNCTION__, failed_packet.GetStringRef().c_str(), + message ? message : ""); + return SendErrorResponse(0x03); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServer::SendOKResponse () -{ - return SendPacketNoLock ("OK"); +GDBRemoteCommunicationServer::SendOKResponse() { + return SendPacketNoLock("OK"); } -bool -GDBRemoteCommunicationServer::HandshakeWithClient() -{ - return GetAck() == PacketResult::Success; +bool GDBRemoteCommunicationServer::HandshakeWithClient() { + return GetAck() == PacketResult::Success; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 1d512bf1de5..55a615aa3dc 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -17,8 +17,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunication.h" +#include "lldb/lldb-private-forward.h" class StringExtractorGDBRemote; @@ -27,52 +27,46 @@ namespace process_gdb_remote { class ProcessGDBRemote; -class GDBRemoteCommunicationServer : public GDBRemoteCommunication -{ +class GDBRemoteCommunicationServer : public GDBRemoteCommunication { public: - using PortMap = std::map<uint16_t, lldb::pid_t>; - using PacketHandler = std::function<PacketResult(StringExtractorGDBRemote &packet, - Error &error, - bool &interrupt, - bool &quit)>; + using PortMap = std::map<uint16_t, lldb::pid_t>; + using PacketHandler = + std::function<PacketResult(StringExtractorGDBRemote &packet, Error &error, + bool &interrupt, bool &quit)>; - GDBRemoteCommunicationServer(const char *comm_name, - const char *listener_name); + GDBRemoteCommunicationServer(const char *comm_name, + const char *listener_name); - ~GDBRemoteCommunicationServer() override; + ~GDBRemoteCommunicationServer() override; - void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, - PacketHandler handler); + void + RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, + PacketHandler handler); - PacketResult - GetPacketAndSendResponse (uint32_t timeout_usec, - Error &error, - bool &interrupt, - bool &quit); + PacketResult GetPacketAndSendResponse(uint32_t timeout_usec, Error &error, + bool &interrupt, bool &quit); - // After connecting, do a little handshake with the client to make sure - // we are at least communicating - bool - HandshakeWithClient (); + // After connecting, do a little handshake with the client to make sure + // we are at least communicating + bool HandshakeWithClient(); protected: - std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> m_packet_handlers; - bool m_exit_now; // use in asynchronous handling to indicate process should exit. + std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> + m_packet_handlers; + bool m_exit_now; // use in asynchronous handling to indicate process should + // exit. - PacketResult - SendUnimplementedResponse (const char *packet); + PacketResult SendUnimplementedResponse(const char *packet); - PacketResult - SendErrorResponse (uint8_t error); + PacketResult SendErrorResponse(uint8_t error); - PacketResult - SendIllFormedResponse (const StringExtractorGDBRemote &packet, const char *error_message); + PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet, + const char *error_message); - PacketResult - SendOKResponse (); + PacketResult SendOKResponse(); private: - DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer); + DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServer); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 5ae5627dffc..f7ef2fe2176 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -18,11 +18,10 @@ #endif // C++ Includes -#include <cstring> #include <chrono> +#include <cstring> // Other libraries and framework includes -#include "llvm/ADT/Triple.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StreamGDBRemote.h" @@ -39,6 +38,7 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "llvm/ADT/Triple.h" // Project includes #include "ProcessGDBRemoteLog.h" @@ -55,1232 +55,1178 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; #ifdef __ANDROID__ - const static uint32_t g_default_packet_timeout_sec = 20; // seconds +const static uint32_t g_default_packet_timeout_sec = 20; // seconds #else - const static uint32_t g_default_packet_timeout_sec = 0; // not specified +const static uint32_t g_default_packet_timeout_sec = 0; // not specified #endif //---------------------------------------------------------------------- // GDBRemoteCommunicationServerCommon constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) : - GDBRemoteCommunicationServer (comm_name, listener_name), - m_process_launch_info (), - m_process_launch_error (), - m_proc_infos (), - m_proc_infos_index (0), - m_thread_suffix_supported (false), - m_list_threads_in_stop_reply (false) -{ - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, - &GDBRemoteCommunicationServerCommon::Handle_A); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QEnvironment, - &GDBRemoteCommunicationServerCommon::Handle_QEnvironment); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded, - &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfProcessInfo, - &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGroupName, - &GDBRemoteCommunicationServerCommon::Handle_qGroupName); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo, - &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch, - &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, - &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, - &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qEcho, - &GDBRemoteCommunicationServerCommon::Handle_qEcho); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qModuleInfo, - &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, - &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir, - &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_shell, - &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID, - &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError, - &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDERR, - &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDIN, - &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT, - &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSpeedTest, - &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qsProcessInfo, - &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode, - &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSupported, - &GDBRemoteCommunicationServerCommon::Handle_qSupported); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, - &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qUserName, - &GDBRemoteCommunicationServerCommon::Handle_qUserName); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_close, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Close); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_exists, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_md5, - &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_mode, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_open, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Open); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pread, - &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pwrite, - &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_size, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Size); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_stat, - &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_symlink, - &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_unlink, - &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink); +GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( + const char *comm_name, const char *listener_name) + : GDBRemoteCommunicationServer(comm_name, listener_name), + m_process_launch_info(), m_process_launch_error(), m_proc_infos(), + m_proc_infos_index(0), m_thread_suffix_supported(false), + m_list_threads_in_stop_reply(false) { + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, + &GDBRemoteCommunicationServerCommon::Handle_A); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QEnvironment, + &GDBRemoteCommunicationServerCommon::Handle_QEnvironment); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded, + &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qfProcessInfo, + &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qGroupName, + &GDBRemoteCommunicationServerCommon::Handle_qGroupName); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qHostInfo, + &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QLaunchArch, + &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, + &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, + &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qEcho, + &GDBRemoteCommunicationServerCommon::Handle_qEcho); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qModuleInfo, + &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, + &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir, + &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qPlatform_shell, + &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID, + &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError, + &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetSTDERR, + &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetSTDIN, + &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT, + &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qSpeedTest, + &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qsProcessInfo, + &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode, + &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qSupported, + &GDBRemoteCommunicationServerCommon::Handle_qSupported); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, + &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qUserName, + &GDBRemoteCommunicationServerCommon::Handle_qUserName); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_close, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Close); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_exists, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_md5, + &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_mode, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_open, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Open); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_pread, + &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_pwrite, + &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_size, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Size); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_stat, + &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_symlink, + &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vFile_unlink, + &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() -{ -} +GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {} GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &packet) -{ - StreamString response; +GDBRemoteCommunicationServerCommon::Handle_qHostInfo( + StringExtractorGDBRemote &packet) { + StreamString response; - // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 + // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 - ArchSpec host_arch(HostInfo::GetArchitecture()); - const llvm::Triple &host_triple = host_arch.GetTriple(); - response.PutCString("triple:"); - response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); - response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); - - const char* distribution_id = host_arch.GetDistributionId ().AsCString (); - if (distribution_id) - { - response.PutCString("distribution_id:"); - response.PutCStringAsRawHex8(distribution_id); - response.PutCString(";"); - } + ArchSpec host_arch(HostInfo::GetArchitecture()); + const llvm::Triple &host_triple = host_arch.GetTriple(); + response.PutCString("triple:"); + response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); + response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize()); + + const char *distribution_id = host_arch.GetDistributionId().AsCString(); + if (distribution_id) { + response.PutCString("distribution_id:"); + response.PutCStringAsRawHex8(distribution_id); + response.PutCString(";"); + } #if defined(__APPLE__) - // For parity with debugserver, we'll include the vendor key. - response.PutCString("vendor:apple;"); - - // Send out MachO info. - uint32_t cpu = host_arch.GetMachOCPUType(); - uint32_t sub = host_arch.GetMachOCPUSubType(); - if (cpu != LLDB_INVALID_CPUTYPE) - response.Printf ("cputype:%u;", cpu); - if (sub != LLDB_INVALID_CPUTYPE) - response.Printf ("cpusubtype:%u;", sub); - - if (cpu == ArchSpec::kCore_arm_any) - { - // Indicate the OS type. -#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1 - response.PutCString("ostype:tvos;"); -#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - response.PutCString("ostype:watchos;"); + // For parity with debugserver, we'll include the vendor key. + response.PutCString("vendor:apple;"); + + // Send out MachO info. + uint32_t cpu = host_arch.GetMachOCPUType(); + uint32_t sub = host_arch.GetMachOCPUSubType(); + if (cpu != LLDB_INVALID_CPUTYPE) + response.Printf("cputype:%u;", cpu); + if (sub != LLDB_INVALID_CPUTYPE) + response.Printf("cpusubtype:%u;", sub); + + if (cpu == ArchSpec::kCore_arm_any) { +// Indicate the OS type. +#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 + response.PutCString("ostype:tvos;"); +#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + response.PutCString("ostype:watchos;"); #else - response.PutCString("ostype:ios;"); + response.PutCString("ostype:ios;"); #endif - // On arm, we use "synchronous" watchpoints which means the exception is - // delivered before the instruction executes. - response.PutCString("watchpoint_exceptions_received:before;"); - } - else - { - response.PutCString("ostype:macosx;"); - response.Printf("watchpoint_exceptions_received:after;"); - } + // On arm, we use "synchronous" watchpoints which means the exception is + // delivered before the instruction executes. + response.PutCString("watchpoint_exceptions_received:before;"); + } else { + response.PutCString("ostype:macosx;"); + response.Printf("watchpoint_exceptions_received:after;"); + } #else - if (host_arch.GetMachine() == llvm::Triple::aarch64 || - host_arch.GetMachine() == llvm::Triple::aarch64_be || - host_arch.GetMachine() == llvm::Triple::arm || - host_arch.GetMachine() == llvm::Triple::armeb || - host_arch.GetMachine() == llvm::Triple::mips64 || - host_arch.GetMachine() == llvm::Triple::mips64el || - host_arch.GetMachine() == llvm::Triple::mips || - host_arch.GetMachine() == llvm::Triple::mipsel) - response.Printf("watchpoint_exceptions_received:before;"); - else - response.Printf("watchpoint_exceptions_received:after;"); + if (host_arch.GetMachine() == llvm::Triple::aarch64 || + host_arch.GetMachine() == llvm::Triple::aarch64_be || + host_arch.GetMachine() == llvm::Triple::arm || + host_arch.GetMachine() == llvm::Triple::armeb || + host_arch.GetMachine() == llvm::Triple::mips64 || + host_arch.GetMachine() == llvm::Triple::mips64el || + host_arch.GetMachine() == llvm::Triple::mips || + host_arch.GetMachine() == llvm::Triple::mipsel) + response.Printf("watchpoint_exceptions_received:before;"); + else + response.Printf("watchpoint_exceptions_received:after;"); #endif - switch (endian::InlHostByteOrder()) - { - case eByteOrderBig: response.PutCString ("endian:big;"); break; - case eByteOrderLittle: response.PutCString ("endian:little;"); break; - case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; - default: response.PutCString ("endian:unknown;"); break; - } - - uint32_t major = UINT32_MAX; - uint32_t minor = UINT32_MAX; - uint32_t update = UINT32_MAX; - if (HostInfo::GetOSVersion(major, minor, update)) - { - if (major != UINT32_MAX) - { - response.Printf("os_version:%u", major); - if (minor != UINT32_MAX) - { - response.Printf(".%u", minor); - if (update != UINT32_MAX) - response.Printf(".%u", update); - } - response.PutChar(';'); - } + switch (endian::InlHostByteOrder()) { + case eByteOrderBig: + response.PutCString("endian:big;"); + break; + case eByteOrderLittle: + response.PutCString("endian:little;"); + break; + case eByteOrderPDP: + response.PutCString("endian:pdp;"); + break; + default: + response.PutCString("endian:unknown;"); + break; + } + + uint32_t major = UINT32_MAX; + uint32_t minor = UINT32_MAX; + uint32_t update = UINT32_MAX; + if (HostInfo::GetOSVersion(major, minor, update)) { + if (major != UINT32_MAX) { + response.Printf("os_version:%u", major); + if (minor != UINT32_MAX) { + response.Printf(".%u", minor); + if (update != UINT32_MAX) + response.Printf(".%u", update); + } + response.PutChar(';'); } + } - std::string s; - if (HostInfo::GetOSBuildString(s)) - { - response.PutCString ("os_build:"); - response.PutCStringAsRawHex8(s.c_str()); - response.PutChar(';'); - } - if (HostInfo::GetOSKernelDescription(s)) - { - response.PutCString ("os_kernel:"); - response.PutCStringAsRawHex8(s.c_str()); - response.PutChar(';'); - } + std::string s; + if (HostInfo::GetOSBuildString(s)) { + response.PutCString("os_build:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } + if (HostInfo::GetOSKernelDescription(s)) { + response.PutCString("os_kernel:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } #if defined(__APPLE__) #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - // For iOS devices, we are connected through a USB Mux so we never pretend - // to actually have a hostname as far as the remote lldb that is connecting - // to this lldb-platform is concerned - response.PutCString ("hostname:"); - response.PutCStringAsRawHex8("127.0.0.1"); + // For iOS devices, we are connected through a USB Mux so we never pretend + // to actually have a hostname as far as the remote lldb that is connecting + // to this lldb-platform is concerned + response.PutCString("hostname:"); + response.PutCStringAsRawHex8("127.0.0.1"); + response.PutChar(';'); +#else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + if (HostInfo::GetHostname(s)) { + response.PutCString("hostname:"); + response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); -#else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - if (HostInfo::GetHostname(s)) - { - response.PutCString ("hostname:"); - response.PutCStringAsRawHex8(s.c_str()); - response.PutChar(';'); - } -#endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + } +#endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) -#else // #if defined(__APPLE__) - if (HostInfo::GetHostname(s)) - { - response.PutCString ("hostname:"); - response.PutCStringAsRawHex8(s.c_str()); - response.PutChar(';'); - } -#endif // #if defined(__APPLE__) +#else // #if defined(__APPLE__) + if (HostInfo::GetHostname(s)) { + response.PutCString("hostname:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } +#endif // #if defined(__APPLE__) - if (g_default_packet_timeout_sec > 0) - response.Printf ("default_packet_timeout:%u;", g_default_packet_timeout_sec); + if (g_default_packet_timeout_sec > 0) + response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec); - return SendPacketNoLock (response.GetString()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) -{ - // Packet format: "qProcessInfoPID:%i" where %i is the pid - packet.SetFilePos (::strlen ("qProcessInfoPID:")); - lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); - if (pid != LLDB_INVALID_PROCESS_ID) - { - ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo (pid, proc_info)) - { - StreamString response; - CreateProcessInfoResponse (proc_info, response); - return SendPacketNoLock (response.GetString()); - } +GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID( + StringExtractorGDBRemote &packet) { + // Packet format: "qProcessInfoPID:%i" where %i is the pid + packet.SetFilePos(::strlen("qProcessInfoPID:")); + lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID); + if (pid != LLDB_INVALID_PROCESS_ID) { + ProcessInstanceInfo proc_info; + if (Host::GetProcessInfo(pid, proc_info)) { + StreamString response; + CreateProcessInfoResponse(proc_info, response); + return SendPacketNoLock(response.GetString()); } - return SendErrorResponse (1); + } + return SendErrorResponse(1); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) -{ - m_proc_infos_index = 0; - m_proc_infos.Clear(); - - ProcessInstanceInfoMatch match_info; - packet.SetFilePos(::strlen ("qfProcessInfo")); - if (packet.GetChar() == ':') - { - llvm::StringRef key; - llvm::StringRef value; - while (packet.GetNameColonValue(key, value)) - { - bool success = true; - if (key.equals("name")) - { - StringExtractor extractor(value); - std::string file; - extractor.GetHexByteString(file); - match_info.GetProcessInfo().GetExecutableFile().SetFile(file.c_str(), false); - } - else if (key.equals("name_match")) - { - NameMatchType name_match = llvm::StringSwitch<NameMatchType>(value) - .Case("equals", eNameMatchEquals) - .Case("starts_with", eNameMatchStartsWith) - .Case("ends_with", eNameMatchEndsWith) - .Case("contains", eNameMatchContains) - .Case("regex", eNameMatchRegularExpression) - .Default(eNameMatchIgnore); - match_info.SetNameMatchType(name_match); - if (name_match == eNameMatchIgnore) - return SendErrorResponse(2); - } - else if (key.equals("pid")) - { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - if (value.getAsInteger(0, pid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetProcessID(pid); - } - else if (key.equals("parent_pid")) - { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - if (value.getAsInteger(0, pid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetParentProcessID(pid); - } - else if (key.equals("uid")) - { - uint32_t uid = UINT32_MAX; - if (value.getAsInteger(0, uid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetUserID(uid); - } - else if (key.equals("gid")) - { - uint32_t gid = UINT32_MAX; - if (value.getAsInteger(0, gid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetGroupID(gid); - } - else if (key.equals("euid")) - { - uint32_t uid = UINT32_MAX; - if (value.getAsInteger(0, uid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetEffectiveUserID(uid); - } - else if (key.equals("egid")) - { - uint32_t gid = UINT32_MAX; - if (value.getAsInteger(0, gid)) - return SendErrorResponse(2); - match_info.GetProcessInfo().SetEffectiveGroupID(gid); - } - else if (key.equals("all_users")) - { - match_info.SetMatchAllUsers(Args::StringToBoolean(value, false, &success)); - } - else if (key.equals("triple")) - { - match_info.GetProcessInfo().GetArchitecture().SetTriple(value.str().c_str(), NULL); - } - else - { - success = false; - } - - if (!success) - return SendErrorResponse (2); - } - } - - if (Host::FindProcesses (match_info, m_proc_infos)) - { - // We found something, return the first item by calling the get - // subsequent process info packet handler... - return Handle_qsProcessInfo (packet); +GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( + StringExtractorGDBRemote &packet) { + m_proc_infos_index = 0; + m_proc_infos.Clear(); + + ProcessInstanceInfoMatch match_info; + packet.SetFilePos(::strlen("qfProcessInfo")); + if (packet.GetChar() == ':') { + llvm::StringRef key; + llvm::StringRef value; + while (packet.GetNameColonValue(key, value)) { + bool success = true; + if (key.equals("name")) { + StringExtractor extractor(value); + std::string file; + extractor.GetHexByteString(file); + match_info.GetProcessInfo().GetExecutableFile().SetFile(file.c_str(), + false); + } else if (key.equals("name_match")) { + NameMatchType name_match = + llvm::StringSwitch<NameMatchType>(value) + .Case("equals", eNameMatchEquals) + .Case("starts_with", eNameMatchStartsWith) + .Case("ends_with", eNameMatchEndsWith) + .Case("contains", eNameMatchContains) + .Case("regex", eNameMatchRegularExpression) + .Default(eNameMatchIgnore); + match_info.SetNameMatchType(name_match); + if (name_match == eNameMatchIgnore) + return SendErrorResponse(2); + } else if (key.equals("pid")) { + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + if (value.getAsInteger(0, pid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetProcessID(pid); + } else if (key.equals("parent_pid")) { + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + if (value.getAsInteger(0, pid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetParentProcessID(pid); + } else if (key.equals("uid")) { + uint32_t uid = UINT32_MAX; + if (value.getAsInteger(0, uid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetUserID(uid); + } else if (key.equals("gid")) { + uint32_t gid = UINT32_MAX; + if (value.getAsInteger(0, gid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetGroupID(gid); + } else if (key.equals("euid")) { + uint32_t uid = UINT32_MAX; + if (value.getAsInteger(0, uid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetEffectiveUserID(uid); + } else if (key.equals("egid")) { + uint32_t gid = UINT32_MAX; + if (value.getAsInteger(0, gid)) + return SendErrorResponse(2); + match_info.GetProcessInfo().SetEffectiveGroupID(gid); + } else if (key.equals("all_users")) { + match_info.SetMatchAllUsers( + Args::StringToBoolean(value, false, &success)); + } else if (key.equals("triple")) { + match_info.GetProcessInfo().GetArchitecture().SetTriple( + value.str().c_str(), NULL); + } else { + success = false; + } + + if (!success) + return SendErrorResponse(2); } - return SendErrorResponse (3); + } + + if (Host::FindProcesses(match_info, m_proc_infos)) { + // We found something, return the first item by calling the get + // subsequent process info packet handler... + return Handle_qsProcessInfo(packet); + } + return SendErrorResponse(3); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) -{ - if (m_proc_infos_index < m_proc_infos.GetSize()) - { - StreamString response; - CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); - ++m_proc_infos_index; - return SendPacketNoLock (response.GetString()); - } - return SendErrorResponse (4); +GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo( + StringExtractorGDBRemote &packet) { + if (m_proc_infos_index < m_proc_infos.GetSize()) { + StreamString response; + CreateProcessInfoResponse( + m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); + ++m_proc_infos_index; + return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(4); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qUserName (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerCommon::Handle_qUserName( + StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); - - // Packet format: "qUserName:%i" where %i is the uid - packet.SetFilePos(::strlen ("qUserName:")); - uint32_t uid = packet.GetU32 (UINT32_MAX); - if (uid != UINT32_MAX) - { - std::string name; - if (HostInfo::LookupUserName(uid, name)) - { - StreamString response; - response.PutCStringAsRawHex8 (name.c_str()); - return SendPacketNoLock (response.GetString()); - } + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); + + // Packet format: "qUserName:%i" where %i is the uid + packet.SetFilePos(::strlen("qUserName:")); + uint32_t uid = packet.GetU32(UINT32_MAX); + if (uid != UINT32_MAX) { + std::string name; + if (HostInfo::LookupUserName(uid, name)) { + StreamString response; + response.PutCStringAsRawHex8(name.c_str()); + return SendPacketNoLock(response.GetString()); } - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); + } + if (log) + log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); #endif - return SendErrorResponse (5); - + return SendErrorResponse(5); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qGroupName (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerCommon::Handle_qGroupName( + StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) - // Packet format: "qGroupName:%i" where %i is the gid - packet.SetFilePos(::strlen ("qGroupName:")); - uint32_t gid = packet.GetU32 (UINT32_MAX); - if (gid != UINT32_MAX) - { - std::string name; - if (HostInfo::LookupGroupName(gid, name)) - { - StreamString response; - response.PutCStringAsRawHex8 (name.c_str()); - return SendPacketNoLock (response.GetString()); - } + // Packet format: "qGroupName:%i" where %i is the gid + packet.SetFilePos(::strlen("qGroupName:")); + uint32_t gid = packet.GetU32(UINT32_MAX); + if (gid != UINT32_MAX) { + std::string name; + if (HostInfo::LookupGroupName(gid, name)) { + StreamString response; + response.PutCStringAsRawHex8(name.c_str()); + return SendPacketNoLock(response.GetString()); } + } #endif - return SendErrorResponse (6); + return SendErrorResponse(6); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("qSpeedTest:")); - - llvm::StringRef key; - llvm::StringRef value; - bool success = packet.GetNameColonValue(key, value); - if (success && key.equals("response_size")) - { - uint32_t response_size = 0; - if (!value.getAsInteger(0, response_size)) - { - if (response_size == 0) - return SendOKResponse(); - StreamString response; - uint32_t bytes_left = response_size; - response.PutCString("data:"); - while (bytes_left > 0) - { - if (bytes_left >= 26) - { - response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - bytes_left -= 26; - } - else - { - response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - bytes_left = 0; - } - } - return SendPacketNoLock (response.GetString()); +GDBRemoteCommunicationServerCommon::Handle_qSpeedTest( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qSpeedTest:")); + + llvm::StringRef key; + llvm::StringRef value; + bool success = packet.GetNameColonValue(key, value); + if (success && key.equals("response_size")) { + uint32_t response_size = 0; + if (!value.getAsInteger(0, response_size)) { + if (response_size == 0) + return SendOKResponse(); + StreamString response; + uint32_t bytes_left = response_size; + response.PutCString("data:"); + while (bytes_left > 0) { + if (bytes_left >= 26) { + response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + bytes_left -= 26; + } else { + response.Printf("%*.*s;", bytes_left, bytes_left, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + bytes_left = 0; } + } + return SendPacketNoLock(response.GetString()); } - return SendErrorResponse (7); + } + return SendErrorResponse(7); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:open:")); - std::string path; - packet.GetHexByteStringTerminatedBy(path,','); - if (!path.empty()) - { - if (packet.GetChar() == ',') - { - uint32_t flags = File::ConvertOpenOptionsForPOSIXOpen( - packet.GetHexMaxU32(false, 0)); - if (packet.GetChar() == ',') - { - mode_t mode = packet.GetHexMaxU32(false, 0600); - Error error; - const FileSpec path_spec{path, true}; - int fd = ::open(path_spec.GetCString(), flags, mode); - const int save_errno = fd == -1 ? errno : 0; - StreamString response; - response.PutChar('F'); - response.Printf("%i", fd); - if (save_errno) - response.Printf(",%i", save_errno); - return SendPacketNoLock(response.GetString()); - } - } +GDBRemoteCommunicationServerCommon::Handle_vFile_Open( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:open:")); + std::string path; + packet.GetHexByteStringTerminatedBy(path, ','); + if (!path.empty()) { + if (packet.GetChar() == ',') { + uint32_t flags = + File::ConvertOpenOptionsForPOSIXOpen(packet.GetHexMaxU32(false, 0)); + if (packet.GetChar() == ',') { + mode_t mode = packet.GetHexMaxU32(false, 0600); + Error error; + const FileSpec path_spec{path, true}; + int fd = ::open(path_spec.GetCString(), flags, mode); + const int save_errno = fd == -1 ? errno : 0; + StreamString response; + response.PutChar('F'); + response.Printf("%i", fd); + if (save_errno) + response.Printf(",%i", save_errno); + return SendPacketNoLock(response.GetString()); + } } - return SendErrorResponse(18); + } + return SendErrorResponse(18); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Close (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:close:")); - int fd = packet.GetS32(-1); - Error error; - int err = -1; - int save_errno = 0; - if (fd >= 0) - { - err = close(fd); - save_errno = err == -1 ? errno : 0; - } - else - { - save_errno = EINVAL; - } - StreamString response; - response.PutChar('F'); - response.Printf("%i", err); - if (save_errno) - response.Printf(",%i", save_errno); - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerCommon::Handle_vFile_Close( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:close:")); + int fd = packet.GetS32(-1); + Error error; + int err = -1; + int save_errno = 0; + if (fd >= 0) { + err = close(fd); + save_errno = err == -1 ? errno : 0; + } else { + save_errno = EINVAL; + } + StreamString response; + response.PutChar('F'); + response.Printf("%i", err); + if (save_errno) + response.Printf(",%i", save_errno); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_pRead (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( + StringExtractorGDBRemote &packet) { #ifdef _WIN32 - // Not implemented on Windows - return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); + // Not implemented on Windows + return SendUnimplementedResponse( + "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); #else - StreamGDBRemote response; - packet.SetFilePos(::strlen("vFile:pread:")); - int fd = packet.GetS32(-1); - if (packet.GetChar() == ',') - { - uint64_t count = packet.GetU64(UINT64_MAX); - if (packet.GetChar() == ',') - { - uint64_t offset = packet.GetU64(UINT32_MAX); - if (count == UINT64_MAX) - { - response.Printf("F-1:%i", EINVAL); - return SendPacketNoLock(response.GetString()); - } - - std::string buffer(count, 0); - const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset); - const int save_errno = bytes_read == -1 ? errno : 0; - response.PutChar('F'); - response.Printf("%zi", bytes_read); - if (save_errno) - response.Printf(",%i", save_errno); - else - { - response.PutChar(';'); - response.PutEscapedBytes(&buffer[0], bytes_read); - } - return SendPacketNoLock(response.GetString()); - } + StreamGDBRemote response; + packet.SetFilePos(::strlen("vFile:pread:")); + int fd = packet.GetS32(-1); + if (packet.GetChar() == ',') { + uint64_t count = packet.GetU64(UINT64_MAX); + if (packet.GetChar() == ',') { + uint64_t offset = packet.GetU64(UINT32_MAX); + if (count == UINT64_MAX) { + response.Printf("F-1:%i", EINVAL); + return SendPacketNoLock(response.GetString()); + } + + std::string buffer(count, 0); + const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset); + const int save_errno = bytes_read == -1 ? errno : 0; + response.PutChar('F'); + response.Printf("%zi", bytes_read); + if (save_errno) + response.Printf(",%i", save_errno); + else { + response.PutChar(';'); + response.PutEscapedBytes(&buffer[0], bytes_read); + } + return SendPacketNoLock(response.GetString()); } - return SendErrorResponse(21); + } + return SendErrorResponse(21); #endif } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( + StringExtractorGDBRemote &packet) { #ifdef _WIN32 - return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite() unimplemented"); + return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_" + "vFile_pWrite() unimplemented"); #else - packet.SetFilePos(::strlen("vFile:pwrite:")); - - StreamGDBRemote response; - response.PutChar('F'); - - int fd = packet.GetU32(UINT32_MAX); - if (packet.GetChar() == ',') - { - off_t offset = packet.GetU64(UINT32_MAX); - if (packet.GetChar() == ',') - { - std::string buffer; - if (packet.GetEscapedBinaryData(buffer)) - { - const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset); - const int save_errno = bytes_written == -1 ? errno : 0; - response.Printf("%zi", bytes_written); - if (save_errno) - response.Printf(",%i", save_errno); - } - else - { - response.Printf ("-1,%i", EINVAL); - } - return SendPacketNoLock(response.GetString()); - } + packet.SetFilePos(::strlen("vFile:pwrite:")); + + StreamGDBRemote response; + response.PutChar('F'); + + int fd = packet.GetU32(UINT32_MAX); + if (packet.GetChar() == ',') { + off_t offset = packet.GetU64(UINT32_MAX); + if (packet.GetChar() == ',') { + std::string buffer; + if (packet.GetEscapedBinaryData(buffer)) { + const ssize_t bytes_written = + ::pwrite(fd, buffer.data(), buffer.size(), offset); + const int save_errno = bytes_written == -1 ? errno : 0; + response.Printf("%zi", bytes_written); + if (save_errno) + response.Printf(",%i", save_errno); + } else { + response.Printf("-1,%i", EINVAL); + } + return SendPacketNoLock(response.GetString()); } - return SendErrorResponse(27); + } + return SendErrorResponse(27); #endif } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Size (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:size:")); - std::string path; - packet.GetHexByteString(path); - if (!path.empty()) - { - lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path.c_str(), false)); - StreamString response; - response.PutChar('F'); - response.PutHex64(retcode); - if (retcode == UINT64_MAX) - { - response.PutChar(','); - response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode() - } - return SendPacketNoLock(response.GetString()); - } - return SendErrorResponse(22); -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Mode (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:mode:")); - std::string path; - packet.GetHexByteString(path); - if (!path.empty()) - { - Error error; - const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); - StreamString response; - response.Printf("F%u", mode); - if (mode == 0 || error.Fail()) - response.Printf(",%i", (int)error.GetError()); - return SendPacketNoLock(response.GetString()); - } - return SendErrorResponse(23); -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Exists (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:exists:")); - std::string path; - packet.GetHexByteString(path); - if (!path.empty()) - { - bool retcode = FileSystem::GetFileExists(FileSpec(path.c_str(), false)); - StreamString response; - response.PutChar('F'); - response.PutChar(','); - if (retcode) - response.PutChar('1'); - else - response.PutChar('0'); - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerCommon::Handle_vFile_Size( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:size:")); + std::string path; + packet.GetHexByteString(path); + if (!path.empty()) { + lldb::user_id_t retcode = + FileSystem::GetFileSize(FileSpec(path.c_str(), false)); + StreamString response; + response.PutChar('F'); + response.PutHex64(retcode); + if (retcode == UINT64_MAX) { + response.PutChar(','); + response.PutHex64( + retcode); // TODO: replace with Host::GetSyswideErrorCode() } - return SendErrorResponse(24); + return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(22); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_symlink (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:symlink:")); - std::string dst, src; - packet.GetHexByteStringTerminatedBy(dst, ','); - packet.GetChar(); // Skip ',' char - packet.GetHexByteString(src); - Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); +GDBRemoteCommunicationServerCommon::Handle_vFile_Mode( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:mode:")); + std::string path; + packet.GetHexByteString(path); + if (!path.empty()) { + Error error; + const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); StreamString response; - response.Printf("F%u,%u", error.GetError(), error.GetError()); + response.Printf("F%u", mode); + if (mode == 0 || error.Fail()) + response.Printf(",%i", (int)error.GetError()); return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(23); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_unlink (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:unlink:")); - std::string path; - packet.GetHexByteString(path); - Error error = FileSystem::Unlink(FileSpec{path, true}); +GDBRemoteCommunicationServerCommon::Handle_vFile_Exists( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:exists:")); + std::string path; + packet.GetHexByteString(path); + if (!path.empty()) { + bool retcode = FileSystem::GetFileExists(FileSpec(path.c_str(), false)); StreamString response; - response.Printf("F%u,%u", error.GetError(), error.GetError()); + response.PutChar('F'); + response.PutChar(','); + if (retcode) + response.PutChar('1'); + else + response.PutChar('0'); return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(24); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("qPlatform_shell:")); - std::string path; - std::string working_dir; - packet.GetHexByteStringTerminatedBy(path,','); - if (!path.empty()) - { - if (packet.GetChar() == ',') - { - // FIXME: add timeout to qPlatform_shell packet - // uint32_t timeout = packet.GetHexMaxU32(false, 32); - uint32_t timeout = 10; - if (packet.GetChar() == ',') - packet.GetHexByteString(working_dir); - int status, signo; - std::string output; - Error err = Host::RunShellCommand(path.c_str(), - FileSpec{working_dir, true}, - &status, &signo, &output, timeout); - StreamGDBRemote response; - if (err.Fail()) - { - response.PutCString("F,"); - response.PutHex32(UINT32_MAX); - } - else - { - response.PutCString("F,"); - response.PutHex32(status); - response.PutChar(','); - response.PutHex32(signo); - response.PutChar(','); - response.PutEscapedBytes(output.c_str(), output.size()); - } - return SendPacketNoLock(response.GetString()); - } - } - return SendErrorResponse(24); +GDBRemoteCommunicationServerCommon::Handle_vFile_symlink( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:symlink:")); + std::string dst, src; + packet.GetHexByteStringTerminatedBy(dst, ','); + packet.GetChar(); // Skip ',' char + packet.GetHexByteString(src); + Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); + StreamString response; + response.Printf("F%u,%u", error.GetError(), error.GetError()); + return SendPacketNoLock(response.GetString()); } - GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_Stat (StringExtractorGDBRemote &packet) -{ - return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented"); +GDBRemoteCommunicationServerCommon::Handle_vFile_unlink( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:unlink:")); + std::string path; + packet.GetHexByteString(path); + Error error = FileSystem::Unlink(FileSpec{path, true}); + StreamString response; + response.Printf("F%u,%u", error.GetError(), error.GetError()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("vFile:MD5:")); - std::string path; - packet.GetHexByteString(path); - if (!path.empty()) - { - uint64_t a,b; - StreamGDBRemote response; - if (!FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b)) - { - response.PutCString("F,"); - response.PutCString("x"); - } - else - { - response.PutCString("F,"); - response.PutHex64(a); - response.PutHex64(b); - } - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qPlatform_shell:")); + std::string path; + std::string working_dir; + packet.GetHexByteStringTerminatedBy(path, ','); + if (!path.empty()) { + if (packet.GetChar() == ',') { + // FIXME: add timeout to qPlatform_shell packet + // uint32_t timeout = packet.GetHexMaxU32(false, 32); + uint32_t timeout = 10; + if (packet.GetChar() == ',') + packet.GetHexByteString(working_dir); + int status, signo; + std::string output; + Error err = + Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true}, + &status, &signo, &output, timeout); + StreamGDBRemote response; + if (err.Fail()) { + response.PutCString("F,"); + response.PutHex32(UINT32_MAX); + } else { + response.PutCString("F,"); + response.PutHex32(status); + response.PutChar(','); + response.PutHex32(signo); + response.PutChar(','); + response.PutEscapedBytes(output.c_str(), output.size()); + } + return SendPacketNoLock(response.GetString()); } - return SendErrorResponse(25); + } + return SendErrorResponse(24); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("qPlatform_mkdir:")); - mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); - if (packet.GetChar() == ',') - { - std::string path; - packet.GetHexByteString(path); - Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode); - - StreamGDBRemote response; - response.Printf("F%u", error.GetError()); +GDBRemoteCommunicationServerCommon::Handle_vFile_Stat( + StringExtractorGDBRemote &packet) { + return SendUnimplementedResponse( + "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented"); +} - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerCommon::Handle_vFile_MD5( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("vFile:MD5:")); + std::string path; + packet.GetHexByteString(path); + if (!path.empty()) { + uint64_t a, b; + StreamGDBRemote response; + if (!FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b)) { + response.PutCString("F,"); + response.PutCString("x"); + } else { + response.PutCString("F,"); + response.PutHex64(a); + response.PutHex64(b); } - return SendErrorResponse(20); + return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(25); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("qPlatform_chmod:")); - - mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); - if (packet.GetChar() == ',') - { - std::string path; - packet.GetHexByteString(path); - Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode); +GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qPlatform_mkdir:")); + mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); + if (packet.GetChar() == ',') { + std::string path; + packet.GetHexByteString(path); + Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode); - StreamGDBRemote response; - response.Printf("F%u", error.GetError()); + StreamGDBRemote response; + response.Printf("F%u", error.GetError()); - return SendPacketNoLock(response.GetString()); - } - return SendErrorResponse(19); + return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(20); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qPlatform_chmod:")); + + mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); + if (packet.GetChar() == ',') { + std::string path; + packet.GetHexByteString(path); + Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode); + StreamGDBRemote response; + response.Printf("F%u", error.GetError()); - // Features common to lldb-platform and llgs. - uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less - response.Printf ("PacketSize=%x", max_packet_size); + return SendPacketNoLock(response.GetString()); + } + return SendErrorResponse(19); +} - response.PutCString (";QStartNoAckMode+"); - response.PutCString (";QThreadSuffixSupported+"); - response.PutCString (";QListThreadsInStopReply+"); - response.PutCString (";qEcho+"); +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerCommon::Handle_qSupported( + StringExtractorGDBRemote &packet) { + StreamGDBRemote response; + + // Features common to lldb-platform and llgs. + uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet + // size--debugger can always use less + response.Printf("PacketSize=%x", max_packet_size); + + response.PutCString(";QStartNoAckMode+"); + response.PutCString(";QThreadSuffixSupported+"); + response.PutCString(";QListThreadsInStopReply+"); + response.PutCString(";qEcho+"); #if defined(__linux__) - response.PutCString (";qXfer:auxv:read+"); + response.PutCString(";qXfer:auxv:read+"); #endif - return SendPacketNoLock(response.GetString()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet) -{ - m_thread_suffix_supported = true; - return SendOKResponse(); +GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported( + StringExtractorGDBRemote &packet) { + m_thread_suffix_supported = true; + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet) -{ - m_list_threads_in_stop_reply = true; - return SendOKResponse(); +GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply( + StringExtractorGDBRemote &packet) { + m_list_threads_in_stop_reply = true; + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QSetDetachOnError:")); - if (packet.GetU32(0)) - m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError); - else - m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError); - return SendOKResponse (); +GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetDetachOnError:")); + if (packet.GetU32(0)) + m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError); + else + m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) -{ - // Send response first before changing m_send_acks to we ack this packet - PacketResult packet_result = SendOKResponse (); - m_send_acks = false; - return packet_result; +GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode( + StringExtractorGDBRemote &packet) { + // Send response first before changing m_send_acks to we ack this packet + PacketResult packet_result = SendOKResponse(); + m_send_acks = false; + return packet_result; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QSetSTDIN:")); - FileAction file_action; - std::string path; - packet.GetHexByteString(path); - const bool read = true; - const bool write = false; - if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) - { - m_process_launch_info.AppendFileAction(file_action); - return SendOKResponse (); - } - return SendErrorResponse (15); +GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetSTDIN:")); + FileAction file_action; + std::string path; + packet.GetHexByteString(path); + const bool read = true; + const bool write = false; + if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) { + m_process_launch_info.AppendFileAction(file_action); + return SendOKResponse(); + } + return SendErrorResponse(15); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QSetSTDOUT:")); - FileAction file_action; - std::string path; - packet.GetHexByteString(path); - const bool read = false; - const bool write = true; - if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) - { - m_process_launch_info.AppendFileAction(file_action); - return SendOKResponse (); - } - return SendErrorResponse (16); +GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetSTDOUT:")); + FileAction file_action; + std::string path; + packet.GetHexByteString(path); + const bool read = false; + const bool write = true; + if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) { + m_process_launch_info.AppendFileAction(file_action); + return SendOKResponse(); + } + return SendErrorResponse(16); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QSetSTDERR:")); - FileAction file_action; - std::string path; - packet.GetHexByteString(path); - const bool read = false; - const bool write = true; - if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) - { - m_process_launch_info.AppendFileAction(file_action); - return SendOKResponse (); - } - return SendErrorResponse (17); +GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetSTDERR:")); + FileAction file_action; + std::string path; + packet.GetHexByteString(path); + const bool read = false; + const bool write = true; + if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) { + m_process_launch_info.AppendFileAction(file_action); + return SendOKResponse(); + } + return SendErrorResponse(17); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet) -{ - if (m_process_launch_error.Success()) - return SendOKResponse(); - StreamString response; - response.PutChar('E'); - response.PutCString(m_process_launch_error.AsCString("<unknown error>")); - return SendPacketNoLock (response.GetString()); +GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess( + StringExtractorGDBRemote &packet) { + if (m_process_launch_error.Success()) + return SendOKResponse(); + StreamString response; + response.PutChar('E'); + response.PutCString(m_process_launch_error.AsCString("<unknown error>")); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QEnvironment (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QEnvironment:")); - const uint32_t bytes_left = packet.GetBytesLeft(); - if (bytes_left > 0) - { - m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); - return SendOKResponse (); - } - return SendErrorResponse (12); +GDBRemoteCommunicationServerCommon::Handle_QEnvironment( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QEnvironment:")); + const uint32_t bytes_left = packet.GetBytesLeft(); + if (bytes_left > 0) { + m_process_launch_info.GetEnvironmentEntries().AppendArgument(packet.Peek()); + return SendOKResponse(); + } + return SendErrorResponse(12); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen("QEnvironmentHexEncoded:")); - const uint32_t bytes_left = packet.GetBytesLeft(); - if (bytes_left > 0) - { - std::string str; - packet.GetHexByteString(str); - m_process_launch_info.GetEnvironmentEntries().AppendArgument(str.c_str()); - return SendOKResponse(); - } - return SendErrorResponse(12); +GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QEnvironmentHexEncoded:")); + const uint32_t bytes_left = packet.GetBytesLeft(); + if (bytes_left > 0) { + std::string str; + packet.GetHexByteString(str); + m_process_launch_info.GetEnvironmentEntries().AppendArgument(str.c_str()); + return SendOKResponse(); + } + return SendErrorResponse(12); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QLaunchArch (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QLaunchArch:")); - const uint32_t bytes_left = packet.GetBytesLeft(); - if (bytes_left > 0) - { - const char* arch_triple = packet.Peek(); - ArchSpec arch_spec(arch_triple,NULL); - m_process_launch_info.SetArchitecture(arch_spec); - return SendOKResponse(); - } - return SendErrorResponse(13); +GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QLaunchArch:")); + const uint32_t bytes_left = packet.GetBytesLeft(); + if (bytes_left > 0) { + const char *arch_triple = packet.Peek(); + ArchSpec arch_spec(arch_triple, NULL); + m_process_launch_info.SetArchitecture(arch_spec); + return SendOKResponse(); + } + return SendErrorResponse(13); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_A (StringExtractorGDBRemote &packet) -{ - // The 'A' packet is the most over designed packet ever here with - // redundant argument indexes, redundant argument lengths and needed hex - // encoded argument string values. Really all that is needed is a comma - // separated hex encoded argument value list, but we will stay true to the - // documented version of the 'A' packet here... - - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - int actual_arg_index = 0; - - packet.SetFilePos(1); // Skip the 'A' - bool success = true; - while (success && packet.GetBytesLeft() > 0) - { - // Decode the decimal argument string length. This length is the - // number of hex nibbles in the argument string value. - const uint32_t arg_len = packet.GetU32(UINT32_MAX); - if (arg_len == UINT32_MAX) +GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { + // The 'A' packet is the most over designed packet ever here with + // redundant argument indexes, redundant argument lengths and needed hex + // encoded argument string values. Really all that is needed is a comma + // separated hex encoded argument value list, but we will stay true to the + // documented version of the 'A' packet here... + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + int actual_arg_index = 0; + + packet.SetFilePos(1); // Skip the 'A' + bool success = true; + while (success && packet.GetBytesLeft() > 0) { + // Decode the decimal argument string length. This length is the + // number of hex nibbles in the argument string value. + const uint32_t arg_len = packet.GetU32(UINT32_MAX); + if (arg_len == UINT32_MAX) + success = false; + else { + // Make sure the argument hex string length is followed by a comma + if (packet.GetChar() != ',') + success = false; + else { + // Decode the argument index. We ignore this really because + // who would really send down the arguments in a random order??? + const uint32_t arg_idx = packet.GetU32(UINT32_MAX); + if (arg_idx == UINT32_MAX) + success = false; + else { + // Make sure the argument index is followed by a comma + if (packet.GetChar() != ',') success = false; - else - { - // Make sure the argument hex string length is followed by a comma - if (packet.GetChar() != ',') - success = false; - else - { - // Decode the argument index. We ignore this really because - // who would really send down the arguments in a random order??? - const uint32_t arg_idx = packet.GetU32(UINT32_MAX); - if (arg_idx == UINT32_MAX) - success = false; - else - { - // Make sure the argument index is followed by a comma - if (packet.GetChar() != ',') - success = false; - else - { - // Decode the argument string value from hex bytes - // back into a UTF8 string and make sure the length - // matches the one supplied in the packet - std::string arg; - if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2)) - success = false; - else - { - // If there are any bytes left - if (packet.GetBytesLeft()) - { - if (packet.GetChar() != ',') - success = false; - } - - if (success) - { - if (arg_idx == 0) - m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false); - m_process_launch_info.GetArguments().AppendArgument(arg.c_str()); - if (log) - log->Printf ("LLGSPacketHandler::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str ()); - ++actual_arg_index; - } - } - } - } + else { + // Decode the argument string value from hex bytes + // back into a UTF8 string and make sure the length + // matches the one supplied in the packet + std::string arg; + if (packet.GetHexByteStringFixedLength(arg, arg_len) != + (arg_len / 2)) + success = false; + else { + // If there are any bytes left + if (packet.GetBytesLeft()) { + if (packet.GetChar() != ',') + success = false; + } + + if (success) { + if (arg_idx == 0) + m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), + false); + m_process_launch_info.GetArguments().AppendArgument( + arg.c_str()); + if (log) + log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", + __FUNCTION__, actual_arg_index, arg.c_str()); + ++actual_arg_index; + } } + } } + } } - - if (success) - { - m_process_launch_error = LaunchProcess (); - if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) - { - return SendOKResponse (); - } - else - { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", - __FUNCTION__, - m_process_launch_error.AsCString()); - - } + } + + if (success) { + m_process_launch_error = LaunchProcess(); + if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { + return SendOKResponse(); + } else { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", + __FUNCTION__, m_process_launch_error.AsCString()); } - return SendErrorResponse (8); + } + return SendErrorResponse(8); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qEcho (StringExtractorGDBRemote &packet) -{ - // Just echo back the exact same packet for qEcho... - return SendPacketNoLock(packet.GetStringRef()); +GDBRemoteCommunicationServerCommon::Handle_qEcho( + StringExtractorGDBRemote &packet) { + // Just echo back the exact same packet for qEcho... + return SendPacketNoLock(packet.GetStringRef()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qModuleInfo (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("qModuleInfo:")); - - std::string module_path; - packet.GetHexByteStringTerminatedBy(module_path, ';'); - if (module_path.empty()) - return SendErrorResponse (1); - - if (packet.GetChar() != ';') - return SendErrorResponse (2); - - std::string triple; - packet.GetHexByteString(triple); - ArchSpec arch(triple.c_str()); - - const FileSpec req_module_path_spec(module_path.c_str(), true); - const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); - const ModuleSpec module_spec(module_path_spec, arch); - - ModuleSpecList module_specs; - if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs)) - return SendErrorResponse (3); - - ModuleSpec matched_module_spec; - if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) - return SendErrorResponse (4); - - const auto file_offset = matched_module_spec.GetObjectOffset(); - const auto file_size = matched_module_spec.GetObjectSize(); - const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); - - StreamGDBRemote response; - - if (uuid_str.empty()) - { - std::string md5_hash; - if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash)) - return SendErrorResponse (5); - response.PutCString ("md5:"); - response.PutCStringAsRawHex8(md5_hash.c_str()); - } - else{ - response.PutCString ("uuid:"); - response.PutCStringAsRawHex8(uuid_str.c_str()); - } - response.PutChar(';'); +GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qModuleInfo:")); + + std::string module_path; + packet.GetHexByteStringTerminatedBy(module_path, ';'); + if (module_path.empty()) + return SendErrorResponse(1); + + if (packet.GetChar() != ';') + return SendErrorResponse(2); + + std::string triple; + packet.GetHexByteString(triple); + ArchSpec arch(triple.c_str()); + + const FileSpec req_module_path_spec(module_path.c_str(), true); + const FileSpec module_path_spec = + FindModuleFile(req_module_path_spec.GetPath(), arch); + const ModuleSpec module_spec(module_path_spec, arch); + + ModuleSpecList module_specs; + if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, + module_specs)) + return SendErrorResponse(3); + + ModuleSpec matched_module_spec; + if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) + return SendErrorResponse(4); + + const auto file_offset = matched_module_spec.GetObjectOffset(); + const auto file_size = matched_module_spec.GetObjectSize(); + const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); + + StreamGDBRemote response; + + if (uuid_str.empty()) { + std::string md5_hash; + if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), + file_offset, file_size, md5_hash)) + return SendErrorResponse(5); + response.PutCString("md5:"); + response.PutCStringAsRawHex8(md5_hash.c_str()); + } else { + response.PutCString("uuid:"); + response.PutCStringAsRawHex8(uuid_str.c_str()); + } + response.PutChar(';'); + + const auto &module_arch = matched_module_spec.GetArchitecture(); + response.PutCString("triple:"); + response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str()); + response.PutChar(';'); + + response.PutCString("file_path:"); + response.PutCStringAsRawHex8(module_path_spec.GetCString()); + response.PutChar(';'); + response.PutCString("file_offset:"); + response.PutHex64(file_offset); + response.PutChar(';'); + response.PutCString("file_size:"); + response.PutHex64(file_size); + response.PutChar(';'); + + return SendPacketNoLock(response.GetString()); +} - const auto &module_arch = matched_module_spec.GetArchitecture(); +void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( + const ProcessInstanceInfo &proc_info, StreamString &response) { + response.Printf( + "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", + proc_info.GetProcessID(), proc_info.GetParentProcessID(), + proc_info.GetUserID(), proc_info.GetGroupID(), + proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); + response.PutCString("name:"); + response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); + response.PutChar(';'); + const ArchSpec &proc_arch = proc_info.GetArchitecture(); + if (proc_arch.IsValid()) { + const llvm::Triple &proc_triple = proc_arch.GetTriple(); response.PutCString("triple:"); - response.PutCStringAsRawHex8( module_arch.GetTriple().getTriple().c_str()); - response.PutChar(';'); - - response.PutCString("file_path:"); - response.PutCStringAsRawHex8(module_path_spec.GetCString()); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); - response.PutCString("file_offset:"); - response.PutHex64(file_offset); - response.PutChar(';'); - response.PutCString("file_size:"); - response.PutHex64(file_size); - response.PutChar(';'); - - return SendPacketNoLock(response.GetString()); + } } -void -GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, - StreamString &response) -{ - response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", - proc_info.GetProcessID(), - proc_info.GetParentProcessID(), - proc_info.GetUserID(), - proc_info.GetGroupID(), - proc_info.GetEffectiveUserID(), - proc_info.GetEffectiveGroupID()); - response.PutCString ("name:"); - response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); - response.PutChar(';'); - const ArchSpec &proc_arch = proc_info.GetArchitecture(); - if (proc_arch.IsValid()) - { - const llvm::Triple &proc_triple = proc_arch.GetTriple(); - response.PutCString("triple:"); - response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); - response.PutChar(';'); - } -} - -void -GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle ( - const ProcessInstanceInfo &proc_info, StreamString &response) -{ - response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;", - proc_info.GetProcessID(), - proc_info.GetParentProcessID(), - proc_info.GetUserID(), - proc_info.GetGroupID(), - proc_info.GetEffectiveUserID(), - proc_info.GetEffectiveGroupID()); - - const ArchSpec &proc_arch = proc_info.GetArchitecture(); - if (proc_arch.IsValid()) - { - const llvm::Triple &proc_triple = proc_arch.GetTriple(); +void GDBRemoteCommunicationServerCommon:: + CreateProcessInfoResponse_DebugServerStyle( + const ProcessInstanceInfo &proc_info, StreamString &response) { + response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64 + ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;", + proc_info.GetProcessID(), proc_info.GetParentProcessID(), + proc_info.GetUserID(), proc_info.GetGroupID(), + proc_info.GetEffectiveUserID(), + proc_info.GetEffectiveGroupID()); + + const ArchSpec &proc_arch = proc_info.GetArchitecture(); + if (proc_arch.IsValid()) { + const llvm::Triple &proc_triple = proc_arch.GetTriple(); #if defined(__APPLE__) - // We'll send cputype/cpusubtype. - const uint32_t cpu_type = proc_arch.GetMachOCPUType(); - if (cpu_type != 0) - response.Printf ("cputype:%" PRIx32 ";", cpu_type); - - const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType(); - if (cpu_subtype != 0) - response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype); - - const std::string vendor = proc_triple.getVendorName (); - if (!vendor.empty ()) - response.Printf ("vendor:%s;", vendor.c_str ()); + // We'll send cputype/cpusubtype. + const uint32_t cpu_type = proc_arch.GetMachOCPUType(); + if (cpu_type != 0) + response.Printf("cputype:%" PRIx32 ";", cpu_type); + + const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType(); + if (cpu_subtype != 0) + response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype); + + const std::string vendor = proc_triple.getVendorName(); + if (!vendor.empty()) + response.Printf("vendor:%s;", vendor.c_str()); #else - // We'll send the triple. - response.PutCString("triple:"); - response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); - response.PutChar(';'); + // We'll send the triple. + response.PutCString("triple:"); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutChar(';'); #endif - std::string ostype = proc_triple.getOSName (); - // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. - if (proc_triple.getVendor () == llvm::Triple::Apple) - { - switch (proc_triple.getArch ()) - { - case llvm::Triple::arm: - case llvm::Triple::thumb: - case llvm::Triple::aarch64: - ostype = "ios"; - break; - default: - // No change. - break; - } - } - response.Printf ("ostype:%s;", ostype.c_str ()); - - - switch (proc_arch.GetByteOrder ()) - { - case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break; - case lldb::eByteOrderBig: response.PutCString ("endian:big;"); break; - case lldb::eByteOrderPDP: response.PutCString ("endian:pdp;"); break; - default: - // Nothing. - break; - } - - if (proc_triple.isArch64Bit ()) - response.PutCString ("ptrsize:8;"); - else if (proc_triple.isArch32Bit ()) - response.PutCString ("ptrsize:4;"); - else if (proc_triple.isArch16Bit ()) - response.PutCString ("ptrsize:2;"); + std::string ostype = proc_triple.getOSName(); + // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. + if (proc_triple.getVendor() == llvm::Triple::Apple) { + switch (proc_triple.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + case llvm::Triple::aarch64: + ostype = "ios"; + break; + default: + // No change. + break; + } + } + response.Printf("ostype:%s;", ostype.c_str()); + + switch (proc_arch.GetByteOrder()) { + case lldb::eByteOrderLittle: + response.PutCString("endian:little;"); + break; + case lldb::eByteOrderBig: + response.PutCString("endian:big;"); + break; + case lldb::eByteOrderPDP: + response.PutCString("endian:pdp;"); + break; + default: + // Nothing. + break; } + + if (proc_triple.isArch64Bit()) + response.PutCString("ptrsize:8;"); + else if (proc_triple.isArch32Bit()) + response.PutCString("ptrsize:4;"); + else if (proc_triple.isArch16Bit()) + response.PutCString("ptrsize:2;"); + } } -FileSpec -GDBRemoteCommunicationServerCommon::FindModuleFile(const std::string& module_path, - const ArchSpec& arch) -{ +FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( + const std::string &module_path, const ArchSpec &arch) { #ifdef __ANDROID__ - return HostInfoAndroid::ResolveLibraryPath(module_path, arch); + return HostInfoAndroid::ResolveLibraryPath(module_path, arch); #else - return FileSpec(module_path.c_str(), true); + return FileSpec(module_path.c_str(), true); #endif } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 7bb67263f3b..d6be24a0e4b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -16,8 +16,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-forward.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationServer.h" #include "GDBRemoteCommunicationServerCommon.h" @@ -29,169 +29,126 @@ namespace process_gdb_remote { class ProcessGDBRemote; -class GDBRemoteCommunicationServerCommon : - public GDBRemoteCommunicationServer -{ +class GDBRemoteCommunicationServerCommon : public GDBRemoteCommunicationServer { public: - GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name); + GDBRemoteCommunicationServerCommon(const char *comm_name, + const char *listener_name); - ~GDBRemoteCommunicationServerCommon() override; + ~GDBRemoteCommunicationServerCommon() override; protected: - ProcessLaunchInfo m_process_launch_info; - Error m_process_launch_error; - ProcessInstanceInfoList m_proc_infos; - uint32_t m_proc_infos_index; - bool m_thread_suffix_supported; - bool m_list_threads_in_stop_reply; + ProcessLaunchInfo m_process_launch_info; + Error m_process_launch_error; + ProcessInstanceInfoList m_proc_infos; + uint32_t m_proc_infos_index; + bool m_thread_suffix_supported; + bool m_list_threads_in_stop_reply; - PacketResult - Handle_A (StringExtractorGDBRemote &packet); + PacketResult Handle_A(StringExtractorGDBRemote &packet); - PacketResult - Handle_qHostInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qHostInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qProcessInfoPID (StringExtractorGDBRemote &packet); + PacketResult Handle_qProcessInfoPID(StringExtractorGDBRemote &packet); - PacketResult - Handle_qfProcessInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qfProcessInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qsProcessInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qsProcessInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qUserName (StringExtractorGDBRemote &packet); + PacketResult Handle_qUserName(StringExtractorGDBRemote &packet); - PacketResult - Handle_qGroupName (StringExtractorGDBRemote &packet); + PacketResult Handle_qGroupName(StringExtractorGDBRemote &packet); - PacketResult - Handle_qSpeedTest (StringExtractorGDBRemote &packet); + PacketResult Handle_qSpeedTest(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Open (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Open(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Close (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Close(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_pRead (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_pRead(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_pWrite (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_pWrite(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Size (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Size(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Mode (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Mode(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Exists (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Exists(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_symlink (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_symlink(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_unlink (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_unlink(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_Stat (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_Stat(StringExtractorGDBRemote &packet); - PacketResult - Handle_vFile_MD5 (StringExtractorGDBRemote &packet); + PacketResult Handle_vFile_MD5(StringExtractorGDBRemote &packet); - PacketResult - Handle_qEcho (StringExtractorGDBRemote &packet); + PacketResult Handle_qEcho(StringExtractorGDBRemote &packet); - PacketResult - Handle_qModuleInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qModuleInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qPlatform_shell (StringExtractorGDBRemote &packet); + PacketResult Handle_qPlatform_shell(StringExtractorGDBRemote &packet); - PacketResult - Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet); + PacketResult Handle_qPlatform_mkdir(StringExtractorGDBRemote &packet); - PacketResult - Handle_qPlatform_chmod (StringExtractorGDBRemote &packet); + PacketResult Handle_qPlatform_chmod(StringExtractorGDBRemote &packet); - PacketResult - Handle_qSupported (StringExtractorGDBRemote &packet); + PacketResult Handle_qSupported(StringExtractorGDBRemote &packet); - PacketResult - Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet); + PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet); - PacketResult - Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet); + PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetDetachOnError (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet); - PacketResult - Handle_QStartNoAckMode (StringExtractorGDBRemote &packet); + PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetSTDIN (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetSTDIN(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetSTDOUT (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetSTDOUT(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetSTDERR (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetSTDERR(StringExtractorGDBRemote &packet); - PacketResult - Handle_qLaunchSuccess (StringExtractorGDBRemote &packet); + PacketResult Handle_qLaunchSuccess(StringExtractorGDBRemote &packet); - PacketResult - Handle_QEnvironment (StringExtractorGDBRemote &packet); + PacketResult Handle_QEnvironment(StringExtractorGDBRemote &packet); - PacketResult - Handle_QEnvironmentHexEncoded (StringExtractorGDBRemote &packet); + PacketResult Handle_QEnvironmentHexEncoded(StringExtractorGDBRemote &packet); - PacketResult - Handle_QLaunchArch (StringExtractorGDBRemote &packet); + PacketResult Handle_QLaunchArch(StringExtractorGDBRemote &packet); - static void - CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, - StreamString &response); + static void CreateProcessInfoResponse(const ProcessInstanceInfo &proc_info, + StreamString &response); - static void - CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info, - StreamString &response); + static void CreateProcessInfoResponse_DebugServerStyle( + const ProcessInstanceInfo &proc_info, StreamString &response); - template <typename T> - void - RegisterMemberFunctionHandler (StringExtractorGDBRemote::ServerPacketType packet_type, - PacketResult (T::*handler) (StringExtractorGDBRemote& packet)) - { - RegisterPacketHandler(packet_type, - [this, handler] (StringExtractorGDBRemote packet, - Error &error, - bool &interrupt, - bool &quit) - { - return (static_cast<T*>(this)->*handler) (packet); - }); - } + template <typename T> + void RegisterMemberFunctionHandler( + StringExtractorGDBRemote::ServerPacketType packet_type, + PacketResult (T::*handler)(StringExtractorGDBRemote &packet)) { + RegisterPacketHandler(packet_type, + [this, handler](StringExtractorGDBRemote packet, + Error &error, bool &interrupt, + bool &quit) { + return (static_cast<T *>(this)->*handler)(packet); + }); + } - //------------------------------------------------------------------ - /// Launch a process with the current launch settings. - /// - /// This method supports running an lldb-gdbserver or similar - /// server in a situation where the startup code has been provided - /// with all the information for a child process to be launched. - /// - /// @return - /// An Error object indicating the success or failure of the - /// launch. - //------------------------------------------------------------------ - virtual Error - LaunchProcess () = 0; + //------------------------------------------------------------------ + /// Launch a process with the current launch settings. + /// + /// This method supports running an lldb-gdbserver or similar + /// server in a situation where the startup code has been provided + /// with all the information for a child process to be launched. + /// + /// @return + /// An Error object indicating the success or failure of the + /// launch. + //------------------------------------------------------------------ + virtual Error LaunchProcess() = 0; - virtual FileSpec - FindModuleFile (const std::string& module_path, const ArchSpec& arch); + virtual FileSpec FindModuleFile(const std::string &module_path, + const ArchSpec &arch); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 04720ace197..bc018368461 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -16,8 +16,8 @@ // C Includes // C++ Includes -#include <cstring> #include <chrono> +#include <cstring> #include <thread> // Other libraries and framework includes @@ -47,10 +47,10 @@ #include "llvm/Support/ScopedPrinter.h" // Project includes -#include "Utility/StringExtractorGDBRemote.h" -#include "Utility/UriParser.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" +#include "Utility/StringExtractorGDBRemote.h" +#include "Utility/UriParser.h" using namespace lldb; using namespace lldb_private; @@ -61,2940 +61,3107 @@ using namespace llvm; // GDBRemote Errors //---------------------------------------------------------------------- -namespace -{ - enum GDBRemoteServerError - { - // Set to the first unused error number in literal form below - eErrorFirst = 29, - eErrorNoProcess = eErrorFirst, - eErrorResume, - eErrorExitStatus - }; +namespace { +enum GDBRemoteServerError { + // Set to the first unused error number in literal form below + eErrorFirst = 29, + eErrorNoProcess = eErrorFirst, + eErrorResume, + eErrorExitStatus +}; } //---------------------------------------------------------------------- // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(MainLoop &mainloop) - : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), - m_current_tid(LLDB_INVALID_THREAD_ID), - m_continue_tid(LLDB_INVALID_THREAD_ID), - m_debugged_process_mutex(), - m_debugged_process_sp(), - m_stdio_communication("process.stdio"), +GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( + MainLoop &mainloop) + : GDBRemoteCommunicationServerCommon("gdb-remote.server", + "gdb-remote.server.rx_packet"), + m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID), + m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(), + m_debugged_process_sp(), m_stdio_communication("process.stdio"), m_inferior_prev_state(StateType::eStateInvalid), - m_active_auxv_buffer_sp(), - m_saved_registers_mutex(), - m_saved_registers_map(), - m_next_saved_registers_id(1), - m_handshake_completed(false) -{ - RegisterPacketHandlers(); -} - -void -GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() -{ - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, - &GDBRemoteCommunicationServerLLGS::Handle_C); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, - &GDBRemoteCommunicationServerLLGS::Handle_c); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, - &GDBRemoteCommunicationServerLLGS::Handle_D); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, - &GDBRemoteCommunicationServerLLGS::Handle_H); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, - &GDBRemoteCommunicationServerLLGS::Handle_I); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, - &GDBRemoteCommunicationServerLLGS::Handle_interrupt); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m, - &GDBRemoteCommunicationServerLLGS::Handle_memory_read); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, - &GDBRemoteCommunicationServerLLGS::Handle_M); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, - &GDBRemoteCommunicationServerLLGS::Handle_p); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, - &GDBRemoteCommunicationServerLLGS::Handle_P); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, - &GDBRemoteCommunicationServerLLGS::Handle_qC); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, - &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, - &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, - &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, - &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, - &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, - &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, - &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, - &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, - &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, - &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, - &GDBRemoteCommunicationServerLLGS::Handle_s); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_stop_reason, - &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vAttach, - &GDBRemoteCommunicationServerLLGS::Handle_vAttach); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont, - &GDBRemoteCommunicationServerLLGS::Handle_vCont); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions, - &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x, - &GDBRemoteCommunicationServerLLGS::Handle_memory_read); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, - &GDBRemoteCommunicationServerLLGS::Handle_Z); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, - &GDBRemoteCommunicationServerLLGS::Handle_z); - - RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, - [this](StringExtractorGDBRemote packet, - Error &error, - bool &interrupt, - bool &quit) - { - quit = true; - return this->Handle_k (packet); - }); -} - -Error -GDBRemoteCommunicationServerLLGS::SetLaunchArguments (const char *const args[], int argc) -{ - if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Error ("%s: no process command line specified to launch", __FUNCTION__); - - m_process_launch_info.SetArguments (const_cast<const char**> (args), true); - return Error (); -} - -Error -GDBRemoteCommunicationServerLLGS::SetLaunchFlags (unsigned int launch_flags) -{ - m_process_launch_info.GetFlags ().Set (launch_flags); - return Error (); -} - -Error -GDBRemoteCommunicationServerLLGS::LaunchProcess () -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - if (!m_process_launch_info.GetArguments ().GetArgumentCount ()) - return Error ("%s: no process command line specified to launch", __FUNCTION__); - - const bool should_forward_stdio = m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || - m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || - m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr; - m_process_launch_info.SetLaunchInSeparateProcessGroup(true); - m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); - - const bool default_to_use_pty = true; - m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); - - Error error; - { - std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); - assert (!m_debugged_process_sp && "lldb-server creating debugged " - "process but one already exists"); - error = NativeProcessProtocol::Launch( - m_process_launch_info, - *this, - m_mainloop, - m_debugged_process_sp); - } - - if (!error.Success ()) - { - fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); - return error; - } - - // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol - // as needed. - // llgs local-process debugging may specify PTY paths, which will make these - // file actions non-null - // process launch -i/e/o will also make these file actions non-null - // nullptr means that the traffic is expected to flow over gdb-remote protocol - if (should_forward_stdio) - { - // nullptr means it's not redirected to file or pty (in case of LLGS local) - // at least one of stdio will be transferred pty<->gdb-remote - // we need to give the pty master handle to this object to read and/or write - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID ()); - - // Setup stdout/stderr mapping from inferior to $O - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); - if (terminal_fd >= 0) - { - if (log) - log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor (terminal_fd); - if (error.Fail ()) - return error; - } - else - { - if (log) - log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); - } - } - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID ()); - } - - printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ()); - + m_active_auxv_buffer_sp(), m_saved_registers_mutex(), + m_saved_registers_map(), m_next_saved_registers_id(1), + m_handshake_completed(false) { + RegisterPacketHandlers(); +} + +void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, + &GDBRemoteCommunicationServerLLGS::Handle_C); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, + &GDBRemoteCommunicationServerLLGS::Handle_c); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, + &GDBRemoteCommunicationServerLLGS::Handle_D); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, + &GDBRemoteCommunicationServerLLGS::Handle_H); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, + &GDBRemoteCommunicationServerLLGS::Handle_I); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_interrupt, + &GDBRemoteCommunicationServerLLGS::Handle_interrupt); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_m, + &GDBRemoteCommunicationServerLLGS::Handle_memory_read); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, + &GDBRemoteCommunicationServerLLGS::Handle_M); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, + &GDBRemoteCommunicationServerLLGS::Handle_p); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, + &GDBRemoteCommunicationServerLLGS::Handle_P); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, + &GDBRemoteCommunicationServerLLGS::Handle_qC); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, + &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, + &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, + &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qProcessInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, + &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, + &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, + &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, + &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, + &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, + &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, + &GDBRemoteCommunicationServerLLGS::Handle_s); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_stop_reason, + &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vAttach, + &GDBRemoteCommunicationServerLLGS::Handle_vAttach); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vCont, + &GDBRemoteCommunicationServerLLGS::Handle_vCont); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vCont_actions, + &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_x, + &GDBRemoteCommunicationServerLLGS::Handle_memory_read); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, + &GDBRemoteCommunicationServerLLGS::Handle_Z); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, + &GDBRemoteCommunicationServerLLGS::Handle_z); + + RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, + [this](StringExtractorGDBRemote packet, Error &error, + bool &interrupt, bool &quit) { + quit = true; + return this->Handle_k(packet); + }); +} + +Error GDBRemoteCommunicationServerLLGS::SetLaunchArguments( + const char *const args[], int argc) { + if ((argc < 1) || !args || !args[0] || !args[0][0]) + return Error("%s: no process command line specified to launch", + __FUNCTION__); + + m_process_launch_info.SetArguments(const_cast<const char **>(args), true); + return Error(); +} + +Error GDBRemoteCommunicationServerLLGS::SetLaunchFlags( + unsigned int launch_flags) { + m_process_launch_info.GetFlags().Set(launch_flags); + return Error(); +} + +Error GDBRemoteCommunicationServerLLGS::LaunchProcess() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + if (!m_process_launch_info.GetArguments().GetArgumentCount()) + return Error("%s: no process command line specified to launch", + __FUNCTION__); + + const bool should_forward_stdio = + m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || + m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || + m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr; + m_process_launch_info.SetLaunchInSeparateProcessGroup(true); + m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); + + const bool default_to_use_pty = true; + m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); + + Error error; + { + std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); + assert(!m_debugged_process_sp && "lldb-server creating debugged " + "process but one already exists"); + error = NativeProcessProtocol::Launch(m_process_launch_info, *this, + m_mainloop, m_debugged_process_sp); + } + + if (!error.Success()) { + fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, + m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); return error; -} - -Error -GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid) -{ - Error error; - - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); + } + + // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol + // as needed. + // llgs local-process debugging may specify PTY paths, which will make these + // file actions non-null + // process launch -i/e/o will also make these file actions non-null + // nullptr means that the traffic is expected to flow over gdb-remote protocol + if (should_forward_stdio) { + // nullptr means it's not redirected to file or pty (in case of LLGS local) + // at least one of stdio will be transferred pty<->gdb-remote + // we need to give the pty master handle to this object to read and/or write if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid); - - // Before we try to attach, make sure we aren't already monitoring something else. - if (m_debugged_process_sp && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) - return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID()); - - // Try to attach. - error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp); - if (!error.Success ()) - { - fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ()); + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " setting up stdout/stderr redirection via $O gdb-remote commands", + __FUNCTION__, m_debugged_process_sp->GetID()); + + // Setup stdout/stderr mapping from inferior to $O + auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); + if (terminal_fd >= 0) { + if (log) + log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); + error = SetSTDIOFileDescriptor(terminal_fd); + if (error.Fail()) return error; + } else { + if (log) + log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); } - - // Setup stdout/stderr mapping from inferior. - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); - if (terminal_fd >= 0) - { - if (log) - log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor (terminal_fd); - if (error.Fail ()) - return error; - } - else - { - if (log) - log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); - } - - printf ("Attached to process %" PRIu64 "...\n", pid); - + } else { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " skipping stdout/stderr redirection via $O: inferior will " + "communicate over client-provided file descriptors", + __FUNCTION__, m_debugged_process_sp->GetID()); + } + + printf("Launched '%s' as process %" PRIu64 "...\n", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), + m_process_launch_info.GetProcessID()); + + return error; +} + +Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { + Error error; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, + __FUNCTION__, pid); + + // Before we try to attach, make sure we aren't already monitoring something + // else. + if (m_debugged_process_sp && + m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) + return Error("cannot attach to a process %" PRIu64 + " when another process with pid %" PRIu64 + " is being debugged.", + pid, m_debugged_process_sp->GetID()); + + // Try to attach. + error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, + m_debugged_process_sp); + if (!error.Success()) { + fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s", + __FUNCTION__, pid, error.AsCString()); return error; -} + } -void -GDBRemoteCommunicationServerLLGS::InitializeDelegate (NativeProcessProtocol *process) -{ - assert (process && "process cannot be NULL"); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Setup stdout/stderr mapping from inferior. + auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); + if (terminal_fd >= 0) { if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called with NativeProcessProtocol pid %" PRIu64 ", current state: %s", - __FUNCTION__, - process->GetID (), - StateAsCString (process->GetState ())); - } -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendWResponse (NativeProcessProtocol *process) -{ - assert (process && "process cannot be NULL"); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // send W notification - ExitType exit_type = ExitType::eExitTypeInvalid; - int return_code = 0; - std::string exit_description; - - const bool got_exit_info = process->GetExitStatus (&exit_type, &return_code, exit_description); - if (!got_exit_info) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", failed to retrieve process exit status", __FUNCTION__, process->GetID ()); - - StreamGDBRemote response; - response.PutChar ('E'); - response.PutHex8 (GDBRemoteServerError::eErrorExitStatus); - return SendPacketNoLock(response.GetString()); - } - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", returning exit type %d, return code %d [%s]", __FUNCTION__, process->GetID (), exit_type, return_code, exit_description.c_str ()); - - StreamGDBRemote response; - - char return_type_code; - switch (exit_type) - { - case ExitType::eExitTypeExit: - return_type_code = 'W'; - break; - case ExitType::eExitTypeSignal: - return_type_code = 'X'; - break; - case ExitType::eExitTypeStop: - return_type_code = 'S'; - break; - case ExitType::eExitTypeInvalid: - return_type_code = 'E'; - break; - } - response.PutChar (return_type_code); + log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); + error = SetSTDIOFileDescriptor(terminal_fd); + if (error.Fail()) + return error; + } else { + if (log) + log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); + } - // POSIX exit status limited to unsigned 8 bits. - response.PutHex8 (return_code); + printf("Attached to process %" PRIu64 "...\n", pid); - return SendPacketNoLock(response.GetString()); - } + return error; } -static void -AppendHexValue (StreamString &response, const uint8_t* buf, uint32_t buf_size, bool swap) -{ - int64_t i; - if (swap) - { - for (i = buf_size-1; i >= 0; i--) - response.PutHex8 (buf[i]); - } - else - { - for (i = 0; i < buf_size; i++) - response.PutHex8 (buf[i]); - } +void GDBRemoteCommunicationServerLLGS::InitializeDelegate( + NativeProcessProtocol *process) { + assert(process && "process cannot be NULL"); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", current state: %s", + __FUNCTION__, process->GetID(), + StateAsCString(process->GetState())); + } } -static void -WriteRegisterValueInHexFixedWidth (StreamString &response, - NativeRegisterContextSP ®_ctx_sp, - const RegisterInfo ®_info, - const RegisterValue *reg_value_p) -{ - RegisterValue reg_value; - if (!reg_value_p) - { - Error error = reg_ctx_sp->ReadRegister (®_info, reg_value); - if (error.Success ()) - reg_value_p = ®_value; - // else log. - } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::SendWResponse( + NativeProcessProtocol *process) { + assert(process && "process cannot be NULL"); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // send W notification + ExitType exit_type = ExitType::eExitTypeInvalid; + int return_code = 0; + std::string exit_description; + + const bool got_exit_info = + process->GetExitStatus(&exit_type, &return_code, exit_description); + if (!got_exit_info) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + ", failed to retrieve process exit status", + __FUNCTION__, process->GetID()); - if (reg_value_p) - { - AppendHexValue (response, (const uint8_t*) reg_value_p->GetBytes (), reg_value_p->GetByteSize (), false); - } - else - { - // Zero-out any unreadable values. - if (reg_info.byte_size > 0) - { - std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0'); - AppendHexValue (response, zeros.data(), zeros.size(), false); - } - } -} + StreamGDBRemote response; + response.PutChar('E'); + response.PutHex8(GDBRemoteServerError::eErrorExitStatus); + return SendPacketNoLock(response.GetString()); + } else { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + ", returning exit type %d, return code %d [%s]", + __FUNCTION__, process->GetID(), exit_type, return_code, + exit_description.c_str()); -static JSONObject::SP -GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD)); + StreamGDBRemote response; - NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext (); - if (! reg_ctx_sp) - return nullptr; + char return_type_code; + switch (exit_type) { + case ExitType::eExitTypeExit: + return_type_code = 'W'; + break; + case ExitType::eExitTypeSignal: + return_type_code = 'X'; + break; + case ExitType::eExitTypeStop: + return_type_code = 'S'; + break; + case ExitType::eExitTypeInvalid: + return_type_code = 'E'; + break; + } + response.PutChar(return_type_code); + + // POSIX exit status limited to unsigned 8 bits. + response.PutHex8(return_code); - JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); + return SendPacketNoLock(response.GetString()); + } +} + +static void AppendHexValue(StreamString &response, const uint8_t *buf, + uint32_t buf_size, bool swap) { + int64_t i; + if (swap) { + for (i = buf_size - 1; i >= 0; i--) + response.PutHex8(buf[i]); + } else { + for (i = 0; i < buf_size; i++) + response.PutHex8(buf[i]); + } +} + +static void WriteRegisterValueInHexFixedWidth( + StreamString &response, NativeRegisterContextSP ®_ctx_sp, + const RegisterInfo ®_info, const RegisterValue *reg_value_p) { + RegisterValue reg_value; + if (!reg_value_p) { + Error error = reg_ctx_sp->ReadRegister(®_info, reg_value); + if (error.Success()) + reg_value_p = ®_value; + // else log. + } + + if (reg_value_p) { + AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(), + reg_value_p->GetByteSize(), false); + } else { + // Zero-out any unreadable values. + if (reg_info.byte_size > 0) { + std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0'); + AppendHexValue(response, zeros.data(), zeros.size(), false); + } + } +} + +static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread, + bool abridged) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); + if (!reg_ctx_sp) + return nullptr; + + JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET - // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers. - const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); - if (! reg_set_p) - return nullptr; - for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) - { - uint32_t reg_num = *reg_num_p; + // Expedite all registers in the first register set (i.e. should be GPRs) that + // are not contained in other registers. + const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); + if (!reg_set_p) + return nullptr; + for (const uint32_t *reg_num_p = reg_set_p->registers; + *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { + uint32_t reg_num = *reg_num_p; #else - // Expedite only a couple of registers until we figure out why sending registers is - // expensive. - static const uint32_t k_expedited_registers[] = { - LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM - }; - static const uint32_t k_abridged_expedited_registers[] = { - LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM - }; - - for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers; - *generic_reg_p != LLDB_INVALID_REGNUM; - ++generic_reg_p) - { - uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p); - if (reg_num == LLDB_INVALID_REGNUM) - continue; // Target does not support the given register. + // Expedite only a couple of registers until we figure out why sending + // registers is + // expensive. + static const uint32_t k_expedited_registers[] = { + LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, + LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM}; + static const uint32_t k_abridged_expedited_registers[] = { + LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM}; + + for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers + : k_expedited_registers; + *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { + uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, *generic_reg_p); + if (reg_num == LLDB_INVALID_REGNUM) + continue; // Target does not support the given register. #endif - const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); - if (reg_info_p == nullptr) - { - if (log) - log->Printf("%s failed to get register info for register index %" PRIu32, - __FUNCTION__, reg_num); - continue; - } - - if (reg_info_p->value_regs != nullptr) - continue; // Only expedite registers that are not contained in other registers. - - RegisterValue reg_value; - Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); - if (error.Fail()) - { - if (log) - log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, - reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num, - error.AsCString ()); - continue; - } - - StreamString stream; - WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, ®_value); - - register_object_sp->SetObject(llvm::to_string(reg_num), std::make_shared<JSONString>(stream.GetString())); - } - - return register_object_sp; -} - -static const char * -GetStopReasonString(StopReason stop_reason) -{ - switch (stop_reason) - { - case eStopReasonTrace: - return "trace"; - case eStopReasonBreakpoint: - return "breakpoint"; - case eStopReasonWatchpoint: - return "watchpoint"; - case eStopReasonSignal: - return "signal"; - case eStopReasonException: - return "exception"; - case eStopReasonExec: - return "exec"; - case eStopReasonInstrumentation: - case eStopReasonInvalid: - case eStopReasonPlanComplete: - case eStopReasonThreadExiting: - case eStopReasonNone: - break; // ignored + const RegisterInfo *const reg_info_p = + reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); + if (reg_info_p == nullptr) { + if (log) + log->Printf( + "%s failed to get register info for register index %" PRIu32, + __FUNCTION__, reg_num); + continue; } - return nullptr; -} - -static JSONArray::SP -GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - - JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); - - // Ensure we can get info on the given thread. - uint32_t thread_idx = 0; - for ( NativeThreadProtocolSP thread_sp; - (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; - ++thread_idx) - { - lldb::tid_t tid = thread_sp->GetID(); + if (reg_info_p->value_regs != nullptr) + continue; // Only expedite registers that are not contained in other + // registers. - // Grab the reason this thread stopped. - struct ThreadStopInfo tid_stop_info; - std::string description; - if (!thread_sp->GetStopReason (tid_stop_info, description)) - return nullptr; - - const int signum = tid_stop_info.details.signal.signo; - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + RegisterValue reg_value; + Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + if (error.Fail()) { + if (log) + log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, - process.GetID (), - tid, - signum, - tid_stop_info.reason, - tid_stop_info.details.exception.type); - } - - JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); - threads_array_sp->AppendObject(thread_obj_sp); - - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged)) - thread_obj_sp->SetObject("registers", registers_sp); - - thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); - if (signum != 0) - thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); - - const std::string thread_name = thread_sp->GetName (); - if (! thread_name.empty()) - thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); - - if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) - thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str)); - - if (! description.empty()) - thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description)); + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + reg_num, error.AsCString()); + continue; + } + + StreamString stream; + WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, + ®_value); + + register_object_sp->SetObject( + llvm::to_string(reg_num), + std::make_shared<JSONString>(stream.GetString())); + } + + return register_object_sp; +} + +static const char *GetStopReasonString(StopReason stop_reason) { + switch (stop_reason) { + case eStopReasonTrace: + return "trace"; + case eStopReasonBreakpoint: + return "breakpoint"; + case eStopReasonWatchpoint: + return "watchpoint"; + case eStopReasonSignal: + return "signal"; + case eStopReasonException: + return "exception"; + case eStopReasonExec: + return "exec"; + case eStopReasonInstrumentation: + case eStopReasonInvalid: + case eStopReasonPlanComplete: + case eStopReasonThreadExiting: + case eStopReasonNone: + break; // ignored + } + return nullptr; +} + +static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, + bool abridged) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + + JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + + // Ensure we can get info on the given thread. + uint32_t thread_idx = 0; + for (NativeThreadProtocolSP thread_sp; + (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; + ++thread_idx) { + + lldb::tid_t tid = thread_sp->GetID(); - if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) - { - thread_obj_sp->SetObject("metype", - std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); - - JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); - for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) - { - medata_array_sp->AppendObject(std::make_shared<JSONNumber>( - tid_stop_info.details.exception.data[i])); - } - thread_obj_sp->SetObject("medata", medata_array_sp); - } + // Grab the reason this thread stopped. + struct ThreadStopInfo tid_stop_info; + std::string description; + if (!thread_sp->GetStopReason(tid_stop_info, description)) + return nullptr; - // TODO: Expedite interesting regions of inferior memory + const int signum = tid_stop_info.details.signal.signo; + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 + " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + __FUNCTION__, process.GetID(), tid, signum, + tid_stop_info.reason, tid_stop_info.details.exception.type); } - return threads_array_sp; -} + JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); + threads_array_sp->AppendObject(thread_obj_sp); -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged)) + thread_obj_sp->SetObject("registers", registers_sp); - // Ensure we have a debugged process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (50); + thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); + if (signum != 0) + thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64 " tid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID (), tid); + const std::string thread_name = thread_sp->GetName(); + if (!thread_name.empty()) + thread_obj_sp->SetObject("name", + std::make_shared<JSONString>(thread_name)); - // Ensure we can get info on the given thread. - NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid)); - if (!thread_sp) - return SendErrorResponse (51); + if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) + thread_obj_sp->SetObject("reason", + std::make_shared<JSONString>(stop_reason_str)); - // Grab the reason this thread stopped. - struct ThreadStopInfo tid_stop_info; - std::string description; - if (!thread_sp->GetStopReason (tid_stop_info, description)) - return SendErrorResponse (52); + if (!description.empty()) + thread_obj_sp->SetObject("description", + std::make_shared<JSONString>(description)); - // FIXME implement register handling for exec'd inferiors. - // if (tid_stop_info.reason == eStopReasonExec) - // { - // const bool force = true; - // InitializeRegisters(force); - // } + if ((tid_stop_info.reason == eStopReasonException) && + tid_stop_info.details.exception.type) { + thread_obj_sp->SetObject( + "metype", + std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); - StreamString response; - // Output the T packet with the thread - response.PutChar ('T'); - int signum = tid_stop_info.details.signal.signo; - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, - __FUNCTION__, - m_debugged_process_sp->GetID (), - tid, - signum, - tid_stop_info.reason, - tid_stop_info.details.exception.type); + JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); + for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; + ++i) { + medata_array_sp->AppendObject(std::make_shared<JSONNumber>( + tid_stop_info.details.exception.data[i])); + } + thread_obj_sp->SetObject("medata", medata_array_sp); } - // Print the signal number. - response.PutHex8 (signum & 0xff); - - // Include the tid. - response.Printf ("thread:%" PRIx64 ";", tid); - - // Include the thread name if there is one. - const std::string thread_name = thread_sp->GetName (); - if (!thread_name.empty ()) - { - size_t thread_name_len = thread_name.length (); - - if (::strcspn (thread_name.c_str (), "$#+-;:") == thread_name_len) - { - response.PutCString ("name:"); - response.PutCString (thread_name.c_str ()); - } - else - { - // The thread name contains special chars, send as hex bytes. - response.PutCString ("hexname:"); - response.PutCStringAsRawHex8 (thread_name.c_str ()); - } - response.PutChar (';'); - } + // TODO: Expedite interesting regions of inferior memory + } - // If a 'QListThreadsInStopReply' was sent to enable this feature, we - // will send all thread IDs back in the "threads" key whose value is - // a list of hex thread IDs separated by commas: - // "threads:10a,10b,10c;" - // This will save the debugger from having to send a pair of qfThreadInfo - // and qsThreadInfo packets, but it also might take a lot of room in the - // stop reply packet, so it must be enabled only on systems where there - // are no limits on packet lengths. - if (m_list_threads_in_stop_reply) - { - response.PutCString ("threads:"); - - uint32_t thread_index = 0; - NativeThreadProtocolSP listed_thread_sp; - for (listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index); listed_thread_sp; ++thread_index, listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index)) - { - if (thread_index > 0) - response.PutChar (','); - response.Printf ("%" PRIx64, listed_thread_sp->GetID ()); - } - response.PutChar (';'); - - // Include JSON info that describes the stop reason for any threads - // that actually have stop reasons. We use the new "jstopinfo" key - // whose values is hex ascii JSON that contains the thread IDs - // thread stop info only for threads that have stop reasons. Only send - // this if we have more than one thread otherwise this packet has all - // the info it needs. - if (thread_index > 0) - { - const bool threads_with_valid_stop_info_only = true; - JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp, - threads_with_valid_stop_info_only); - if (threads_info_sp) - { - response.PutCString("jstopinfo:"); - StreamString unescaped_response; - threads_info_sp->Write(unescaped_response); - response.PutCStringAsRawHex8(unescaped_response.GetData()); - response.PutChar(';'); - } - else if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); + return threads_array_sp; +} - } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( + lldb::tid_t tid) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + + // Ensure we have a debugged process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(50); + + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64 + " tid %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID(), tid); + + // Ensure we can get info on the given thread. + NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); + if (!thread_sp) + return SendErrorResponse(51); + + // Grab the reason this thread stopped. + struct ThreadStopInfo tid_stop_info; + std::string description; + if (!thread_sp->GetStopReason(tid_stop_info, description)) + return SendErrorResponse(52); + + // FIXME implement register handling for exec'd inferiors. + // if (tid_stop_info.reason == eStopReasonExec) + // { + // const bool force = true; + // InitializeRegisters(force); + // } + + StreamString response; + // Output the T packet with the thread + response.PutChar('T'); + int signum = tid_stop_info.details.signal.signo; + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 + " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID(), tid, signum, + tid_stop_info.reason, tid_stop_info.details.exception.type); + } + + // Print the signal number. + response.PutHex8(signum & 0xff); + + // Include the tid. + response.Printf("thread:%" PRIx64 ";", tid); + + // Include the thread name if there is one. + const std::string thread_name = thread_sp->GetName(); + if (!thread_name.empty()) { + size_t thread_name_len = thread_name.length(); + + if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) { + response.PutCString("name:"); + response.PutCString(thread_name.c_str()); + } else { + // The thread name contains special chars, send as hex bytes. + response.PutCString("hexname:"); + response.PutCStringAsRawHex8(thread_name.c_str()); + } + response.PutChar(';'); + } + + // If a 'QListThreadsInStopReply' was sent to enable this feature, we + // will send all thread IDs back in the "threads" key whose value is + // a list of hex thread IDs separated by commas: + // "threads:10a,10b,10c;" + // This will save the debugger from having to send a pair of qfThreadInfo + // and qsThreadInfo packets, but it also might take a lot of room in the + // stop reply packet, so it must be enabled only on systems where there + // are no limits on packet lengths. + if (m_list_threads_in_stop_reply) { + response.PutCString("threads:"); + + uint32_t thread_index = 0; + NativeThreadProtocolSP listed_thread_sp; + for (listed_thread_sp = + m_debugged_process_sp->GetThreadAtIndex(thread_index); + listed_thread_sp; ++thread_index, + listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex( + thread_index)) { + if (thread_index > 0) + response.PutChar(','); + response.Printf("%" PRIx64, listed_thread_sp->GetID()); + } + response.PutChar(';'); + + // Include JSON info that describes the stop reason for any threads + // that actually have stop reasons. We use the new "jstopinfo" key + // whose values is hex ascii JSON that contains the thread IDs + // thread stop info only for threads that have stop reasons. Only send + // this if we have more than one thread otherwise this packet has all + // the info it needs. + if (thread_index > 0) { + const bool threads_with_valid_stop_info_only = true; + JSONArray::SP threads_info_sp = GetJSONThreadsInfo( + *m_debugged_process_sp, threads_with_valid_stop_info_only); + if (threads_info_sp) { + response.PutCString("jstopinfo:"); + StreamString unescaped_response; + threads_info_sp->Write(unescaped_response); + response.PutCStringAsRawHex8(unescaped_response.GetData()); + response.PutChar(';'); + } else if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " + "jstopinfo field for pid %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); } - - // - // Expedite registers. - // - - // Grab the register context. - NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext (); - if (reg_ctx_sp) - { - // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers. - const RegisterSet *reg_set_p; - if (reg_ctx_sp->GetRegisterSetCount () > 0 && ((reg_set_p = reg_ctx_sp->GetRegisterSet (0)) != nullptr)) - { + } + + // + // Expedite registers. + // + + // Grab the register context. + NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (reg_ctx_sp) { + // Expedite all registers in the first register set (i.e. should be GPRs) + // that are not contained in other registers. + const RegisterSet *reg_set_p; + if (reg_ctx_sp->GetRegisterSetCount() > 0 && + ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " + "from set '%s' (registers set count: %zu)", + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + reg_set_p->num_registers); + + for (const uint32_t *reg_num_p = reg_set_p->registers; + *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { + const RegisterInfo *const reg_info_p = + reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p); + if (reg_info_p == nullptr) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " + "register info for register set '%s', register index " + "%" PRIu32, + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + *reg_num_p); + } else if (reg_info_p->value_regs == nullptr) { + // Only expediate registers that are not contained in other registers. + RegisterValue reg_value; + Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + if (error.Success()) { + response.Printf("%.02x:", *reg_num_p); + WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, + ®_value); + response.PutChar(';'); + } else { if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s expediting registers from set '%s' (registers set count: %zu)", __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", reg_set_p->num_registers); - - for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) - { - const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex (*reg_num_p); - if (reg_info_p == nullptr) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to get register info for register set '%s', register index %" PRIu32, __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", *reg_num_p); - } - else if (reg_info_p->value_regs == nullptr) - { - // Only expediate registers that are not contained in other registers. - RegisterValue reg_value; - Error error = reg_ctx_sp->ReadRegister (reg_info_p, reg_value); - if (error.Success ()) - { - response.Printf ("%.02x:", *reg_num_p); - WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, ®_value); - response.PutChar (';'); - } - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "<unnamed-register>", *reg_num_p, error.AsCString ()); - - } - } - } + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " + "register '%s' index %" PRIu32 ": %s", + __FUNCTION__, reg_info_p->name ? reg_info_p->name + : "<unnamed-register>", + *reg_num_p, error.AsCString()); + } } + } } + } - const char* reason_str = GetStopReasonString(tid_stop_info.reason); - if (reason_str != nullptr) - { - response.Printf ("reason:%s;", reason_str); - } + const char *reason_str = GetStopReasonString(tid_stop_info.reason); + if (reason_str != nullptr) { + response.Printf("reason:%s;", reason_str); + } - if (!description.empty()) - { - // Description may contains special chars, send as hex bytes. - response.PutCString ("description:"); - response.PutCStringAsRawHex8 (description.c_str ()); - response.PutChar (';'); - } - else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) - { - response.PutCString ("metype:"); - response.PutHex64 (tid_stop_info.details.exception.type); - response.PutCString (";mecount:"); - response.PutHex32 (tid_stop_info.details.exception.data_count); - response.PutChar (';'); - - for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) - { - response.PutCString ("medata:"); - response.PutHex64 (tid_stop_info.details.exception.data[i]); - response.PutChar (';'); - } + if (!description.empty()) { + // Description may contains special chars, send as hex bytes. + response.PutCString("description:"); + response.PutCStringAsRawHex8(description.c_str()); + response.PutChar(';'); + } else if ((tid_stop_info.reason == eStopReasonException) && + tid_stop_info.details.exception.type) { + response.PutCString("metype:"); + response.PutHex64(tid_stop_info.details.exception.type); + response.PutCString(";mecount:"); + response.PutHex32(tid_stop_info.details.exception.data_count); + response.PutChar(';'); + + for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { + response.PutCString("medata:"); + response.PutHex64(tid_stop_info.details.exception.data[i]); + response.PutChar(';'); } + } - return SendPacketNoLock (response.GetString()); + return SendPacketNoLock(response.GetString()); } -void -GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProtocol *process) -{ - assert (process && "process cannot be NULL"); - - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); +void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( + NativeProcessProtocol *process) { + assert(process && "process cannot be NULL"); - PacketResult result = SendStopReasonForState(StateType::eStateExited); - if (result != PacketResult::Success) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ()); - } - - // Close the pipe to the inferior terminal i/o if we launched it - // and set one up. - MaybeCloseInferiorTerminalConnection (); - - // We are ready to exit the debug monitor. - m_exit_now = true; -} - -void -GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProtocol *process) -{ - assert (process && "process cannot be NULL"); - - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - - // Send the stop reason unless this is the stop after the - // launch or attach. - switch (m_inferior_prev_state) - { - case eStateLaunching: - case eStateAttaching: - // Don't send anything per debugserver behavior. - break; - default: - // In all other cases, send the stop reason. - PacketResult result = SendStopReasonForState(StateType::eStateStopped); - if (result != PacketResult::Success) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ()); - } - break; - } -} + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); -void -GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) -{ - assert (process && "process cannot be NULL"); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + PacketResult result = SendStopReasonForState(StateType::eStateExited); + if (result != PacketResult::Success) { if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called with NativeProcessProtocol pid %" PRIu64 ", state: %s", - __FUNCTION__, - process->GetID (), - StateAsCString (state)); - } + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); + } + + // Close the pipe to the inferior terminal i/o if we launched it + // and set one up. + MaybeCloseInferiorTerminalConnection(); + + // We are ready to exit the debug monitor. + m_exit_now = true; +} + +void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( + NativeProcessProtocol *process) { + assert(process && "process cannot be NULL"); + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + + // Send the stop reason unless this is the stop after the + // launch or attach. + switch (m_inferior_prev_state) { + case eStateLaunching: + case eStateAttaching: + // Don't send anything per debugserver behavior. + break; + default: + // In all other cases, send the stop reason. + PacketResult result = SendStopReasonForState(StateType::eStateStopped); + if (result != PacketResult::Success) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); + } + break; + } +} + +void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( + NativeProcessProtocol *process, lldb::StateType state) { + assert(process && "process cannot be NULL"); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); + } + + switch (state) { + case StateType::eStateRunning: + StartSTDIOForwarding(); + break; + + case StateType::eStateStopped: + // Make sure we get all of the pending stdout/stderr from the inferior + // and send it to the lldb host before we send the state change + // notification + SendProcessOutput(); + // Then stop the forwarding, so that any late output (see llvm.org/pr25652) + // does not + // interfere with our protocol. + StopSTDIOForwarding(); + HandleInferiorState_Stopped(process); + break; - switch (state) - { - case StateType::eStateRunning: - StartSTDIOForwarding(); - break; - - case StateType::eStateStopped: - // Make sure we get all of the pending stdout/stderr from the inferior - // and send it to the lldb host before we send the state change - // notification - SendProcessOutput(); - // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not - // interfere with our protocol. - StopSTDIOForwarding(); - HandleInferiorState_Stopped (process); - break; - - case StateType::eStateExited: - // Same as above - SendProcessOutput(); - StopSTDIOForwarding(); - HandleInferiorState_Exited (process); - break; + case StateType::eStateExited: + // Same as above + SendProcessOutput(); + StopSTDIOForwarding(); + HandleInferiorState_Exited(process); + break; - default: - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s didn't handle state change for pid %" PRIu64 ", new state: %s", - __FUNCTION__, - process->GetID (), - StateAsCString (state)); - } - break; + default: + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state " + "change for pid %" PRIu64 ", new state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); } + break; + } - // Remember the previous state reported to us. - m_inferior_prev_state = state; + // Remember the previous state reported to us. + m_inferior_prev_state = state; } -void -GDBRemoteCommunicationServerLLGS::DidExec (NativeProcessProtocol *process) -{ - ClearProcessSpecificData (); +void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { + ClearProcessSpecificData(); } -void -GDBRemoteCommunicationServerLLGS::DataAvailableCallback () -{ - Log *log (GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); +void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { + Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); - if (! m_handshake_completed) - { - if (! HandshakeWithClient()) - { - if(log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting", - __FUNCTION__); - m_mainloop.RequestTermination(); - return; - } - m_handshake_completed = true; + if (!m_handshake_completed) { + if (!HandshakeWithClient()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with " + "client failed, exiting", + __FUNCTION__); + m_mainloop.RequestTermination(); + return; } + m_handshake_completed = true; + } - bool interrupt = false; - bool done = false; - Error error; - while (true) - { - const PacketResult result = GetPacketAndSendResponse (0, error, interrupt, done); - if (result == PacketResult::ErrorReplyTimeout) - break; // No more packets in the queue - - if ((result != PacketResult::Success)) - { - if(log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s", - __FUNCTION__, error.AsCString()); - m_mainloop.RequestTermination(); - break; - } + bool interrupt = false; + bool done = false; + Error error; + while (true) { + const PacketResult result = + GetPacketAndSendResponse(0, error, interrupt, done); + if (result == PacketResult::ErrorReplyTimeout) + break; // No more packets in the queue + + if ((result != PacketResult::Success)) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet " + "failed: %s", + __FUNCTION__, error.AsCString()); + m_mainloop.RequestTermination(); + break; } + } } -Error -GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connection> &&connection) -{ - IOObjectSP read_object_sp = connection->GetReadObject(); - GDBRemoteCommunicationServer::SetConnection(connection.release()); +Error GDBRemoteCommunicationServerLLGS::InitializeConnection( + std::unique_ptr<Connection> &&connection) { + IOObjectSP read_object_sp = connection->GetReadObject(); + GDBRemoteCommunicationServer::SetConnection(connection.release()); - Error error; - m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp, - [this] (MainLoopBase &) { DataAvailableCallback(); }, error); - return error; + Error error; + m_network_handle_up = m_mainloop.RegisterReadObject( + read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); }, + error); + return error; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendONotification (const char *buffer, uint32_t len) -{ - if ((buffer == nullptr) || (len == 0)) - { - // Nothing to send. - return PacketResult::Success; - } - - StreamString response; - response.PutChar ('O'); - response.PutBytesAsRawHex8 (buffer, len); - - return SendPacketNoLock (response.GetString()); -} - -Error -GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd) -{ - Error error; - - // Set up the reading/handling of process I/O - std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true)); - if (!conn_up) - { - error.SetErrorString ("failed to create ConnectionFileDescriptor"); - return error; - } +GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, + uint32_t len) { + if ((buffer == nullptr) || (len == 0)) { + // Nothing to send. + return PacketResult::Success; + } - m_stdio_communication.SetCloseOnEOF (false); - m_stdio_communication.SetConnection (conn_up.release()); - if (!m_stdio_communication.IsConnected ()) - { - error.SetErrorString ("failed to set connection for inferior I/O communication"); - return error; - } + StreamString response; + response.PutChar('O'); + response.PutBytesAsRawHex8(buffer, len); - return Error(); + return SendPacketNoLock(response.GetString()); } -void -GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() -{ - // Don't forward if not connected (e.g. when attaching). - if (! m_stdio_communication.IsConnected()) - return; - - Error error; - lldbassert(! m_stdio_handle_up); - m_stdio_handle_up = m_mainloop.RegisterReadObject( - m_stdio_communication.GetConnection()->GetReadObject(), - [this] (MainLoopBase &) { SendProcessOutput(); }, error); - - if (! m_stdio_handle_up) - { - // Not much we can do about the failure. Log it and continue without forwarding. - if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s", - __FUNCTION__, error.AsCString()); - } -} +Error GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { + Error error; -void -GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() -{ - m_stdio_handle_up.reset(); -} + // Set up the reading/handling of process I/O + std::unique_ptr<ConnectionFileDescriptor> conn_up( + new ConnectionFileDescriptor(fd, true)); + if (!conn_up) { + error.SetErrorString("failed to create ConnectionFileDescriptor"); + return error; + } -void -GDBRemoteCommunicationServerLLGS::SendProcessOutput() -{ - char buffer[1024]; - ConnectionStatus status; - Error error; - while (true) - { - size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error); - switch (status) - { - case eConnectionStatusSuccess: - SendONotification(buffer, bytes_read); - break; - case eConnectionStatusLostConnection: - case eConnectionStatusEndOfFile: - case eConnectionStatusError: - case eConnectionStatusNoConnection: - if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString()); - m_stdio_handle_up.reset(); - return; - - case eConnectionStatusInterrupted: - case eConnectionStatusTimedOut: - return; - } - } + m_stdio_communication.SetCloseOnEOF(false); + m_stdio_communication.SetConnection(conn_up.release()); + if (!m_stdio_communication.IsConnected()) { + error.SetErrorString( + "failed to set connection for inferior I/O communication"); + return error; + } + + return Error(); +} + +void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { + // Don't forward if not connected (e.g. when attaching). + if (!m_stdio_communication.IsConnected()) + return; + + Error error; + lldbassert(!m_stdio_handle_up); + m_stdio_handle_up = m_mainloop.RegisterReadObject( + m_stdio_communication.GetConnection()->GetReadObject(), + [this](MainLoopBase &) { SendProcessOutput(); }, error); + + if (!m_stdio_handle_up) { + // Not much we can do about the failure. Log it and continue without + // forwarding. + if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) + log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " + "forwarding: %s", + __FUNCTION__, error.AsCString()); + } +} + +void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() { + m_stdio_handle_up.reset(); +} + +void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { + char buffer[1024]; + ConnectionStatus status; + Error error; + while (true) { + size_t bytes_read = + m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error); + switch (status) { + case eConnectionStatusSuccess: + SendONotification(buffer, bytes_read); + break; + case eConnectionStatusLostConnection: + case eConnectionStatusEndOfFile: + case eConnectionStatusError: + case eConnectionStatusNoConnection: + if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) + log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio " + "forwarding as communication returned status %d (error: " + "%s)", + __FUNCTION__, status, error.AsCString()); + m_stdio_handle_up.reset(); + return; + + case eConnectionStatusInterrupted: + case eConnectionStatusTimedOut: + return; + } + } } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo (StringExtractorGDBRemote &packet) -{ - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); +GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); - lldb::pid_t pid = m_debugged_process_sp->GetID (); + lldb::pid_t pid = m_debugged_process_sp->GetID(); - if (pid == LLDB_INVALID_PROCESS_ID) - return SendErrorResponse (1); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(1); - ProcessInstanceInfo proc_info; - if (!Host::GetProcessInfo (pid, proc_info)) - return SendErrorResponse (1); + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo(pid, proc_info)) + return SendErrorResponse(1); - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetString()); + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet) -{ - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); +GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID (); - SetCurrentThreadID (tid); + // Make sure we set the current thread so g and p packets return + // the data the gdb will expect. + lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); + SetCurrentThreadID(tid); - NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread (); - if (!thread_sp) - return SendErrorResponse (69); + NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread(); + if (!thread_sp) + return SendErrorResponse(69); - StreamString response; - response.Printf ("QC%" PRIx64, thread_sp->GetID ()); + StreamString response; + response.Printf("QC%" PRIx64, thread_sp->GetID()); - return SendPacketNoLock (response.GetString()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); +GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - StopSTDIOForwarding(); + StopSTDIOForwarding(); - if (! m_debugged_process_sp) - { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__); - return PacketResult::Success; - } + if (!m_debugged_process_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s No debugged process found.", + __FUNCTION__); + return PacketResult::Success; + } - Error error = m_debugged_process_sp->Kill(); - if (error.Fail() && log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s", - __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); + Error error = m_debugged_process_sp->Kill(); + if (error.Fail() && log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged " + "process %" PRIu64 ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); - // No OK response for kill packet. - // return SendOKResponse (); - return PacketResult::Success; + // No OK response for kill packet. + // return SendOKResponse (); + return PacketResult::Success; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("QSetDisableASLR:")); - if (packet.GetU32(0)) - m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR); - else - m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); - return SendOKResponse (); +GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetDisableASLR:")); + if (packet.GetU32(0)) + m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR); + else + m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos (::strlen ("QSetWorkingDir:")); - std::string path; - packet.GetHexByteString (path); - m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); - return SendOKResponse (); +GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetWorkingDir:")); + std::string path; + packet.GetHexByteString(path); + m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) -{ - FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; - if (working_dir) - { - StreamString response; - response.PutCStringAsRawHex8(working_dir.GetCString()); - return SendPacketNoLock(response.GetString()); - } +GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( + StringExtractorGDBRemote &packet) { + FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; + if (working_dir) { + StreamString response; + response.PutCStringAsRawHex8(working_dir.GetCString()); + return SendPacketNoLock(response.GetString()); + } - return SendErrorResponse(14); + return SendErrorResponse(14); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_C (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - - // Ensure we have a native process. - if (!m_debugged_process_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__); - return SendErrorResponse (0x36); - } - - // Pull out the signal number. - packet.SetFilePos (::strlen ("C")); - if (packet.GetBytesLeft () < 1) - { - // Shouldn't be using a C without a signal. - return SendIllFormedResponse (packet, "C packet specified without signal."); - } - const uint32_t signo = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (signo == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse (packet, "failed to parse signal number"); - - // Handle optional continue address. - if (packet.GetBytesLeft () > 0) - { - // FIXME add continue at address support for $C{signo}[;{continue-address}]. - if (*packet.Peek () == ';') - return SendUnimplementedResponse (packet.GetStringRef().c_str()); - else - return SendIllFormedResponse (packet, "unexpected content after $C{signal-number}"); - } - - ResumeActionList resume_actions (StateType::eStateRunning, 0); - Error error; - - // We have two branches: what to do if a continue thread is specified (in which case we target - // sending the signal to that thread), or when we don't have a continue thread set (in which - // case we send a signal to the process). +GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - // TODO discuss with Greg Clayton, make sure this makes sense. - - lldb::tid_t signal_tid = GetContinueThreadID (); - if (signal_tid != LLDB_INVALID_THREAD_ID) - { - // The resume action for the continue thread (or all threads if a continue thread is not set). - ResumeAction action = { GetContinueThreadID (), StateType::eStateRunning, static_cast<int> (signo) }; - - // Add the action for the continue thread (or all threads when the continue thread isn't present). - resume_actions.Append (action); - } + // Ensure we have a native process. + if (!m_debugged_process_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); + return SendErrorResponse(0x36); + } + + // Pull out the signal number. + packet.SetFilePos(::strlen("C")); + if (packet.GetBytesLeft() < 1) { + // Shouldn't be using a C without a signal. + return SendIllFormedResponse(packet, "C packet specified without signal."); + } + const uint32_t signo = + packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); + if (signo == std::numeric_limits<uint32_t>::max()) + return SendIllFormedResponse(packet, "failed to parse signal number"); + + // Handle optional continue address. + if (packet.GetBytesLeft() > 0) { + // FIXME add continue at address support for $C{signo}[;{continue-address}]. + if (*packet.Peek() == ';') + return SendUnimplementedResponse(packet.GetStringRef().c_str()); else - { - // Send the signal to the process since we weren't targeting a specific continue thread with the signal. - error = m_debugged_process_sp->Signal (signo); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send signal for process %" PRIu64 ": %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - - return SendErrorResponse (0x52); - } - } - - // Resume the threads. - error = m_debugged_process_sp->Resume (resume_actions); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to resume threads for process %" PRIu64 ": %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); + return SendIllFormedResponse( + packet, "unexpected content after $C{signal-number}"); + } + + ResumeActionList resume_actions(StateType::eStateRunning, 0); + Error error; + + // We have two branches: what to do if a continue thread is specified (in + // which case we target + // sending the signal to that thread), or when we don't have a continue thread + // set (in which + // case we send a signal to the process). + + // TODO discuss with Greg Clayton, make sure this makes sense. + + lldb::tid_t signal_tid = GetContinueThreadID(); + if (signal_tid != LLDB_INVALID_THREAD_ID) { + // The resume action for the continue thread (or all threads if a continue + // thread is not set). + ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning, + static_cast<int>(signo)}; + + // Add the action for the continue thread (or all threads when the continue + // thread isn't present). + resume_actions.Append(action); + } else { + // Send the signal to the process since we weren't targeting a specific + // continue thread with the signal. + error = m_debugged_process_sp->Signal(signo); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send " + "signal for process %" PRIu64 ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + + return SendErrorResponse(0x52); + } + } + + // Resume the threads. + error = m_debugged_process_sp->Resume(resume_actions); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to resume " + "threads for process %" PRIu64 ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); - return SendErrorResponse (0x38); - } + return SendErrorResponse(0x38); + } - // Don't send an "OK" packet; response is the stopped/exited message. - return PacketResult::Success; + // Don't send an "OK" packet; response is the stopped/exited message. + return PacketResult::Success; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_c (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - - packet.SetFilePos (packet.GetFilePos() + ::strlen ("c")); +GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - // For now just support all continue. - const bool has_continue_address = (packet.GetBytesLeft () > 0); - if (has_continue_address) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s not implemented for c{address} variant [%s remains]", __FUNCTION__, packet.Peek ()); - return SendUnimplementedResponse (packet.GetStringRef().c_str()); - } + packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); - // Ensure we have a native process. - if (!m_debugged_process_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__); - return SendErrorResponse (0x36); - } + // For now just support all continue. + const bool has_continue_address = (packet.GetBytesLeft() > 0); + if (has_continue_address) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s not implemented for " + "c{address} variant [%s remains]", + __FUNCTION__, packet.Peek()); + return SendUnimplementedResponse(packet.GetStringRef().c_str()); + } + + // Ensure we have a native process. + if (!m_debugged_process_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); + return SendErrorResponse(0x36); + } - // Build the ResumeActionList - ResumeActionList actions (StateType::eStateRunning, 0); + // Build the ResumeActionList + ResumeActionList actions(StateType::eStateRunning, 0); - Error error = m_debugged_process_sp->Resume (actions); - if (error.Fail ()) - { - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64 ": %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - } - return SendErrorResponse (GDBRemoteServerError::eErrorResume); + Error error = m_debugged_process_sp->Resume(actions); + if (error.Fail()) { + if (log) { + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64 + ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); } + return SendErrorResponse(GDBRemoteServerError::eErrorResume); + } - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ()); + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); - // No response required from continue. - return PacketResult::Success; + // No response required from continue. + return PacketResult::Success; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_vCont_actions (StringExtractorGDBRemote &packet) -{ - StreamString response; - response.Printf("vCont;c;C;s;S"); +GDBRemoteCommunicationServerLLGS::Handle_vCont_actions( + StringExtractorGDBRemote &packet) { + StreamString response; + response.Printf("vCont;c;C;s;S"); - return SendPacketNoLock(response.GetString()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", __FUNCTION__); - - packet.SetFilePos (::strlen ("vCont")); +GDBRemoteCommunicationServerLLGS::Handle_vCont( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", + __FUNCTION__); - if (packet.GetBytesLeft() == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s missing action from vCont package", __FUNCTION__); - return SendIllFormedResponse (packet, "Missing action from vCont package"); - } + packet.SetFilePos(::strlen("vCont")); - // Check if this is all continue (no options or ";c"). - if (::strcmp (packet.Peek (), ";c") == 0) - { - // Move past the ';', then do a simple 'c'. - packet.SetFilePos (packet.GetFilePos () + 1); - return Handle_c (packet); - } - else if (::strcmp (packet.Peek (), ";s") == 0) - { - // Move past the ';', then do a simple 's'. - packet.SetFilePos (packet.GetFilePos () + 1); - return Handle_s (packet); - } + if (packet.GetBytesLeft() == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from " + "vCont package", + __FUNCTION__); + return SendIllFormedResponse(packet, "Missing action from vCont package"); + } + + // Check if this is all continue (no options or ";c"). + if (::strcmp(packet.Peek(), ";c") == 0) { + // Move past the ';', then do a simple 'c'. + packet.SetFilePos(packet.GetFilePos() + 1); + return Handle_c(packet); + } else if (::strcmp(packet.Peek(), ";s") == 0) { + // Move past the ';', then do a simple 's'. + packet.SetFilePos(packet.GetFilePos() + 1); + return Handle_s(packet); + } + + // Ensure we have a native process. + if (!m_debugged_process_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); + return SendErrorResponse(0x36); + } + + ResumeActionList thread_actions; + + while (packet.GetBytesLeft() && *packet.Peek() == ';') { + // Skip the semi-colon. + packet.GetChar(); + + // Build up the thread action. + ResumeAction thread_action; + thread_action.tid = LLDB_INVALID_THREAD_ID; + thread_action.state = eStateInvalid; + thread_action.signal = 0; + + const char action = packet.GetChar(); + switch (action) { + case 'C': + thread_action.signal = packet.GetHexMaxU32(false, 0); + if (thread_action.signal == 0) + return SendIllFormedResponse( + packet, "Could not parse signal in vCont packet C action"); + LLVM_FALLTHROUGH; + + case 'c': + // Continue + thread_action.state = eStateRunning; + break; + + case 'S': + thread_action.signal = packet.GetHexMaxU32(false, 0); + if (thread_action.signal == 0) + return SendIllFormedResponse( + packet, "Could not parse signal in vCont packet S action"); + LLVM_FALLTHROUGH; + + case 's': + // Step + thread_action.state = eStateStepping; + break; - // Ensure we have a native process. - if (!m_debugged_process_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__); - return SendErrorResponse (0x36); + default: + return SendIllFormedResponse(packet, "Unsupported vCont action"); + break; } - ResumeActionList thread_actions; - - while (packet.GetBytesLeft () && *packet.Peek () == ';') - { - // Skip the semi-colon. - packet.GetChar (); - - // Build up the thread action. - ResumeAction thread_action; - thread_action.tid = LLDB_INVALID_THREAD_ID; - thread_action.state = eStateInvalid; - thread_action.signal = 0; - - const char action = packet.GetChar (); - switch (action) - { - case 'C': - thread_action.signal = packet.GetHexMaxU32 (false, 0); - if (thread_action.signal == 0) - return SendIllFormedResponse (packet, "Could not parse signal in vCont packet C action"); - LLVM_FALLTHROUGH; - - case 'c': - // Continue - thread_action.state = eStateRunning; - break; - - case 'S': - thread_action.signal = packet.GetHexMaxU32 (false, 0); - if (thread_action.signal == 0) - return SendIllFormedResponse (packet, "Could not parse signal in vCont packet S action"); - LLVM_FALLTHROUGH; - - case 's': - // Step - thread_action.state = eStateStepping; - break; - - default: - return SendIllFormedResponse (packet, "Unsupported vCont action"); - break; - } - - // Parse out optional :{thread-id} value. - if (packet.GetBytesLeft () && (*packet.Peek () == ':')) - { - // Consume the separator. - packet.GetChar (); - - thread_action.tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID); - if (thread_action.tid == LLDB_INVALID_THREAD_ID) - return SendIllFormedResponse (packet, "Could not parse thread number in vCont packet"); - } + // Parse out optional :{thread-id} value. + if (packet.GetBytesLeft() && (*packet.Peek() == ':')) { + // Consume the separator. + packet.GetChar(); - thread_actions.Append (thread_action); + thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); + if (thread_action.tid == LLDB_INVALID_THREAD_ID) + return SendIllFormedResponse( + packet, "Could not parse thread number in vCont packet"); } - Error error = m_debugged_process_sp->Resume (thread_actions); - if (error.Fail ()) - { - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s vCont failed for process %" PRIu64 ": %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - } - return SendErrorResponse (GDBRemoteServerError::eErrorResume); + thread_actions.Append(thread_action); + } + + Error error = m_debugged_process_sp->Resume(thread_actions); + if (error.Fail()) { + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s vCont failed for " + "process %" PRIu64 ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); } + return SendErrorResponse(GDBRemoteServerError::eErrorResume); + } - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ()); + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); - // No response required from vCont. - return PacketResult::Success; + // No response required from vCont. + return PacketResult::Success; } -void -GDBRemoteCommunicationServerLLGS::SetCurrentThreadID (lldb::tid_t tid) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s setting current thread id to %" PRIu64, __FUNCTION__, tid); +void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s setting current thread " + "id to %" PRIu64, + __FUNCTION__, tid); - m_current_tid = tid; - if (m_debugged_process_sp) - m_debugged_process_sp->SetCurrentThreadID (m_current_tid); + m_current_tid = tid; + if (m_debugged_process_sp) + m_debugged_process_sp->SetCurrentThreadID(m_current_tid); } -void -GDBRemoteCommunicationServerLLGS::SetContinueThreadID (lldb::tid_t tid) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s setting continue thread id to %" PRIu64, __FUNCTION__, tid); +void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s setting continue thread " + "id to %" PRIu64, + __FUNCTION__, tid); - m_continue_tid = tid; + m_continue_tid = tid; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &packet) -{ - // Handle the $? gdbremote command. +GDBRemoteCommunicationServerLLGS::Handle_stop_reason( + StringExtractorGDBRemote &packet) { + // Handle the $? gdbremote command. - // If no process, indicate error - if (!m_debugged_process_sp) - return SendErrorResponse (02); + // If no process, indicate error + if (!m_debugged_process_sp) + return SendErrorResponse(02); - return SendStopReasonForState (m_debugged_process_sp->GetState()); + return SendStopReasonForState(m_debugged_process_sp->GetState()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - switch (process_state) - { - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - // NOTE: gdb protocol doc looks like it should return $OK - // when everything is running (i.e. no stopped result). - return PacketResult::Success; // Ignore - - case eStateSuspended: - case eStateStopped: - case eStateCrashed: - { - lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID (); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThreadID (tid); - return SendStopReplyPacketForThread (tid); - } +GDBRemoteCommunicationServerLLGS::SendStopReasonForState( + lldb::StateType process_state) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + switch (process_state) { + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + // NOTE: gdb protocol doc looks like it should return $OK + // when everything is running (i.e. no stopped result). + return PacketResult::Success; // Ignore + + case eStateSuspended: + case eStateStopped: + case eStateCrashed: { + lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); + // Make sure we set the current thread so g and p packets return + // the data the gdb will expect. + SetCurrentThreadID(tid); + return SendStopReplyPacketForThread(tid); + } - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - return SendWResponse(m_debugged_process_sp.get()); + case eStateInvalid: + case eStateUnloaded: + case eStateExited: + return SendWResponse(m_debugged_process_sp.get()); - default: - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", current state reporting not handled: %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - StateAsCString (process_state)); - } - break; + default: + if (log) { + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + ", current state reporting not handled: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + StateAsCString(process_state)); } - - return SendErrorResponse (0); + break; + } + + return SendErrorResponse(0); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote &packet) -{ - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); - - // Ensure we have a thread. - NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadAtIndex (0)); - if (!thread_sp) - return SendErrorResponse (69); - - // Get the register context for the first thread. - NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ()); - if (!reg_context_sp) - return SendErrorResponse (69); - - // Parse out the register number from the request. - packet.SetFilePos (strlen("qRegisterInfo")); - const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (reg_index == std::numeric_limits<uint32_t>::max ()) - return SendErrorResponse (69); - - // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount ()) - return SendErrorResponse (69); - - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - return SendErrorResponse (69); - - // Build the reginfos response. - StreamGDBRemote response; - - response.PutCString ("name:"); - response.PutCString (reg_info->name); - response.PutChar (';'); - - if (reg_info->alt_name && reg_info->alt_name[0]) - { - response.PutCString ("alt-name:"); - response.PutCString (reg_info->alt_name); - response.PutChar (';'); - } - - response.Printf ("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", reg_info->byte_size * 8, reg_info->byte_offset); - - switch (reg_info->encoding) - { - case eEncodingUint: response.PutCString ("encoding:uint;"); break; - case eEncodingSint: response.PutCString ("encoding:sint;"); break; - case eEncodingIEEE754: response.PutCString ("encoding:ieee754;"); break; - case eEncodingVector: response.PutCString ("encoding:vector;"); break; - default: break; - } - - switch (reg_info->format) - { - case eFormatBinary: response.PutCString ("format:binary;"); break; - case eFormatDecimal: response.PutCString ("format:decimal;"); break; - case eFormatHex: response.PutCString ("format:hex;"); break; - case eFormatFloat: response.PutCString ("format:float;"); break; - case eFormatVectorOfSInt8: response.PutCString ("format:vector-sint8;"); break; - case eFormatVectorOfUInt8: response.PutCString ("format:vector-uint8;"); break; - case eFormatVectorOfSInt16: response.PutCString ("format:vector-sint16;"); break; - case eFormatVectorOfUInt16: response.PutCString ("format:vector-uint16;"); break; - case eFormatVectorOfSInt32: response.PutCString ("format:vector-sint32;"); break; - case eFormatVectorOfUInt32: response.PutCString ("format:vector-uint32;"); break; - case eFormatVectorOfFloat32: response.PutCString ("format:vector-float32;"); break; - case eFormatVectorOfUInt128: response.PutCString ("format:vector-uint128;"); break; - default: break; - }; - - const char *const register_set_name = reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index); - if (register_set_name) - { - response.PutCString ("set:"); - response.PutCString (register_set_name); - response.PutChar (';'); - } - - if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) - response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); - - if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM) - response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]); - - switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) - { - case LLDB_REGNUM_GENERIC_PC: response.PutCString("generic:pc;"); break; - case LLDB_REGNUM_GENERIC_SP: response.PutCString("generic:sp;"); break; - case LLDB_REGNUM_GENERIC_FP: response.PutCString("generic:fp;"); break; - case LLDB_REGNUM_GENERIC_RA: response.PutCString("generic:ra;"); break; - case LLDB_REGNUM_GENERIC_FLAGS: response.PutCString("generic:flags;"); break; - case LLDB_REGNUM_GENERIC_ARG1: response.PutCString("generic:arg1;"); break; - case LLDB_REGNUM_GENERIC_ARG2: response.PutCString("generic:arg2;"); break; - case LLDB_REGNUM_GENERIC_ARG3: response.PutCString("generic:arg3;"); break; - case LLDB_REGNUM_GENERIC_ARG4: response.PutCString("generic:arg4;"); break; - case LLDB_REGNUM_GENERIC_ARG5: response.PutCString("generic:arg5;"); break; - case LLDB_REGNUM_GENERIC_ARG6: response.PutCString("generic:arg6;"); break; - case LLDB_REGNUM_GENERIC_ARG7: response.PutCString("generic:arg7;"); break; - case LLDB_REGNUM_GENERIC_ARG8: response.PutCString("generic:arg8;"); break; - default: break; - } - - if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) - { - response.PutCString ("container-regs:"); - int i = 0; - for (const uint32_t *reg_num = reg_info->value_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) - { - if (i > 0) - response.PutChar (','); - response.Printf ("%" PRIx32, *reg_num); - } - response.PutChar (';'); - } - - if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) - { - response.PutCString ("invalidate-regs:"); - int i = 0; - for (const uint32_t *reg_num = reg_info->invalidate_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) - { - if (i > 0) - response.PutChar (','); - response.Printf ("%" PRIx32, *reg_num); - } - response.PutChar (';'); - } - - if (reg_info->dynamic_size_dwarf_expr_bytes) - { - const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len; - response.PutCString("dynamic_size_dwarf_expr_bytes:"); - for(uint32_t i = 0; i < dwarf_opcode_len; ++i) - response.PutHex8 (reg_info->dynamic_size_dwarf_expr_bytes[i]); - response.PutChar(';'); - } - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + // Ensure we have a thread. + NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadAtIndex(0)); + if (!thread_sp) + return SendErrorResponse(69); + + // Get the register context for the first thread. + NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); + if (!reg_context_sp) + return SendErrorResponse(69); + + // Parse out the register number from the request. + packet.SetFilePos(strlen("qRegisterInfo")); + const uint32_t reg_index = + packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); + if (reg_index == std::numeric_limits<uint32_t>::max()) + return SendErrorResponse(69); + + // Return the end of registers response if we've iterated one past the end of + // the register set. + if (reg_index >= reg_context_sp->GetUserRegisterCount()) + return SendErrorResponse(69); + + const RegisterInfo *reg_info = + reg_context_sp->GetRegisterInfoAtIndex(reg_index); + if (!reg_info) + return SendErrorResponse(69); + + // Build the reginfos response. + StreamGDBRemote response; + + response.PutCString("name:"); + response.PutCString(reg_info->name); + response.PutChar(';'); + + if (reg_info->alt_name && reg_info->alt_name[0]) { + response.PutCString("alt-name:"); + response.PutCString(reg_info->alt_name); + response.PutChar(';'); + } + + response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", + reg_info->byte_size * 8, reg_info->byte_offset); + + switch (reg_info->encoding) { + case eEncodingUint: + response.PutCString("encoding:uint;"); + break; + case eEncodingSint: + response.PutCString("encoding:sint;"); + break; + case eEncodingIEEE754: + response.PutCString("encoding:ieee754;"); + break; + case eEncodingVector: + response.PutCString("encoding:vector;"); + break; + default: + break; + } + + switch (reg_info->format) { + case eFormatBinary: + response.PutCString("format:binary;"); + break; + case eFormatDecimal: + response.PutCString("format:decimal;"); + break; + case eFormatHex: + response.PutCString("format:hex;"); + break; + case eFormatFloat: + response.PutCString("format:float;"); + break; + case eFormatVectorOfSInt8: + response.PutCString("format:vector-sint8;"); + break; + case eFormatVectorOfUInt8: + response.PutCString("format:vector-uint8;"); + break; + case eFormatVectorOfSInt16: + response.PutCString("format:vector-sint16;"); + break; + case eFormatVectorOfUInt16: + response.PutCString("format:vector-uint16;"); + break; + case eFormatVectorOfSInt32: + response.PutCString("format:vector-sint32;"); + break; + case eFormatVectorOfUInt32: + response.PutCString("format:vector-uint32;"); + break; + case eFormatVectorOfFloat32: + response.PutCString("format:vector-float32;"); + break; + case eFormatVectorOfUInt128: + response.PutCString("format:vector-uint128;"); + break; + default: + break; + }; + + const char *const register_set_name = + reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index); + if (register_set_name) { + response.PutCString("set:"); + response.PutCString(register_set_name); + response.PutChar(';'); + } + + if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != + LLDB_INVALID_REGNUM) + response.Printf("ehframe:%" PRIu32 ";", + reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); + + if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM) + response.Printf("dwarf:%" PRIu32 ";", + reg_info->kinds[RegisterKind::eRegisterKindDWARF]); + + switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) { + case LLDB_REGNUM_GENERIC_PC: + response.PutCString("generic:pc;"); + break; + case LLDB_REGNUM_GENERIC_SP: + response.PutCString("generic:sp;"); + break; + case LLDB_REGNUM_GENERIC_FP: + response.PutCString("generic:fp;"); + break; + case LLDB_REGNUM_GENERIC_RA: + response.PutCString("generic:ra;"); + break; + case LLDB_REGNUM_GENERIC_FLAGS: + response.PutCString("generic:flags;"); + break; + case LLDB_REGNUM_GENERIC_ARG1: + response.PutCString("generic:arg1;"); + break; + case LLDB_REGNUM_GENERIC_ARG2: + response.PutCString("generic:arg2;"); + break; + case LLDB_REGNUM_GENERIC_ARG3: + response.PutCString("generic:arg3;"); + break; + case LLDB_REGNUM_GENERIC_ARG4: + response.PutCString("generic:arg4;"); + break; + case LLDB_REGNUM_GENERIC_ARG5: + response.PutCString("generic:arg5;"); + break; + case LLDB_REGNUM_GENERIC_ARG6: + response.PutCString("generic:arg6;"); + break; + case LLDB_REGNUM_GENERIC_ARG7: + response.PutCString("generic:arg7;"); + break; + case LLDB_REGNUM_GENERIC_ARG8: + response.PutCString("generic:arg8;"); + break; + default: + break; + } + + if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { + response.PutCString("container-regs:"); + int i = 0; + for (const uint32_t *reg_num = reg_info->value_regs; + *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { + if (i > 0) + response.PutChar(','); + response.Printf("%" PRIx32, *reg_num); + } + response.PutChar(';'); + } + + if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { + response.PutCString("invalidate-regs:"); + int i = 0; + for (const uint32_t *reg_num = reg_info->invalidate_regs; + *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { + if (i > 0) + response.PutChar(','); + response.Printf("%" PRIx32, *reg_num); + } + response.PutChar(';'); + } + + if (reg_info->dynamic_size_dwarf_expr_bytes) { + const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len; + response.PutCString("dynamic_size_dwarf_expr_bytes:"); + for (uint32_t i = 0; i < dwarf_opcode_len; ++i) + response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]); + response.PutChar(';'); + } + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s() no process (%s), returning OK", __FUNCTION__, m_debugged_process_sp ? "invalid process id" : "null m_debugged_process_sp"); - return SendOKResponse (); - } - - StreamGDBRemote response; - response.PutChar ('m'); +GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s() starting thread iteration", __FUNCTION__); - - NativeThreadProtocolSP thread_sp; - uint32_t thread_index; - for (thread_index = 0, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index); - thread_sp; - ++thread_index, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32 "(%s, tid=0x%" PRIx64 ")", __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", thread_sp ? thread_sp->GetID () : LLDB_INVALID_THREAD_ID); - if (thread_index > 0) - response.PutChar(','); - response.Printf ("%" PRIx64, thread_sp->GetID ()); - } - + log->Printf("GDBRemoteCommunicationServerLLGS::%s() no process (%s), " + "returning OK", + __FUNCTION__, + m_debugged_process_sp ? "invalid process id" + : "null m_debugged_process_sp"); + return SendOKResponse(); + } + + StreamGDBRemote response; + response.PutChar('m'); + + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s() starting thread iteration", + __FUNCTION__); + + NativeThreadProtocolSP thread_sp; + uint32_t thread_index; + for (thread_index = 0, + thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index); + thread_sp; ++thread_index, + thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index)) { if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s() finished thread iteration", __FUNCTION__); + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32 + "(%s, tid=0x%" PRIx64 ")", + __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", + thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); + if (thread_index > 0) + response.PutChar(','); + response.Printf("%" PRIx64, thread_sp->GetID()); + } - return SendPacketNoLock(response.GetString()); + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s() finished thread iteration", + __FUNCTION__); + + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo (StringExtractorGDBRemote &packet) -{ - // FIXME for now we return the full thread list in the initial packet and always do nothing here. - return SendPacketNoLock ("l"); +GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo( + StringExtractorGDBRemote &packet) { + // FIXME for now we return the full thread list in the initial packet and + // always do nothing here. + return SendPacketNoLock("l"); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_p (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Parse out the register number from the request. - packet.SetFilePos (strlen("p")); - const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (reg_index == std::numeric_limits<uint32_t>::max ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ()); - return SendErrorResponse (0x15); - } - - // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); - if (!thread_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no thread available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Get the thread's register context. - NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ()); - if (!reg_context_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ()); - return SendErrorResponse (0x15); - } - - // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); - return SendErrorResponse (0x15); - } - - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index); - return SendErrorResponse (0x15); - } - - // Build the reginfos response. - StreamGDBRemote response; - - // Retrieve the value - RegisterValue reg_value; - Error error = reg_context_sp->ReadRegister (reg_info, reg_value); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, read of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ()); - return SendErrorResponse (0x15); - } - - const uint8_t *const data = reinterpret_cast<const uint8_t*> (reg_value.GetBytes ()); - if (!data) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to get data bytes from requested register %" PRIu32, __FUNCTION__, reg_index); - return SendErrorResponse (0x15); - } +GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Parse out the register number from the request. + packet.SetFilePos(strlen("p")); + const uint32_t reg_index = + packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); + if (reg_index == std::numeric_limits<uint32_t>::max()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().c_str()); + return SendErrorResponse(0x15); + } + + // Get the thread to use. + NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); + if (!thread_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no thread available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Get the thread's register context. + NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); + if (!reg_context_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 + " failed, no register context available for the thread", + __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + return SendErrorResponse(0x15); + } + + // Return the end of registers response if we've iterated one past the end of + // the register set. + if (reg_index >= reg_context_sp->GetUserRegisterCount()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, + reg_context_sp->GetUserRegisterCount()); + return SendErrorResponse(0x15); + } + + const RegisterInfo *reg_info = + reg_context_sp->GetRegisterInfoAtIndex(reg_index); + if (!reg_info) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); + return SendErrorResponse(0x15); + } + + // Build the reginfos response. + StreamGDBRemote response; + + // Retrieve the value + RegisterValue reg_value; + Error error = reg_context_sp->ReadRegister(reg_info, reg_value); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + return SendErrorResponse(0x15); + } + + const uint8_t *const data = + reinterpret_cast<const uint8_t *>(reg_value.GetBytes()); + if (!data) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data " + "bytes from requested register %" PRIu32, + __FUNCTION__, reg_index); + return SendErrorResponse(0x15); + } - // FIXME flip as needed to get data in big/little endian format for this host. - for (uint32_t i = 0; i < reg_value.GetByteSize (); ++i) - response.PutHex8 (data[i]); + // FIXME flip as needed to get data in big/little endian format for this host. + for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i) + response.PutHex8(data[i]); - return SendPacketNoLock (response.GetString()); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_P (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Ensure there is more content. - if (packet.GetBytesLeft () < 1) - return SendIllFormedResponse (packet, "Empty P packet"); - - // Parse out the register number from the request. - packet.SetFilePos (strlen("P")); - const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (reg_index == std::numeric_limits<uint32_t>::max ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ()); - return SendErrorResponse (0x29); - } - - // Note debugserver would send an E30 here. - if ((packet.GetBytesLeft () < 1) || (packet.GetChar () != '=')) - return SendIllFormedResponse (packet, "P packet missing '=' char after register number"); - - // Get process architecture. - ArchSpec process_arch; - if (!m_debugged_process_sp || !m_debugged_process_sp->GetArchitecture (process_arch)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to retrieve inferior architecture", __FUNCTION__); - return SendErrorResponse (0x49); - } - - // Parse out the value. - uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register - size_t reg_size = packet.GetHexBytesAvail (reg_bytes); - - // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); - if (!thread_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no thread available (thread index 0)", __FUNCTION__); - return SendErrorResponse (0x28); - } - - // Get the thread's register context. - NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ()); - if (!reg_context_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ()); - return SendErrorResponse (0x15); - } - - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index); - return SendErrorResponse (0x48); - } - - // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); - return SendErrorResponse (0x47); - } - - // The dwarf expression are evaluate on host site - // which may cause register size to change - // Hence the reg_size may not be same as reg_info->bytes_size - if ((reg_size != reg_info->byte_size) && !(reg_info->dynamic_size_dwarf_expr_bytes)) - { - return SendIllFormedResponse (packet, "P packet register size is incorrect"); - } - - // Build the reginfos response. - StreamGDBRemote response; - - RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ()); - Error error = reg_context_sp->WriteRegister (reg_info, reg_value); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, write of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ()); - return SendErrorResponse (0x32); - } +GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Ensure there is more content. + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Empty P packet"); + + // Parse out the register number from the request. + packet.SetFilePos(strlen("P")); + const uint32_t reg_index = + packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); + if (reg_index == std::numeric_limits<uint32_t>::max()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().c_str()); + return SendErrorResponse(0x29); + } + + // Note debugserver would send an E30 here. + if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '=')) + return SendIllFormedResponse( + packet, "P packet missing '=' char after register number"); + + // Get process architecture. + ArchSpec process_arch; + if (!m_debugged_process_sp || + !m_debugged_process_sp->GetArchitecture(process_arch)) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve " + "inferior architecture", + __FUNCTION__); + return SendErrorResponse(0x49); + } + + // Parse out the value. + uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register + size_t reg_size = packet.GetHexBytesAvail(reg_bytes); + + // Get the thread to use. + NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); + if (!thread_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " + "available (thread index 0)", + __FUNCTION__); + return SendErrorResponse(0x28); + } + + // Get the thread's register context. + NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); + if (!reg_context_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 + " failed, no register context available for the thread", + __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + return SendErrorResponse(0x15); + } + + const RegisterInfo *reg_info = + reg_context_sp->GetRegisterInfoAtIndex(reg_index); + if (!reg_info) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); + return SendErrorResponse(0x48); + } + + // Return the end of registers response if we've iterated one past the end of + // the register set. + if (reg_index >= reg_context_sp->GetUserRegisterCount()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, + reg_context_sp->GetUserRegisterCount()); + return SendErrorResponse(0x47); + } + + // The dwarf expression are evaluate on host site + // which may cause register size to change + // Hence the reg_size may not be same as reg_info->bytes_size + if ((reg_size != reg_info->byte_size) && + !(reg_info->dynamic_size_dwarf_expr_bytes)) { + return SendIllFormedResponse(packet, "P packet register size is incorrect"); + } + + // Build the reginfos response. + StreamGDBRemote response; + + RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder()); + Error error = reg_context_sp->WriteRegister(reg_info, reg_value); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + return SendErrorResponse(0x32); + } - return SendOKResponse(); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_H (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Parse out which variant of $H is requested. - packet.SetFilePos (strlen("H")); - if (packet.GetBytesLeft () < 1) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, H command missing {g,c} variant", __FUNCTION__); - return SendIllFormedResponse (packet, "H command missing {g,c} variant"); - } - - const char h_variant = packet.GetChar (); - switch (h_variant) - { - case 'g': - break; - - case 'c': - break; - - default: - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", __FUNCTION__, h_variant); - return SendIllFormedResponse (packet, "H variant unsupported, should be c or g"); - } - - // Parse out the thread number. - // FIXME return a parse success/fail value. All values are valid here. - const lldb::tid_t tid = packet.GetHexMaxU64 (false, std::numeric_limits<lldb::tid_t>::max ()); +GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - // Ensure we have the given thread when not specifying -1 (all threads) or 0 (any thread). - if (tid != LLDB_INVALID_THREAD_ID && tid != 0) - { - NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid)); - if (!thread_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 " not found", __FUNCTION__, tid); - return SendErrorResponse (0x15); - } - } - - // Now switch the given thread type. - switch (h_variant) - { - case 'g': - SetCurrentThreadID (tid); - break; + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out which variant of $H is requested. + packet.SetFilePos(strlen("H")); + if (packet.GetBytesLeft() < 1) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command " + "missing {g,c} variant", + __FUNCTION__); + return SendIllFormedResponse(packet, "H command missing {g,c} variant"); + } - case 'c': - SetContinueThreadID (tid); - break; + const char h_variant = packet.GetChar(); + switch (h_variant) { + case 'g': + break; - default: - assert (false && "unsupported $H variant - shouldn't get here"); - return SendIllFormedResponse (packet, "H variant unsupported, should be c or g"); - } + case 'c': + break; - return SendOKResponse(); + default: + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", + __FUNCTION__, h_variant); + return SendIllFormedResponse(packet, + "H variant unsupported, should be c or g"); + } + + // Parse out the thread number. + // FIXME return a parse success/fail value. All values are valid here. + const lldb::tid_t tid = + packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max()); + + // Ensure we have the given thread when not specifying -1 (all threads) or 0 + // (any thread). + if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { + NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); + if (!thread_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 + " not found", + __FUNCTION__, tid); + return SendErrorResponse(0x15); + } + } + + // Now switch the given thread type. + switch (h_variant) { + case 'g': + SetCurrentThreadID(tid); + break; + + case 'c': + SetContinueThreadID(tid); + break; + + default: + assert(false && "unsupported $H variant - shouldn't get here"); + return SendIllFormedResponse(packet, + "H variant unsupported, should be c or g"); + } + + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_I (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } +GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - packet.SetFilePos (::strlen("I")); - uint8_t tmp[4096]; - for (;;) - { - size_t read = packet.GetHexBytesAvail(tmp); - if (read == 0) - { - break; - } - // write directly to stdin *this might block if stdin buffer is full* - // TODO: enqueue this block in circular buffer and send window size to remote host - ConnectionStatus status; - Error error; - m_stdio_communication.Write(tmp, read, status, &error); - if (error.Fail()) - { - return SendErrorResponse (0x15); - } + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + packet.SetFilePos(::strlen("I")); + uint8_t tmp[4096]; + for (;;) { + size_t read = packet.GetHexBytesAvail(tmp); + if (read == 0) { + break; + } + // write directly to stdin *this might block if stdin buffer is full* + // TODO: enqueue this block in circular buffer and send window size to + // remote host + ConnectionStatus status; + Error error; + m_stdio_communication.Write(tmp, read, status, &error); + if (error.Fail()) { + return SendErrorResponse(0x15); } + } - return SendOKResponse(); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Interrupt the process. - Error error = m_debugged_process_sp->Interrupt (); - if (error.Fail ()) - { - if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64 ": %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - } - return SendErrorResponse (GDBRemoteServerError::eErrorResume); - } +GDBRemoteCommunicationServerLLGS::Handle_interrupt( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ()); + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Interrupt the process. + Error error = m_debugged_process_sp->Interrupt(); + if (error.Fail()) { + if (log) { + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64 + ": %s", + __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); + } + return SendErrorResponse(GDBRemoteServerError::eErrorResume); + } + + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); - // No response required from stop all. - return PacketResult::Success; + // No response required from stop all. + return PacketResult::Success; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } +GDBRemoteCommunicationServerLLGS::Handle_memory_read( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Parse out the memory address. - packet.SetFilePos (strlen("m")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short m packet"); - - // Read the address. Punting on validation. - // FIXME replace with Hex U64 read with no default value that fails on failed read. - const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); - - // Validate comma. - if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) - return SendIllFormedResponse(packet, "Comma sep missing in m packet"); - - // Get # bytes to read. - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Length missing in m packet"); - - const uint64_t byte_count = packet.GetHexMaxU64(false, 0); - if (byte_count == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__); - return SendOKResponse(); - } - - // Allocate the response buffer. - std::string buf(byte_count, '\0'); - if (buf.empty()) - return SendErrorResponse (0x78); - - - // Retrieve the process memory. - size_t bytes_read = 0; - Error error = m_debugged_process_sp->ReadMemoryWithoutTrap(read_addr, &buf[0], byte_count, bytes_read); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, error.AsCString ()); - return SendErrorResponse (0x08); - } - - if (bytes_read == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, byte_count); - return SendErrorResponse (0x08); - } - - StreamGDBRemote response; - packet.SetFilePos(0); - char kind = packet.GetChar('?'); - if (kind == 'x') - response.PutEscapedBytes(buf.data(), byte_count); - else - { - assert(kind == 'm'); - for (size_t i = 0; i < bytes_read; ++i) - response.PutHex8(buf[i]); - } - - return SendPacketNoLock(response.GetString()); + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out the memory address. + packet.SetFilePos(strlen("m")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Too short m packet"); + + // Read the address. Punting on validation. + // FIXME replace with Hex U64 read with no default value that fails on failed + // read. + const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); + + // Validate comma. + if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) + return SendIllFormedResponse(packet, "Comma sep missing in m packet"); + + // Get # bytes to read. + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Length missing in m packet"); + + const uint64_t byte_count = packet.GetHexMaxU64(false, 0); + if (byte_count == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: " + "zero-length packet", + __FUNCTION__); + return SendOKResponse(); + } + + // Allocate the response buffer. + std::string buf(byte_count, '\0'); + if (buf.empty()) + return SendErrorResponse(0x78); + + // Retrieve the process memory. + size_t bytes_read = 0; + Error error = m_debugged_process_sp->ReadMemoryWithoutTrap( + read_addr, &buf[0], byte_count, bytes_read); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": failed to read. Error: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, + error.AsCString()); + return SendErrorResponse(0x08); + } + + if (bytes_read == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", + __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, + byte_count); + return SendErrorResponse(0x08); + } + + StreamGDBRemote response; + packet.SetFilePos(0); + char kind = packet.GetChar('?'); + if (kind == 'x') + response.PutEscapedBytes(buf.data(), byte_count); + else { + assert(kind == 'm'); + for (size_t i = 0; i < bytes_read; ++i) + response.PutHex8(buf[i]); + } + + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_M (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Parse out the memory address. - packet.SetFilePos (strlen("M")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short M packet"); - - // Read the address. Punting on validation. - // FIXME replace with Hex U64 read with no default value that fails on failed read. - const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); +GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Validate comma. - if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) - return SendIllFormedResponse(packet, "Comma sep missing in M packet"); - - // Get # bytes to read. - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Length missing in M packet"); - - const uint64_t byte_count = packet.GetHexMaxU64(false, 0); - if (byte_count == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to write: zero-length packet", __FUNCTION__); - return PacketResult::Success; - } - - // Validate colon. - if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) - return SendIllFormedResponse(packet, "Comma sep missing in M packet after byte length"); - - // Allocate the conversion buffer. - std::vector<uint8_t> buf(byte_count, 0); - if (buf.empty()) - return SendErrorResponse (0x78); - - // Convert the hex memory write contents to bytes. - StreamGDBRemote response; - const uint64_t convert_count = packet.GetHexBytes(buf, 0); - if (convert_count != byte_count) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": asked to write %" PRIu64 " bytes, but only found %" PRIu64 " to convert.", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, byte_count, convert_count); - return SendIllFormedResponse (packet, "M content byte length specified did not match hex-encoded content length"); - } - - // Write the process memory. - size_t bytes_written = 0; - Error error = m_debugged_process_sp->WriteMemory (write_addr, &buf[0], byte_count, bytes_written); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to write. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, error.AsCString ()); - return SendErrorResponse (0x09); - } - - if (bytes_written == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, byte_count); - return SendErrorResponse (0x09); - } + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out the memory address. + packet.SetFilePos(strlen("M")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Too short M packet"); + + // Read the address. Punting on validation. + // FIXME replace with Hex U64 read with no default value that fails on failed + // read. + const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); + + // Validate comma. + if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) + return SendIllFormedResponse(packet, "Comma sep missing in M packet"); + + // Get # bytes to read. + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Length missing in M packet"); + + const uint64_t byte_count = packet.GetHexMaxU64(false, 0); + if (byte_count == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to write: " + "zero-length packet", + __FUNCTION__); + return PacketResult::Success; + } + + // Validate colon. + if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) + return SendIllFormedResponse( + packet, "Comma sep missing in M packet after byte length"); + + // Allocate the conversion buffer. + std::vector<uint8_t> buf(byte_count, 0); + if (buf.empty()) + return SendErrorResponse(0x78); + + // Convert the hex memory write contents to bytes. + StreamGDBRemote response; + const uint64_t convert_count = packet.GetHexBytes(buf, 0); + if (convert_count != byte_count) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": asked to write %" PRIu64 + " bytes, but only found %" PRIu64 " to convert.", + __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, + byte_count, convert_count); + return SendIllFormedResponse(packet, "M content byte length specified did " + "not match hex-encoded content " + "length"); + } + + // Write the process memory. + size_t bytes_written = 0; + Error error = m_debugged_process_sp->WriteMemory(write_addr, &buf[0], + byte_count, bytes_written); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": failed to write. Error: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, + error.AsCString()); + return SendErrorResponse(0x09); + } + + if (bytes_written == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes", + __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, + byte_count); + return SendErrorResponse(0x09); + } - return SendOKResponse (); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Currently only the NativeProcessProtocol knows if it can handle a qMemoryRegionInfoSupported - // request, but we're not guaranteed to be attached to a process. For now we'll assume the - // client only asks this when a process is being debugged. - - // Ensure we have a process running; otherwise, we can't figure this out - // since we won't have a NativeProcessProtocol. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } +GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Currently only the NativeProcessProtocol knows if it can handle a + // qMemoryRegionInfoSupported + // request, but we're not guaranteed to be attached to a process. For now + // we'll assume the + // client only asks this when a process is being debugged. + + // Ensure we have a process running; otherwise, we can't figure this out + // since we won't have a NativeProcessProtocol. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } - // Test if we can get any region back when asking for the region around NULL. - MemoryRegionInfo region_info; - const Error error = m_debugged_process_sp->GetMemoryRegionInfo (0, region_info); - if (error.Fail ()) - { - // We don't support memory region info collection for this NativeProcessProtocol. - return SendUnimplementedResponse (""); - } + // Test if we can get any region back when asking for the region around NULL. + MemoryRegionInfo region_info; + const Error error = + m_debugged_process_sp->GetMemoryRegionInfo(0, region_info); + if (error.Fail()) { + // We don't support memory region info collection for this + // NativeProcessProtocol. + return SendUnimplementedResponse(""); + } - return SendOKResponse(); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Ensure we have a process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } +GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Parse out the memory address. - packet.SetFilePos (strlen("qMemoryRegionInfo:")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); - - // Read the address. Punting on validation. - const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); - - StreamGDBRemote response; - - // Get the memory region info for the target address. - MemoryRegionInfo region_info; - const Error error = m_debugged_process_sp->GetMemoryRegionInfo (read_addr, region_info); - if (error.Fail ()) - { - // Return the error message. - - response.PutCString ("error:"); - response.PutCStringAsRawHex8 (error.AsCString ()); - response.PutChar (';'); - } - else - { - // Range start and size. - response.Printf ("start:%" PRIx64 ";size:%" PRIx64 ";", region_info.GetRange ().GetRangeBase (), region_info.GetRange ().GetByteSize ()); - - // Permissions. - if (region_info.GetReadable () || - region_info.GetWritable () || - region_info.GetExecutable ()) - { - // Write permissions info. - response.PutCString ("permissions:"); - - if (region_info.GetReadable ()) - response.PutChar ('r'); - if (region_info.GetWritable ()) - response.PutChar('w'); - if (region_info.GetExecutable()) - response.PutChar ('x'); - - response.PutChar (';'); - } - - // Name - ConstString name = region_info.GetName(); - if (name) - { - response.PutCString("name:"); - response.PutCStringAsRawHex8(name.AsCString()); - response.PutChar(';'); - } - } - - return SendPacketNoLock(response.GetString()); + // Ensure we have a process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out the memory address. + packet.SetFilePos(strlen("qMemoryRegionInfo:")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); + + // Read the address. Punting on validation. + const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); + + StreamGDBRemote response; + + // Get the memory region info for the target address. + MemoryRegionInfo region_info; + const Error error = + m_debugged_process_sp->GetMemoryRegionInfo(read_addr, region_info); + if (error.Fail()) { + // Return the error message. + + response.PutCString("error:"); + response.PutCStringAsRawHex8(error.AsCString()); + response.PutChar(';'); + } else { + // Range start and size. + response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";", + region_info.GetRange().GetRangeBase(), + region_info.GetRange().GetByteSize()); + + // Permissions. + if (region_info.GetReadable() || region_info.GetWritable() || + region_info.GetExecutable()) { + // Write permissions info. + response.PutCString("permissions:"); + + if (region_info.GetReadable()) + response.PutChar('r'); + if (region_info.GetWritable()) + response.PutChar('w'); + if (region_info.GetExecutable()) + response.PutChar('x'); + + response.PutChar(';'); + } + + // Name + ConstString name = region_info.GetName(); + if (name) { + response.PutCString("name:"); + response.PutCStringAsRawHex8(name.AsCString()); + response.PutChar(';'); + } + } + + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet) -{ - // Ensure we have a process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Parse out software or hardware breakpoint or watchpoint requested. - packet.SetFilePos (strlen("Z")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier"); - - bool want_breakpoint = true; - bool want_hardware = false; - uint32_t watch_flags = 0; - - const GDBStoppointType stoppoint_type = - GDBStoppointType(packet.GetS32 (eStoppointInvalid)); - switch (stoppoint_type) - { - case eBreakpointSoftware: - want_hardware = false; want_breakpoint = true; break; - case eBreakpointHardware: - want_hardware = true; want_breakpoint = true; break; - case eWatchpointWrite: - watch_flags = 1; - want_hardware = true; want_breakpoint = false; break; - case eWatchpointRead: - watch_flags = 2; - want_hardware = true; want_breakpoint = false; break; - case eWatchpointReadWrite: - watch_flags = 3; - want_hardware = true; want_breakpoint = false; break; - case eStoppointInvalid: - return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); - - } - - if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type"); - - // Parse out the stoppoint address. - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short Z packet, missing address"); - const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); - - if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address"); - - // Parse out the stoppoint size (i.e. size hint for opcode size). - const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (size == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument"); - - if (want_breakpoint) - { - // Try to set the breakpoint. - const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware); - if (error.Success ()) - return SendOKResponse (); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to set breakpoint: %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - return SendErrorResponse (0x09); - } - else - { - // Try to set the watchpoint. - const Error error = m_debugged_process_sp->SetWatchpoint ( - addr, size, watch_flags, want_hardware); - if (error.Success ()) - return SendOKResponse (); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to set watchpoint: %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - return SendErrorResponse (0x09); - } +GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { + // Ensure we have a process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out software or hardware breakpoint or watchpoint requested. + packet.SetFilePos(strlen("Z")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse( + packet, "Too short Z packet, missing software/hardware specifier"); + + bool want_breakpoint = true; + bool want_hardware = false; + uint32_t watch_flags = 0; + + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32(eStoppointInvalid)); + switch (stoppoint_type) { + case eBreakpointSoftware: + want_hardware = false; + want_breakpoint = true; + break; + case eBreakpointHardware: + want_hardware = true; + want_breakpoint = true; + break; + case eWatchpointWrite: + watch_flags = 1; + want_hardware = true; + want_breakpoint = false; + break; + case eWatchpointRead: + watch_flags = 2; + want_hardware = true; + want_breakpoint = false; + break; + case eWatchpointReadWrite: + watch_flags = 3; + want_hardware = true; + want_breakpoint = false; + break; + case eStoppointInvalid: + return SendIllFormedResponse( + packet, "Z packet had invalid software/hardware specifier"); + } + + if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') + return SendIllFormedResponse( + packet, "Malformed Z packet, expecting comma after stoppoint type"); + + // Parse out the stoppoint address. + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Too short Z packet, missing address"); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); + + if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') + return SendIllFormedResponse( + packet, "Malformed Z packet, expecting comma after address"); + + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = + packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); + if (size == std::numeric_limits<uint32_t>::max()) + return SendIllFormedResponse( + packet, "Malformed Z packet, failed to parse size argument"); + + if (want_breakpoint) { + // Try to set the breakpoint. + const Error error = + m_debugged_process_sp->SetBreakpoint(addr, size, want_hardware); + if (error.Success()) + return SendOKResponse(); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to set breakpoint: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x09); + } else { + // Try to set the watchpoint. + const Error error = m_debugged_process_sp->SetWatchpoint( + addr, size, watch_flags, want_hardware); + if (error.Success()) + return SendOKResponse(); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to set watchpoint: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x09); + } } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_z (StringExtractorGDBRemote &packet) -{ - // Ensure we have a process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - // Parse out software or hardware breakpoint or watchpoint requested. - packet.SetFilePos (strlen("z")); - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); - - bool want_breakpoint = true; - - const GDBStoppointType stoppoint_type = - GDBStoppointType(packet.GetS32 (eStoppointInvalid)); - switch (stoppoint_type) - { - case eBreakpointHardware: want_breakpoint = true; break; - case eBreakpointSoftware: want_breakpoint = true; break; - case eWatchpointWrite: want_breakpoint = false; break; - case eWatchpointRead: want_breakpoint = false; break; - case eWatchpointReadWrite: want_breakpoint = false; break; - default: - return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier"); - - } - - if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type"); - - // Parse out the stoppoint address. - if (packet.GetBytesLeft() < 1) - return SendIllFormedResponse(packet, "Too short z packet, missing address"); - const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); - - if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address"); - - /* - // Parse out the stoppoint size (i.e. size hint for opcode size). - const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (size == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument"); - */ - - if (want_breakpoint) - { - // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint (addr); - if (error.Success ()) - return SendOKResponse (); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to remove breakpoint: %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - return SendErrorResponse (0x09); - } - else - { - // Try to clear the watchpoint. - const Error error = m_debugged_process_sp->RemoveWatchpoint (addr); - if (error.Success ()) - return SendOKResponse (); - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " failed to remove watchpoint: %s", - __FUNCTION__, - m_debugged_process_sp->GetID (), - error.AsCString ()); - return SendErrorResponse (0x09); - } +GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { + // Ensure we have a process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + // Parse out software or hardware breakpoint or watchpoint requested. + packet.SetFilePos(strlen("z")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse( + packet, "Too short z packet, missing software/hardware specifier"); + + bool want_breakpoint = true; + + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32(eStoppointInvalid)); + switch (stoppoint_type) { + case eBreakpointHardware: + want_breakpoint = true; + break; + case eBreakpointSoftware: + want_breakpoint = true; + break; + case eWatchpointWrite: + want_breakpoint = false; + break; + case eWatchpointRead: + want_breakpoint = false; + break; + case eWatchpointReadWrite: + want_breakpoint = false; + break; + default: + return SendIllFormedResponse( + packet, "z packet had invalid software/hardware specifier"); + } + + if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') + return SendIllFormedResponse( + packet, "Malformed z packet, expecting comma after stoppoint type"); + + // Parse out the stoppoint address. + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, "Too short z packet, missing address"); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); + + if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') + return SendIllFormedResponse( + packet, "Malformed z packet, expecting comma after address"); + + /* + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, + std::numeric_limits<uint32_t>::max ()); + if (size == std::numeric_limits<uint32_t>::max ()) + return SendIllFormedResponse(packet, "Malformed z packet, failed to parse + size argument"); + */ + + if (want_breakpoint) { + // Try to clear the breakpoint. + const Error error = m_debugged_process_sp->RemoveBreakpoint(addr); + if (error.Success()) + return SendOKResponse(); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to remove breakpoint: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x09); + } else { + // Try to clear the watchpoint. + const Error error = m_debugged_process_sp->RemoveWatchpoint(addr); + if (error.Success()) + return SendOKResponse(); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to remove watchpoint: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x09); + } } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_s (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD)); - - // Ensure we have a process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x32); - } +GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - // We first try to use a continue thread id. If any one or any all set, use the current thread. - // Bail out if we don't have a thread id. - lldb::tid_t tid = GetContinueThreadID (); - if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) - tid = GetCurrentThreadID (); - if (tid == LLDB_INVALID_THREAD_ID) - return SendErrorResponse (0x33); - - // Double check that we have such a thread. - // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. - NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID (tid); - if (!thread_sp || thread_sp->GetID () != tid) - return SendErrorResponse (0x33); - - // Create the step action for the given thread. - ResumeAction action = { tid, eStateStepping, 0 }; - - // Setup the actions list. - ResumeActionList actions; - actions.Append (action); - - // All other threads stop while we're single stepping a thread. - actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - Error error = m_debugged_process_sp->Resume (actions); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), tid, error.AsCString ()); - return SendErrorResponse(0x49); - } + // Ensure we have a process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x32); + } + + // We first try to use a continue thread id. If any one or any all set, use + // the current thread. + // Bail out if we don't have a thread id. + lldb::tid_t tid = GetContinueThreadID(); + if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) + tid = GetCurrentThreadID(); + if (tid == LLDB_INVALID_THREAD_ID) + return SendErrorResponse(0x33); + + // Double check that we have such a thread. + // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. + NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID(tid); + if (!thread_sp || thread_sp->GetID() != tid) + return SendErrorResponse(0x33); + + // Create the step action for the given thread. + ResumeAction action = {tid, eStateStepping, 0}; + + // Setup the actions list. + ResumeActionList actions; + actions.Append(action); + + // All other threads stop while we're single stepping a thread. + actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); + Error error = m_debugged_process_sp->Resume(actions); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 " Resume() failed with error: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), tid, + error.AsCString()); + return SendErrorResponse(0x49); + } - // No response here - the stop or exit will come from the resulting action. - return PacketResult::Success; + // No response here - the stop or exit will come from the resulting action. + return PacketResult::Success; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet) -{ - // *BSD impls should be able to do this too. +GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( + StringExtractorGDBRemote &packet) { +// *BSD impls should be able to do this too. #if defined(__linux__) - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Parse out the offset. - packet.SetFilePos (strlen("qXfer:auxv:read::")); - if (packet.GetBytesLeft () < 1) - return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset"); - - const uint64_t auxv_offset = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ()); - if (auxv_offset == std::numeric_limits<uint64_t>::max ()) - return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset"); - - // Parse out comma. - if (packet.GetBytesLeft () < 1 || packet.GetChar () != ',') - return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing comma after offset"); - - // Parse out the length. - const uint64_t auxv_length = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ()); - if (auxv_length == std::numeric_limits<uint64_t>::max ()) - return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing length"); - - // Grab the auxv data if we need it. - if (!m_active_auxv_buffer_sp) - { - // Make sure we have a valid process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x10); - } - - // Grab the auxv data. - m_active_auxv_buffer_sp = Host::GetAuxvData (m_debugged_process_sp->GetID ()); - if (!m_active_auxv_buffer_sp || m_active_auxv_buffer_sp->GetByteSize () == 0) - { - // Hmm, no auxv data, call that an error. - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data retrieved", __FUNCTION__); - m_active_auxv_buffer_sp.reset (); - return SendErrorResponse (0x11); - } - } - - // FIXME find out if/how I lock the stream here. - - StreamGDBRemote response; - bool done_with_buffer = false; - - if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize ()) - { - // We have nothing left to send. Mark the buffer as complete. - response.PutChar ('l'); - done_with_buffer = true; - } - else - { - // Figure out how many bytes are available starting at the given offset. - const uint64_t bytes_remaining = m_active_auxv_buffer_sp->GetByteSize () - auxv_offset; - - // Figure out how many bytes we're going to read. - const uint64_t bytes_to_read = (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length; - - // Mark the response type according to whether we're reading the remainder of the auxv data. - if (bytes_to_read >= bytes_remaining) - { - // There will be nothing left to read after this - response.PutChar ('l'); - done_with_buffer = true; - } - else - { - // There will still be bytes to read after this request. - response.PutChar ('m'); - } - - // Now write the data in encoded binary form. - response.PutEscapedBytes (m_active_auxv_buffer_sp->GetBytes () + auxv_offset, bytes_to_read); - } - - if (done_with_buffer) - m_active_auxv_buffer_sp.reset (); - - return SendPacketNoLock(response.GetString()); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Parse out the offset. + packet.SetFilePos(strlen("qXfer:auxv:read::")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse(packet, + "qXfer:auxv:read:: packet missing offset"); + + const uint64_t auxv_offset = + packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); + if (auxv_offset == std::numeric_limits<uint64_t>::max()) + return SendIllFormedResponse(packet, + "qXfer:auxv:read:: packet missing offset"); + + // Parse out comma. + if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',') + return SendIllFormedResponse( + packet, "qXfer:auxv:read:: packet missing comma after offset"); + + // Parse out the length. + const uint64_t auxv_length = + packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); + if (auxv_length == std::numeric_limits<uint64_t>::max()) + return SendIllFormedResponse(packet, + "qXfer:auxv:read:: packet missing length"); + + // Grab the auxv data if we need it. + if (!m_active_auxv_buffer_sp) { + // Make sure we have a valid process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x10); + } + + // Grab the auxv data. + m_active_auxv_buffer_sp = Host::GetAuxvData(m_debugged_process_sp->GetID()); + if (!m_active_auxv_buffer_sp || + m_active_auxv_buffer_sp->GetByteSize() == 0) { + // Hmm, no auxv data, call that an error. + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data " + "retrieved", + __FUNCTION__); + m_active_auxv_buffer_sp.reset(); + return SendErrorResponse(0x11); + } + } + + // FIXME find out if/how I lock the stream here. + + StreamGDBRemote response; + bool done_with_buffer = false; + + if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize()) { + // We have nothing left to send. Mark the buffer as complete. + response.PutChar('l'); + done_with_buffer = true; + } else { + // Figure out how many bytes are available starting at the given offset. + const uint64_t bytes_remaining = + m_active_auxv_buffer_sp->GetByteSize() - auxv_offset; + + // Figure out how many bytes we're going to read. + const uint64_t bytes_to_read = + (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length; + + // Mark the response type according to whether we're reading the remainder + // of the auxv data. + if (bytes_to_read >= bytes_remaining) { + // There will be nothing left to read after this + response.PutChar('l'); + done_with_buffer = true; + } else { + // There will still be bytes to read after this request. + response.PutChar('m'); + } + + // Now write the data in encoded binary form. + response.PutEscapedBytes(m_active_auxv_buffer_sp->GetBytes() + auxv_offset, + bytes_to_read); + } + + if (done_with_buffer) + m_active_auxv_buffer_sp.reset(); + + return SendPacketNoLock(response.GetString()); #else - return SendUnimplementedResponse ("not implemented on this platform"); + return SendUnimplementedResponse("not implemented on this platform"); #endif } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Move past packet name. - packet.SetFilePos (strlen ("QSaveRegisterState")); - - // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); - if (!thread_sp) - { - if (m_thread_suffix_supported) - return SendIllFormedResponse (packet, "No thread specified in QSaveRegisterState packet"); - else - return SendIllFormedResponse (packet, "No thread was is set with the Hg packet"); - } - - // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ()); - if (!reg_context_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ()); - return SendErrorResponse (0x15); - } - - // Save registers to a buffer. - DataBufferSP register_data_sp; - Error error = reg_context_sp->ReadAllRegisterValues (register_data_sp); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to save all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x75); - } - - // Allocate a new save id. - const uint32_t save_id = GetNextSavedRegistersID (); - assert ((m_saved_registers_map.find (save_id) == m_saved_registers_map.end ()) && "GetNextRegisterSaveID() returned an existing register save id"); +GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Move past packet name. + packet.SetFilePos(strlen("QSaveRegisterState")); + + // Get the thread to use. + NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); + if (!thread_sp) { + if (m_thread_suffix_supported) + return SendIllFormedResponse( + packet, "No thread specified in QSaveRegisterState packet"); + else + return SendIllFormedResponse(packet, + "No thread was is set with the Hg packet"); + } - // Save the register data buffer under the save id. - { - std::lock_guard<std::mutex> guard(m_saved_registers_mutex); - m_saved_registers_map[save_id] = register_data_sp; - } + // Grab the register context for the thread. + NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); + if (!reg_context_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 + " failed, no register context available for the thread", + __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + return SendErrorResponse(0x15); + } + + // Save registers to a buffer. + DataBufferSP register_data_sp; + Error error = reg_context_sp->ReadAllRegisterValues(register_data_sp); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to save all register values: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x75); + } + + // Allocate a new save id. + const uint32_t save_id = GetNextSavedRegistersID(); + assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && + "GetNextRegisterSaveID() returned an existing register save id"); + + // Save the register data buffer under the save id. + { + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); + m_saved_registers_map[save_id] = register_data_sp; + } - // Write the response. - StreamGDBRemote response; - response.Printf ("%" PRIu32, save_id); - return SendPacketNoLock(response.GetString()); + // Write the response. + StreamGDBRemote response; + response.Printf("%" PRIu32, save_id); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - // Parse out save id. - packet.SetFilePos (strlen ("QRestoreRegisterState:")); - if (packet.GetBytesLeft () < 1) - return SendIllFormedResponse (packet, "QRestoreRegisterState packet missing register save id"); - - const uint32_t save_id = packet.GetU32 (0); - if (save_id == 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState packet has malformed save id, expecting decimal uint32_t", __FUNCTION__); - return SendErrorResponse (0x76); - } +GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Parse out save id. + packet.SetFilePos(strlen("QRestoreRegisterState:")); + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse( + packet, "QRestoreRegisterState packet missing register save id"); + + const uint32_t save_id = packet.GetU32(0); + if (save_id == 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState " + "packet has malformed save id, expecting decimal uint32_t", + __FUNCTION__); + return SendErrorResponse(0x76); + } + + // Get the thread to use. + NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); + if (!thread_sp) { + if (m_thread_suffix_supported) + return SendIllFormedResponse( + packet, "No thread specified in QRestoreRegisterState packet"); + else + return SendIllFormedResponse(packet, + "No thread was is set with the Hg packet"); + } - // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); - if (!thread_sp) - { - if (m_thread_suffix_supported) - return SendIllFormedResponse (packet, "No thread specified in QRestoreRegisterState packet"); - else - return SendIllFormedResponse (packet, "No thread was is set with the Hg packet"); - } + // Grab the register context for the thread. + NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); + if (!reg_context_sp) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 + " failed, no register context available for the thread", + __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); + return SendErrorResponse(0x15); + } + + // Retrieve register state buffer, then remove from the list. + DataBufferSP register_data_sp; + { + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); - // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ()); - if (!reg_context_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ()); - return SendErrorResponse (0x15); + // Find the register set buffer for the given save id. + auto it = m_saved_registers_map.find(save_id); + if (it == m_saved_registers_map.end()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " does not have a register set save buffer for id %" PRIu32, + __FUNCTION__, m_debugged_process_sp->GetID(), save_id); + return SendErrorResponse(0x77); } + register_data_sp = it->second; - // Retrieve register state buffer, then remove from the list. - DataBufferSP register_data_sp; - { - std::lock_guard<std::mutex> guard(m_saved_registers_mutex); + // Remove it from the map. + m_saved_registers_map.erase(it); + } - // Find the register set buffer for the given save id. - auto it = m_saved_registers_map.find (save_id); - if (it == m_saved_registers_map.end ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " does not have a register set save buffer for id %" PRIu32, __FUNCTION__, m_debugged_process_sp->GetID (), save_id); - return SendErrorResponse (0x77); - } - register_data_sp = it->second; - - // Remove it from the map. - m_saved_registers_map.erase (it); - } - - Error error = reg_context_sp->WriteAllRegisterValues (register_data_sp); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to restore all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x77); - } + Error error = reg_context_sp->WriteAllRegisterValues(register_data_sp); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " failed to restore all register values: %s", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x77); + } - return SendOKResponse(); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Consume the ';' after vAttach. - packet.SetFilePos (strlen ("vAttach")); - if (!packet.GetBytesLeft () || packet.GetChar () != ';') - return SendIllFormedResponse (packet, "vAttach missing expected ';'"); - - // Grab the PID to which we will attach (assume hex encoding). - lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16); - if (pid == LLDB_INVALID_PROCESS_ID) - return SendIllFormedResponse (packet, "vAttach failed to parse the process id"); - - // Attempt to attach. +GDBRemoteCommunicationServerLLGS::Handle_vAttach( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Consume the ';' after vAttach. + packet.SetFilePos(strlen("vAttach")); + if (!packet.GetBytesLeft() || packet.GetChar() != ';') + return SendIllFormedResponse(packet, "vAttach missing expected ';'"); + + // Grab the PID to which we will attach (assume hex encoding). + lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendIllFormedResponse(packet, + "vAttach failed to parse the process id"); + + // Attempt to attach. + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " + "pid %" PRIu64, + __FUNCTION__, pid); + + Error error = AttachToProcess(pid); + + if (error.Fail()) { if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s attempting to attach to pid %" PRIu64, __FUNCTION__, pid); - - Error error = AttachToProcess (pid); - - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to attach to pid %" PRIu64 ": %s\n", __FUNCTION__, pid, error.AsCString()); - return SendErrorResponse (0x01); - } + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, pid, error.AsCString()); + return SendErrorResponse(0x01); + } - // Notify we attached by sending a stop packet. - return SendStopReasonForState (m_debugged_process_sp->GetState ()); + // Notify we attached by sending a stop packet. + return SendStopReasonForState(m_debugged_process_sp->GetState()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); - - StopSTDIOForwarding(); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); - return SendErrorResponse (0x15); - } - - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; +GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Consume the ';' after D. - packet.SetFilePos (1); - if (packet.GetBytesLeft ()) - { - if (packet.GetChar () != ';') - return SendIllFormedResponse (packet, "D missing expected ';'"); + StopSTDIOForwarding(); - // Grab the PID from which we will detach (assume hex encoding). - pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16); - if (pid == LLDB_INVALID_PROCESS_ID) - return SendIllFormedResponse (packet, "D failed to parse the process id"); - } + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (log) + log->Printf( + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(0x15); + } + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + // Consume the ';' after D. + packet.SetFilePos(1); + if (packet.GetBytesLeft()) { + if (packet.GetChar() != ';') + return SendIllFormedResponse(packet, "D missing expected ';'"); + + // Grab the PID from which we will detach (assume hex encoding). + pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendIllFormedResponse(packet, "D failed to parse the process id"); + } - if (pid != LLDB_INVALID_PROCESS_ID && - m_debugged_process_sp->GetID () != pid) - { - return SendIllFormedResponse (packet, "Invalid pid"); - } + if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_sp->GetID() != pid) { + return SendIllFormedResponse(packet, "Invalid pid"); + } - const Error error = m_debugged_process_sp->Detach (); - if (error.Fail ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to detach from pid %" PRIu64 ": %s\n", - __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x01); - } + const Error error = m_debugged_process_sp->Detach(); + if (error.Fail()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, m_debugged_process_sp->GetID(), + error.AsCString()); + return SendErrorResponse(0x01); + } - return SendOKResponse (); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet) -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - - packet.SetFilePos (strlen("qThreadStopInfo")); - const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID); - if (tid == LLDB_INVALID_THREAD_ID) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ()); - return SendErrorResponse (0x15); - } - return SendStopReplyPacketForThread (tid); +GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + packet.SetFilePos(strlen("qThreadStopInfo")); + const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); + if (tid == LLDB_INVALID_THREAD_ID) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse thread id from request \"%s\"", + __FUNCTION__, packet.GetStringRef().c_str()); + return SendErrorResponse(0x15); + } + return SendStopReplyPacketForThread(tid); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - - // Ensure we have a debugged process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (50); - - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64, +GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( + StringExtractorGDBRemote &) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + + // Ensure we have a debugged process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(50); + + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid " + "%" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); + StreamString response; + const bool threads_with_valid_stop_info_only = false; + JSONArray::SP threads_array_sp = GetJSONThreadsInfo( + *m_debugged_process_sp, threads_with_valid_stop_info_only); + if (!threads_array_sp) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " + "packet for pid %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); + return SendErrorResponse(52); + } - StreamString response; - const bool threads_with_valid_stop_info_only = false; - JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp, - threads_with_valid_stop_info_only); - if (! threads_array_sp) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64, - __FUNCTION__, m_debugged_process_sp->GetID()); - return SendErrorResponse(52); - } - - threads_array_sp->Write(response); - StreamGDBRemote escaped_response; - escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); - return SendPacketNoLock (escaped_response.GetString()); + threads_array_sp->Write(response); + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet) -{ - // Fail if we don't have a current process. - if (!m_debugged_process_sp || - m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) - return SendErrorResponse (68); - - packet.SetFilePos(strlen("qWatchpointSupportInfo")); - if (packet.GetBytesLeft() == 0) - return SendOKResponse(); - if (packet.GetChar() != ':') - return SendErrorResponse(67); +GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(68); + + packet.SetFilePos(strlen("qWatchpointSupportInfo")); + if (packet.GetBytesLeft() == 0) + return SendOKResponse(); + if (packet.GetChar() != ':') + return SendErrorResponse(67); - uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); - StreamGDBRemote response; - response.Printf ("num:%d;", num); - return SendPacketNoLock(response.GetString()); + uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + StreamGDBRemote response; + response.Printf("num:%d;", num); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRemote &packet) -{ - // Fail if we don't have a current process. - if (!m_debugged_process_sp || - m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) - return SendErrorResponse(67); +GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(67); - packet.SetFilePos(strlen("qFileLoadAddress:")); - if (packet.GetBytesLeft() == 0) - return SendErrorResponse(68); + packet.SetFilePos(strlen("qFileLoadAddress:")); + if (packet.GetBytesLeft() == 0) + return SendErrorResponse(68); - std::string file_name; - packet.GetHexByteString(file_name); - - lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; - Error error = m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address); - if (error.Fail()) - return SendErrorResponse(69); + std::string file_name; + packet.GetHexByteString(file_name); - if (file_load_address == LLDB_INVALID_ADDRESS) - return SendErrorResponse(1); // File not loaded + lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; + Error error = + m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address); + if (error.Fail()) + return SendErrorResponse(69); - StreamGDBRemote response; - response.PutHex64(file_load_address); - return SendPacketNoLock(response.GetString()); -} + if (file_load_address == LLDB_INVALID_ADDRESS) + return SendErrorResponse(1); // File not loaded -void -GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection () -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Tell the stdio connection to shut down. - if (m_stdio_communication.IsConnected()) - { - auto connection = m_stdio_communication.GetConnection(); - if (connection) - { - Error error; - connection->Disconnect (&error); - - if (error.Success ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s disconnect process terminal stdio - SUCCESS", __FUNCTION__); - } - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s disconnect process terminal stdio - FAIL: %s", __FUNCTION__, error.AsCString ()); - } - } - } + StreamGDBRemote response; + response.PutHex64(file_load_address); + return SendPacketNoLock(response.GetString()); } +void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); -NativeThreadProtocolSP -GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix (StringExtractorGDBRemote &packet) -{ - NativeThreadProtocolSP thread_sp; + // Tell the stdio connection to shut down. + if (m_stdio_communication.IsConnected()) { + auto connection = m_stdio_communication.GetConnection(); + if (connection) { + Error error; + connection->Disconnect(&error); - // We have no thread if we don't have a process. - if (!m_debugged_process_sp || m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) - return thread_sp; - - // If the client hasn't asked for thread suffix support, there will not be a thread suffix. - // Use the current thread in that case. - if (!m_thread_suffix_supported) - { - const lldb::tid_t current_tid = GetCurrentThreadID (); - if (current_tid == LLDB_INVALID_THREAD_ID) - return thread_sp; - else if (current_tid == 0) - { - // Pick a thread. - return m_debugged_process_sp->GetThreadAtIndex (0); - } - else - return m_debugged_process_sp->GetThreadByID (current_tid); + if (error.Success()) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - SUCCESS", + __FUNCTION__); + } else { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - FAIL: %s", + __FUNCTION__, error.AsCString()); + } } + } +} - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); +NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( + StringExtractorGDBRemote &packet) { + NativeThreadProtocolSP thread_sp; - // Parse out the ';'. - if (packet.GetBytesLeft () < 1 || packet.GetChar () != ';') - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected ';' prior to start of thread suffix: packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ()); - return thread_sp; - } + // We have no thread if we don't have a process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) + return thread_sp; - if (!packet.GetBytesLeft ()) - return thread_sp; + // If the client hasn't asked for thread suffix support, there will not be a + // thread suffix. + // Use the current thread in that case. + if (!m_thread_suffix_supported) { + const lldb::tid_t current_tid = GetCurrentThreadID(); + if (current_tid == LLDB_INVALID_THREAD_ID) + return thread_sp; + else if (current_tid == 0) { + // Pick a thread. + return m_debugged_process_sp->GetThreadAtIndex(0); + } else + return m_debugged_process_sp->GetThreadByID(current_tid); + } + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Parse out the ';'. + if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected ';' prior to start of thread suffix: packet " + "contents = '%s'", + __FUNCTION__, packet.GetStringRef().c_str()); + return thread_sp; + } - // Parse out thread: portion. - if (strncmp (packet.Peek (), "thread:", strlen("thread:")) != 0) - { - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected 'thread:' but not found, packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ()); - return thread_sp; - } - packet.SetFilePos (packet.GetFilePos () + strlen("thread:")); - const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); - if (tid != 0) - return m_debugged_process_sp->GetThreadByID (tid); + if (!packet.GetBytesLeft()) + return thread_sp; + // Parse out thread: portion. + if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected 'thread:' but not found, packet contents = " + "'%s'", + __FUNCTION__, packet.GetStringRef().c_str()); return thread_sp; + } + packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); + const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); + if (tid != 0) + return m_debugged_process_sp->GetThreadByID(tid); + + return thread_sp; } -lldb::tid_t -GDBRemoteCommunicationServerLLGS::GetCurrentThreadID () const -{ - if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) - { - // Use whatever the debug process says is the current thread id - // since the protocol either didn't specify or specified we want - // any/all threads marked as the current thread. - if (!m_debugged_process_sp) - return LLDB_INVALID_THREAD_ID; - return m_debugged_process_sp->GetCurrentThreadID (); - } - // Use the specific current thread id set by the gdb remote protocol. - return m_current_tid; +lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { + if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) { + // Use whatever the debug process says is the current thread id + // since the protocol either didn't specify or specified we want + // any/all threads marked as the current thread. + if (!m_debugged_process_sp) + return LLDB_INVALID_THREAD_ID; + return m_debugged_process_sp->GetCurrentThreadID(); + } + // Use the specific current thread id set by the gdb remote protocol. + return m_current_tid; } -uint32_t -GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID () -{ - std::lock_guard<std::mutex> guard(m_saved_registers_mutex); - return m_next_saved_registers_id++; +uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); + return m_next_saved_registers_id++; } -void -GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData () -{ - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|GDBR_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__); +void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | GDBR_LOG_PROCESS)); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__); - // Clear any auxv cached data. - // *BSD impls should be able to do this too. +// Clear any auxv cached data. +// *BSD impls should be able to do this too. #if defined(__linux__) - if (log) - log->Printf ("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer (previously %s)", - __FUNCTION__, - m_active_auxv_buffer_sp ? "was set" : "was not set"); - m_active_auxv_buffer_sp.reset (); + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer " + "(previously %s)", + __FUNCTION__, + m_active_auxv_buffer_sp ? "was set" : "was not set"); + m_active_auxv_buffer_sp.reset(); #endif } FileSpec -GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string& module_path, - const ArchSpec& arch) -{ - if (m_debugged_process_sp) - { - FileSpec file_spec; - if (m_debugged_process_sp->GetLoadedModuleFileSpec(module_path.c_str(), file_spec).Success()) - { - if (file_spec.Exists()) - return file_spec; - } - } - - return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); +GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, + const ArchSpec &arch) { + if (m_debugged_process_sp) { + FileSpec file_spec; + if (m_debugged_process_sp + ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) + .Success()) { + if (file_spec.Exists()) + return file_spec; + } + } + + return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index caf6eb319e6..fa52cdaab49 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -16,10 +16,10 @@ #include <unordered_map> // Other libraries and framework includes -#include "lldb/lldb-private-forward.h" #include "lldb/Core/Communication.h" -#include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/MainLoop.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/lldb-private-forward.h" // Project includes #include "GDBRemoteCommunicationServerCommon.h" @@ -32,282 +32,220 @@ namespace process_gdb_remote { class ProcessGDBRemote; -class GDBRemoteCommunicationServerLLGS : - public GDBRemoteCommunicationServerCommon, - public NativeProcessProtocol::NativeDelegate -{ +class GDBRemoteCommunicationServerLLGS + : public GDBRemoteCommunicationServerCommon, + public NativeProcessProtocol::NativeDelegate { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); - - //------------------------------------------------------------------ - /// Specify the program to launch and its arguments. - /// - /// @param[in] args - /// The command line to launch. - /// - /// @param[in] argc - /// The number of elements in the args array of cstring pointers. - /// - /// @return - /// An Error object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Error - SetLaunchArguments (const char *const args[], int argc); - - //------------------------------------------------------------------ - /// Specify the launch flags for the process. - /// - /// @param[in] launch_flags - /// The launch flags to use when launching this process. - /// - /// @return - /// An Error object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Error - SetLaunchFlags (unsigned int launch_flags); - - //------------------------------------------------------------------ - /// Launch a process with the current launch settings. - /// - /// This method supports running an lldb-gdbserver or similar - /// server in a situation where the startup code has been provided - /// with all the information for a child process to be launched. - /// - /// @return - /// An Error object indicating the success or failure of the - /// launch. - //------------------------------------------------------------------ - Error - LaunchProcess () override; - - //------------------------------------------------------------------ - /// Attach to a process. - /// - /// This method supports attaching llgs to a process accessible via the - /// configured Platform. - /// - /// @return - /// An Error object indicating the success or failure of the - /// attach operation. - //------------------------------------------------------------------ - Error - AttachToProcess (lldb::pid_t pid); - - //------------------------------------------------------------------ - // NativeProcessProtocol::NativeDelegate overrides - //------------------------------------------------------------------ - void - InitializeDelegate (NativeProcessProtocol *process) override; - - void - ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) override; - - void - DidExec (NativeProcessProtocol *process) override; - - Error - InitializeConnection (std::unique_ptr<Connection> &&connection); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); + + //------------------------------------------------------------------ + /// Specify the program to launch and its arguments. + /// + /// @param[in] args + /// The command line to launch. + /// + /// @param[in] argc + /// The number of elements in the args array of cstring pointers. + /// + /// @return + /// An Error object indicating the success or failure of making + /// the setting. + //------------------------------------------------------------------ + Error SetLaunchArguments(const char *const args[], int argc); + + //------------------------------------------------------------------ + /// Specify the launch flags for the process. + /// + /// @param[in] launch_flags + /// The launch flags to use when launching this process. + /// + /// @return + /// An Error object indicating the success or failure of making + /// the setting. + //------------------------------------------------------------------ + Error SetLaunchFlags(unsigned int launch_flags); + + //------------------------------------------------------------------ + /// Launch a process with the current launch settings. + /// + /// This method supports running an lldb-gdbserver or similar + /// server in a situation where the startup code has been provided + /// with all the information for a child process to be launched. + /// + /// @return + /// An Error object indicating the success or failure of the + /// launch. + //------------------------------------------------------------------ + Error LaunchProcess() override; + + //------------------------------------------------------------------ + /// Attach to a process. + /// + /// This method supports attaching llgs to a process accessible via the + /// configured Platform. + /// + /// @return + /// An Error object indicating the success or failure of the + /// attach operation. + //------------------------------------------------------------------ + Error AttachToProcess(lldb::pid_t pid); + + //------------------------------------------------------------------ + // NativeProcessProtocol::NativeDelegate overrides + //------------------------------------------------------------------ + void InitializeDelegate(NativeProcessProtocol *process) override; + + void ProcessStateChanged(NativeProcessProtocol *process, + lldb::StateType state) override; + + void DidExec(NativeProcessProtocol *process) override; + + Error InitializeConnection(std::unique_ptr<Connection> &&connection); protected: - MainLoop &m_mainloop; - MainLoop::ReadHandleUP m_network_handle_up; - lldb::tid_t m_current_tid; - lldb::tid_t m_continue_tid; - std::recursive_mutex m_debugged_process_mutex; - NativeProcessProtocolSP m_debugged_process_sp; + MainLoop &m_mainloop; + MainLoop::ReadHandleUP m_network_handle_up; + lldb::tid_t m_current_tid; + lldb::tid_t m_continue_tid; + std::recursive_mutex m_debugged_process_mutex; + NativeProcessProtocolSP m_debugged_process_sp; - Communication m_stdio_communication; - MainLoop::ReadHandleUP m_stdio_handle_up; + Communication m_stdio_communication; + MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state; - lldb::DataBufferSP m_active_auxv_buffer_sp; - std::mutex m_saved_registers_mutex; - std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; - uint32_t m_next_saved_registers_id; - bool m_handshake_completed : 1; + lldb::StateType m_inferior_prev_state; + lldb::DataBufferSP m_active_auxv_buffer_sp; + std::mutex m_saved_registers_mutex; + std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; + uint32_t m_next_saved_registers_id; + bool m_handshake_completed : 1; - PacketResult - SendONotification (const char *buffer, uint32_t len); + PacketResult SendONotification(const char *buffer, uint32_t len); - PacketResult - SendWResponse (NativeProcessProtocol *process); + PacketResult SendWResponse(NativeProcessProtocol *process); - PacketResult - SendStopReplyPacketForThread (lldb::tid_t tid); + PacketResult SendStopReplyPacketForThread(lldb::tid_t tid); - PacketResult - SendStopReasonForState (lldb::StateType process_state); + PacketResult SendStopReasonForState(lldb::StateType process_state); - PacketResult - Handle_k (StringExtractorGDBRemote &packet); + PacketResult Handle_k(StringExtractorGDBRemote &packet); - PacketResult - Handle_qProcessInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qC (StringExtractorGDBRemote &packet); + PacketResult Handle_qC(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetDisableASLR (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetDisableASLR(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetWorkingDir (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet); - PacketResult - Handle_qGetWorkingDir (StringExtractorGDBRemote &packet); + PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); - PacketResult - Handle_C (StringExtractorGDBRemote &packet); + PacketResult Handle_C(StringExtractorGDBRemote &packet); - PacketResult - Handle_c (StringExtractorGDBRemote &packet); + PacketResult Handle_c(StringExtractorGDBRemote &packet); - PacketResult - Handle_vCont (StringExtractorGDBRemote &packet); + PacketResult Handle_vCont(StringExtractorGDBRemote &packet); - PacketResult - Handle_vCont_actions (StringExtractorGDBRemote &packet); + PacketResult Handle_vCont_actions(StringExtractorGDBRemote &packet); - PacketResult - Handle_stop_reason (StringExtractorGDBRemote &packet); + PacketResult Handle_stop_reason(StringExtractorGDBRemote &packet); - PacketResult - Handle_qRegisterInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qRegisterInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qfThreadInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qfThreadInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qsThreadInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qsThreadInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_p (StringExtractorGDBRemote &packet); + PacketResult Handle_p(StringExtractorGDBRemote &packet); - PacketResult - Handle_P (StringExtractorGDBRemote &packet); + PacketResult Handle_P(StringExtractorGDBRemote &packet); - PacketResult - Handle_H (StringExtractorGDBRemote &packet); + PacketResult Handle_H(StringExtractorGDBRemote &packet); - PacketResult - Handle_I (StringExtractorGDBRemote &packet); + PacketResult Handle_I(StringExtractorGDBRemote &packet); - PacketResult - Handle_interrupt (StringExtractorGDBRemote &packet); + PacketResult Handle_interrupt(StringExtractorGDBRemote &packet); - // Handles $m and $x packets. - PacketResult - Handle_memory_read (StringExtractorGDBRemote &packet); + // Handles $m and $x packets. + PacketResult Handle_memory_read(StringExtractorGDBRemote &packet); - PacketResult - Handle_M (StringExtractorGDBRemote &packet); + PacketResult Handle_M(StringExtractorGDBRemote &packet); - PacketResult - Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet); + PacketResult + Handle_qMemoryRegionInfoSupported(StringExtractorGDBRemote &packet); - PacketResult - Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qMemoryRegionInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_Z (StringExtractorGDBRemote &packet); + PacketResult Handle_Z(StringExtractorGDBRemote &packet); - PacketResult - Handle_z (StringExtractorGDBRemote &packet); + PacketResult Handle_z(StringExtractorGDBRemote &packet); - PacketResult - Handle_s (StringExtractorGDBRemote &packet); + PacketResult Handle_s(StringExtractorGDBRemote &packet); - PacketResult - Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet); + PacketResult Handle_qXfer_auxv_read(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSaveRegisterState (StringExtractorGDBRemote &packet); + PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); - PacketResult - Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet); + PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); - PacketResult - Handle_vAttach (StringExtractorGDBRemote &packet); + PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); - PacketResult - Handle_D (StringExtractorGDBRemote &packet); + PacketResult Handle_D(StringExtractorGDBRemote &packet); - PacketResult - Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_jThreadsInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_jThreadsInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qWatchpointSupportInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qFileLoadAddress (StringExtractorGDBRemote &packet); + PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet); - void - SetCurrentThreadID (lldb::tid_t tid); + void SetCurrentThreadID(lldb::tid_t tid); - lldb::tid_t - GetCurrentThreadID () const; + lldb::tid_t GetCurrentThreadID() const; - void - SetContinueThreadID (lldb::tid_t tid); + void SetContinueThreadID(lldb::tid_t tid); - lldb::tid_t - GetContinueThreadID () const { return m_continue_tid; } + lldb::tid_t GetContinueThreadID() const { return m_continue_tid; } - Error - SetSTDIOFileDescriptor (int fd); + Error SetSTDIOFileDescriptor(int fd); - FileSpec - FindModuleFile (const std::string& module_path, const ArchSpec& arch) override; + FileSpec FindModuleFile(const std::string &module_path, + const ArchSpec &arch) override; private: - void - HandleInferiorState_Exited (NativeProcessProtocol *process); + void HandleInferiorState_Exited(NativeProcessProtocol *process); - void - HandleInferiorState_Stopped (NativeProcessProtocol *process); + void HandleInferiorState_Stopped(NativeProcessProtocol *process); - NativeThreadProtocolSP - GetThreadFromSuffix (StringExtractorGDBRemote &packet); + NativeThreadProtocolSP GetThreadFromSuffix(StringExtractorGDBRemote &packet); - uint32_t - GetNextSavedRegistersID (); + uint32_t GetNextSavedRegistersID(); - void - MaybeCloseInferiorTerminalConnection (); + void MaybeCloseInferiorTerminalConnection(); - void - ClearProcessSpecificData (); + void ClearProcessSpecificData(); - void - RegisterPacketHandlers (); + void RegisterPacketHandlers(); - void - DataAvailableCallback (); + void DataAvailableCallback(); - void - SendProcessOutput (); + void SendProcessOutput(); - void - StartSTDIOForwarding(); + void StartSTDIOForwarding(); - void - StopSTDIOForwarding(); + void StopSTDIOForwarding(); - //------------------------------------------------------------------ - // For GDBRemoteCommunicationServerLLGS only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerLLGS); + //------------------------------------------------------------------ + // For GDBRemoteCommunicationServerLLGS only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerLLGS); }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_ +#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index c9baed7b119..80d6b8a756d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -13,8 +13,8 @@ // C Includes // C++ Includes -#include <cstring> #include <chrono> +#include <cstring> #include <mutex> #include <sstream> @@ -47,550 +47,524 @@ using namespace lldb_private::process_gdb_remote; //---------------------------------------------------------------------- // GDBRemoteCommunicationServerPlatform constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, - const char *socket_scheme) - : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_socket_protocol(socket_protocol), - m_socket_scheme(socket_scheme), - m_spawned_pids_mutex(), - m_port_map(), - m_port_offset(0) -{ - m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; - m_pending_gdb_server.port = 0; - - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, - &GDBRemoteCommunicationServerPlatform::Handle_qC); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, - &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer, - &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, - &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, - &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo, - &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, - &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); - RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo, - &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); - - RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, - [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) { - error.SetErrorString("interrupt received"); - interrupt = true; - return PacketResult::Success; - }); +GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( + const Socket::SocketProtocol socket_protocol, const char *socket_scheme) + : GDBRemoteCommunicationServerCommon("gdb-remote.server", + "gdb-remote.server.rx_packet"), + m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme), + m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) { + m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; + m_pending_gdb_server.port = 0; + + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qC, + &GDBRemoteCommunicationServerPlatform::Handle_qC); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, + &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer, + &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, + &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, + &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qProcessInfo, + &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, + &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jSignalsInfo, + &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); + + RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, + [this](StringExtractorGDBRemote packet, Error &error, + bool &interrupt, bool &quit) { + error.SetErrorString("interrupt received"); + interrupt = true; + return PacketResult::Success; + }); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() -{ -} - -Error -GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args, - std::string hostname, - lldb::pid_t& pid, - uint16_t& port, - std::string& socket_name) -{ - if (port == UINT16_MAX) - port = GetNextAvailablePort(); - - // Spawn a new thread to accept the port that gets bound after - // binding to port 0 (zero). - - // ignore the hostname send from the remote end, just use the ip address - // that we're currently communicating with as the hostname - - // Spawn a debugserver and try to get the port it listens to. - ProcessLaunchInfo debugserver_launch_info; - if (hostname.empty()) - hostname = "127.0.0.1"; - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); - - // Do not run in a new session so that it can not linger after the - // platform closes. - debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); - debugserver_launch_info.SetMonitorProcessCallback( - std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false); - - std::string platform_scheme; - std::string platform_ip; - int platform_port; - std::string platform_path; - bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); - UNUSED_IF_ASSERT_DISABLED(ok); - assert(ok); - - std::ostringstream url; - // debugserver does not accept the URL scheme prefix. +GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {} + +Error GDBRemoteCommunicationServerPlatform::LaunchGDBServer( + const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, + uint16_t &port, std::string &socket_name) { + if (port == UINT16_MAX) + port = GetNextAvailablePort(); + + // Spawn a new thread to accept the port that gets bound after + // binding to port 0 (zero). + + // ignore the hostname send from the remote end, just use the ip address + // that we're currently communicating with as the hostname + + // Spawn a debugserver and try to get the port it listens to. + ProcessLaunchInfo debugserver_launch_info; + if (hostname.empty()) + hostname = "127.0.0.1"; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); + + // Do not run in a new session so that it can not linger after the + // platform closes. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); + debugserver_launch_info.SetMonitorProcessCallback( + std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, + this, std::placeholders::_1), + false); + + std::string platform_scheme; + std::string platform_ip; + int platform_port; + std::string platform_path; + bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, + platform_ip, platform_port, platform_path); + UNUSED_IF_ASSERT_DISABLED(ok); + assert(ok); + + std::ostringstream url; +// debugserver does not accept the URL scheme prefix. #if !defined(__APPLE__) - url << m_socket_scheme << "://"; + url << m_socket_scheme << "://"; #endif - uint16_t* port_ptr = &port; - if (m_socket_protocol == Socket::ProtocolTcp) - url << platform_ip << ":" << port; - else - { - socket_name = GetDomainSocketPath("gdbserver").GetPath(); - url << socket_name; - port_ptr = nullptr; - } - - Error error = StartDebugserverProcess (url.str().c_str(), - nullptr, - debugserver_launch_info, - port_ptr, - &args, - -1); - - pid = debugserver_launch_info.GetProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - if (port > 0) - AssociatePortWithProcess(port, pid); - } - else - { - if (port > 0) - FreePort(port); - } - return error; + uint16_t *port_ptr = &port; + if (m_socket_protocol == Socket::ProtocolTcp) + url << platform_ip << ":" << port; + else { + socket_name = GetDomainSocketPath("gdbserver").GetPath(); + url << socket_name; + port_ptr = nullptr; + } + + Error error = StartDebugserverProcess( + url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1); + + pid = debugserver_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + m_spawned_pids.insert(pid); + if (port > 0) + AssociatePortWithProcess(port, pid); + } else { + if (port > 0) + FreePort(port); + } + return error; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) -{ +GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( + StringExtractorGDBRemote &packet) { #ifdef _WIN32 - return SendErrorResponse(9); + return SendErrorResponse(9); #else - // Spawn a local debugserver as a platform so we can then attach or launch - // a process... - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); + // Spawn a local debugserver as a platform so we can then attach or launch + // a process... + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("GDBRemoteCommunicationServerPlatform::%s() called", + __FUNCTION__); + + ConnectionFileDescriptor file_conn; + std::string hostname; + packet.SetFilePos(::strlen("qLaunchGDBServer;")); + llvm::StringRef name; + llvm::StringRef value; + uint16_t port = UINT16_MAX; + while (packet.GetNameColonValue(name, value)) { + if (name.equals("host")) + hostname = value; + else if (name.equals("port")) + value.getAsInteger(0, port); + } + + lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; + std::string socket_name; + Error error = + LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); + if (error.Fail()) { if (log) - log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); - - ConnectionFileDescriptor file_conn; - std::string hostname; - packet.SetFilePos(::strlen ("qLaunchGDBServer;")); - llvm::StringRef name; - llvm::StringRef value; - uint16_t port = UINT16_MAX; - while (packet.GetNameColonValue(name, value)) - { - if (name.equals("host")) - hostname = value; - else if (name.equals("port")) - value.getAsInteger(0, port); - } - - lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; - std::string socket_name; - Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); - if (error.Fail()) - { - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); - return SendErrorResponse(9); - } - - if (log) - log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); - - StreamGDBRemote response; - response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); - if (!socket_name.empty()) - { - response.PutCString("socket_name:"); - response.PutCStringAsRawHex8(socket_name.c_str()); - response.PutChar(';'); - } - - PacketResult packet_result = SendPacketNoLock(response.GetString()); - if (packet_result != PacketResult::Success) - { - if (debugserver_pid != LLDB_INVALID_PROCESS_ID) - ::kill (debugserver_pid, SIGINT); - } - return packet_result; + log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launch failed: %s", + __FUNCTION__, error.AsCString()); + return SendErrorResponse(9); + } + + if (log) + log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launched successfully as pid %" PRIu64, + __FUNCTION__, debugserver_pid); + + StreamGDBRemote response; + response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, + port + m_port_offset); + if (!socket_name.empty()) { + response.PutCString("socket_name:"); + response.PutCStringAsRawHex8(socket_name.c_str()); + response.PutChar(';'); + } + + PacketResult packet_result = SendPacketNoLock(response.GetString()); + if (packet_result != PacketResult::Success) { + if (debugserver_pid != LLDB_INVALID_PROCESS_ID) + ::kill(debugserver_pid, SIGINT); + } + return packet_result; #endif } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet) -{ - if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) - return SendErrorResponse(4); - - JSONObject::SP server_sp = std::make_shared<JSONObject>(); - server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port)); - if (!m_pending_gdb_server.socket_name.empty()) - server_sp->SetObject("socket_name", - std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); - - JSONArray server_list; - server_list.AppendObject(server_sp); - - StreamGDBRemote response; - server_list.Write(response); - - StreamGDBRemote escaped_response; - escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); - return SendPacketNoLock(escaped_response.GetString()); +GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( + StringExtractorGDBRemote &packet) { + if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(4); + + JSONObject::SP server_sp = std::make_shared<JSONObject>(); + server_sp->SetObject("port", + std::make_shared<JSONNumber>(m_pending_gdb_server.port)); + if (!m_pending_gdb_server.socket_name.empty()) + server_sp->SetObject( + "socket_name", + std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); + + JSONArray server_list; + server_list.AppendObject(server_sp); + + StreamGDBRemote response; + server_list.Write(response); + + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); +GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qKillSpawnedProcess:")); - lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); + lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); - // verify that we know anything about this pid. - // Scope for locker - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - { - // not a pid we know about - return SendErrorResponse (10); - } + // verify that we know anything about this pid. + // Scope for locker + { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { + // not a pid we know about + return SendErrorResponse(10); } + } - // go ahead and attempt to kill the spawned process - if (KillSpawnedProcess (pid)) - return SendOKResponse (); - else - return SendErrorResponse (11); + // go ahead and attempt to kill the spawned process + if (KillSpawnedProcess(pid)) + return SendOKResponse(); + else + return SendErrorResponse(11); } -bool -GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) -{ - // make sure we know about this process - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return false; - } +bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { + // make sure we know about this process + { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return false; + } - // first try a SIGTERM (standard kill) - Host::Kill (pid, SIGTERM); + // first try a SIGTERM (standard kill) + Host::Kill(pid, SIGTERM); - // check if that worked - for (size_t i=0; i<10; ++i) + // check if that worked + for (size_t i = 0; i < 10; ++i) { { - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - { - // it is now killed - return true; - } - } - usleep (10000); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { + // it is now killed + return true; + } } + usleep(10000); + } - // check one more time after the final usleep - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return true; - } + // check one more time after the final usleep + { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return true; + } - // the launched process still lives. Now try killing it again, - // this time with an unblockable signal. - Host::Kill (pid, SIGKILL); + // the launched process still lives. Now try killing it again, + // this time with an unblockable signal. + Host::Kill(pid, SIGKILL); - for (size_t i=0; i<10; ++i) + for (size_t i = 0; i < 10; ++i) { { - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - { - // it is now killed - return true; - } - } - usleep (10000); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { + // it is now killed + return true; + } } + usleep(10000); + } - // check one more time after the final usleep - // Scope for locker - { - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return true; - } + // check one more time after the final usleep + // Scope for locker + { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + if (m_spawned_pids.find(pid) == m_spawned_pids.end()) + return true; + } - // no luck - the process still lives - return false; + // no luck - the process still lives + return false; } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet) -{ - lldb::pid_t pid = m_process_launch_info.GetProcessID (); - m_process_launch_info.Clear (); +GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo( + StringExtractorGDBRemote &packet) { + lldb::pid_t pid = m_process_launch_info.GetProcessID(); + m_process_launch_info.Clear(); - if (pid == LLDB_INVALID_PROCESS_ID) - return SendErrorResponse (1); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(1); - ProcessInstanceInfo proc_info; - if (!Host::GetProcessInfo (pid, proc_info)) - return SendErrorResponse (1); + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo(pid, proc_info)) + return SendErrorResponse(1); - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetString()); + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) -{ - // If this packet is sent to a platform, then change the current working directory - - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd)) == NULL) - return SendErrorResponse(errno); - - StreamString response; - response.PutBytesAsRawHex8(cwd, strlen(cwd)); - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir( + StringExtractorGDBRemote &packet) { + // If this packet is sent to a platform, then change the current working + // directory + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + return SendErrorResponse(errno); + + StreamString response; + response.PutBytesAsRawHex8(cwd, strlen(cwd)); + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) -{ - packet.SetFilePos (::strlen ("QSetWorkingDir:")); - std::string path; - packet.GetHexByteString (path); - - // If this packet is sent to a platform, then change the current working directory - if (::chdir(path.c_str()) != 0) - return SendErrorResponse (errno); - return SendOKResponse (); +GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("QSetWorkingDir:")); + std::string path; + packet.GetHexByteString(path); + + // If this packet is sent to a platform, then change the current working + // directory + if (::chdir(path.c_str()) != 0) + return SendErrorResponse(errno); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet) -{ - // NOTE: lldb should now be using qProcessInfo for process IDs. This path here - // should not be used. It is reporting process id instead of thread id. The - // correct answer doesn't seem to make much sense for lldb-platform. - // CONSIDER: flip to "unsupported". - lldb::pid_t pid = m_process_launch_info.GetProcessID(); - - StreamString response; - response.Printf("QC%" PRIx64, pid); - - // If we launch a process and this GDB server is acting as a platform, - // then we need to clear the process launch state so we can start - // launching another process. In order to launch a process a bunch or - // packets need to be sent: environment packets, working directory, - // disable ASLR, and many more settings. When we launch a process we - // then need to know when to clear this information. Currently we are - // selecting the 'qC' packet as that packet which seems to make the most - // sense. - if (pid != LLDB_INVALID_PROCESS_ID) - { - m_process_launch_info.Clear(); - } - - return SendPacketNoLock (response.GetString()); +GDBRemoteCommunicationServerPlatform::Handle_qC( + StringExtractorGDBRemote &packet) { + // NOTE: lldb should now be using qProcessInfo for process IDs. This path + // here + // should not be used. It is reporting process id instead of thread id. The + // correct answer doesn't seem to make much sense for lldb-platform. + // CONSIDER: flip to "unsupported". + lldb::pid_t pid = m_process_launch_info.GetProcessID(); + + StreamString response; + response.Printf("QC%" PRIx64, pid); + + // If we launch a process and this GDB server is acting as a platform, + // then we need to clear the process launch state so we can start + // launching another process. In order to launch a process a bunch or + // packets need to be sent: environment packets, working directory, + // disable ASLR, and many more settings. When we launch a process we + // then need to know when to clear this information. Currently we are + // selecting the 'qC' packet as that packet which seems to make the most + // sense. + if (pid != LLDB_INVALID_PROCESS_ID) { + m_process_launch_info.Clear(); + } + + return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet) -{ - StructuredData::Array signal_array; - - const auto &signals = Host::GetUnixSignals(); - for (auto signo = signals->GetFirstSignalNumber(); - signo != LLDB_INVALID_SIGNAL_NUMBER; - signo = signals->GetNextSignalNumber(signo)) - { - auto dictionary = std::make_shared<StructuredData::Dictionary>(); - - dictionary->AddIntegerItem("signo", signo); - dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); - - bool suppress, stop, notify; - signals->GetSignalInfo(signo, suppress, stop, notify); - dictionary->AddBooleanItem("suppress", suppress); - dictionary->AddBooleanItem("stop", stop); - dictionary->AddBooleanItem("notify", notify); - - signal_array.Push(dictionary); - } - - StreamString response; - signal_array.Dump(response); - return SendPacketNoLock(response.GetString()); +GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo( + StringExtractorGDBRemote &packet) { + StructuredData::Array signal_array; + + const auto &signals = Host::GetUnixSignals(); + for (auto signo = signals->GetFirstSignalNumber(); + signo != LLDB_INVALID_SIGNAL_NUMBER; + signo = signals->GetNextSignalNumber(signo)) { + auto dictionary = std::make_shared<StructuredData::Dictionary>(); + + dictionary->AddIntegerItem("signo", signo); + dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); + + bool suppress, stop, notify; + signals->GetSignalInfo(signo, suppress, stop, notify); + dictionary->AddBooleanItem("suppress", suppress); + dictionary->AddBooleanItem("stop", stop); + dictionary->AddBooleanItem("notify", notify); + + signal_array.Push(dictionary); + } + + StreamString response; + signal_array.Dump(response); + return SendPacketNoLock(response.GetString()); } -bool -GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid) -{ - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - FreePortForProcess(pid); - m_spawned_pids.erase(pid); - return true; +bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped( + lldb::pid_t pid) { + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + FreePortForProcess(pid); + m_spawned_pids.erase(pid); + return true; } -Error -GDBRemoteCommunicationServerPlatform::LaunchProcess () -{ - if (!m_process_launch_info.GetArguments ().GetArgumentCount ()) - return Error ("%s: no process command line specified to launch", __FUNCTION__); - - // specify the process monitor if not already set. This should - // generally be what happens since we need to reap started - // processes. - if (!m_process_launch_info.GetMonitorProcessCallback ()) - m_process_launch_info.SetMonitorProcessCallback( - std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), - false); - - Error error = Host::LaunchProcess(m_process_launch_info); - if (!error.Success ()) - { - fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); - return error; - } +Error GDBRemoteCommunicationServerPlatform::LaunchProcess() { + if (!m_process_launch_info.GetArguments().GetArgumentCount()) + return Error("%s: no process command line specified to launch", + __FUNCTION__); + + // specify the process monitor if not already set. This should + // generally be what happens since we need to reap started + // processes. + if (!m_process_launch_info.GetMonitorProcessCallback()) + m_process_launch_info.SetMonitorProcessCallback( + std::bind( + &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, + this, std::placeholders::_1), + false); + + Error error = Host::LaunchProcess(m_process_launch_info); + if (!error.Success()) { + fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, + m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); + return error; + } - printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID()); + printf("Launched '%s' as process %" PRIu64 "...\n", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), + m_process_launch_info.GetProcessID()); - // add to list of spawned processes. On an lldb-gdbserver, we - // would expect there to be only one. - const auto pid = m_process_launch_info.GetProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) - { - // add to spawned pids - std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - } + // add to list of spawned processes. On an lldb-gdbserver, we + // would expect there to be only one. + const auto pid = m_process_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { + // add to spawned pids + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); + m_spawned_pids.insert(pid); + } - return error; + return error; } -void -GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map) -{ - m_port_map = port_map; +void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) { + m_port_map = port_map; } -uint16_t -GDBRemoteCommunicationServerPlatform::GetNextAvailablePort () -{ - if (m_port_map.empty()) - return 0; // Bind to port zero and get a port, we didn't have any limitations +uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() { + if (m_port_map.empty()) + return 0; // Bind to port zero and get a port, we didn't have any + // limitations - for (auto &pair : m_port_map) - { - if (pair.second == LLDB_INVALID_PROCESS_ID) - { - pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; - return pair.first; - } + for (auto &pair : m_port_map) { + if (pair.second == LLDB_INVALID_PROCESS_ID) { + pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; + return pair.first; } - return UINT16_MAX; + } + return UINT16_MAX; } -bool -GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid) -{ - PortMap::iterator pos = m_port_map.find(port); - if (pos != m_port_map.end()) - { - pos->second = pid; - return true; - } - return false; +bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess( + uint16_t port, lldb::pid_t pid) { + PortMap::iterator pos = m_port_map.find(port); + if (pos != m_port_map.end()) { + pos->second = pid; + return true; + } + return false; } -bool -GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port) -{ - PortMap::iterator pos = m_port_map.find(port); - if (pos != m_port_map.end()) - { - pos->second = LLDB_INVALID_PROCESS_ID; - return true; - } - return false; +bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) { + PortMap::iterator pos = m_port_map.find(port); + if (pos != m_port_map.end()) { + pos->second = LLDB_INVALID_PROCESS_ID; + return true; + } + return false; } -bool -GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid) -{ - if (!m_port_map.empty()) - { - for (auto &pair : m_port_map) - { - if (pair.second == pid) - { - pair.second = LLDB_INVALID_PROCESS_ID; - return true; - } - } +bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) { + if (!m_port_map.empty()) { + for (auto &pair : m_port_map) { + if (pair.second == pid) { + pair.second = LLDB_INVALID_PROCESS_ID; + return true; + } } - return false; + } + return false; } -const FileSpec& -GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() -{ - static FileSpec g_domainsocket_dir; - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() { - const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); - if (domainsocket_dir_env != nullptr) - g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); - else - HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir); - }); - - return g_domainsocket_dir; +const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() { + static FileSpec g_domainsocket_dir; + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + const char *domainsocket_dir_env = + ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); + if (domainsocket_dir_env != nullptr) + g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); + else + HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir); + }); + + return g_domainsocket_dir; } FileSpec -GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix) -{ - llvm::SmallString<PATH_MAX> socket_path; - llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str()); +GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) { + llvm::SmallString<PATH_MAX> socket_path; + llvm::SmallString<PATH_MAX> socket_name( + (llvm::StringRef(prefix) + ".%%%%%%").str()); - FileSpec socket_path_spec(GetDomainSocketDir()); - socket_path_spec.AppendPathComponent(socket_name.c_str()); + FileSpec socket_path_spec(GetDomainSocketDir()); + socket_path_spec.AppendPathComponent(socket_name.c_str()); - llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); - return FileSpec(socket_path.c_str(), false); + llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); + return FileSpec(socket_path.c_str(), false); } -void -GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) -{ - m_port_offset = port_offset; +void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) { + m_port_offset = port_offset; } -void -GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid, - uint16_t port, - const std::string& socket_name) -{ - m_pending_gdb_server.pid = pid; - m_pending_gdb_server.port = port; - m_pending_gdb_server.socket_name = socket_name; +void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer( + lldb::pid_t pid, uint16_t port, const std::string &socket_name) { + m_pending_gdb_server.pid = pid; + m_pending_gdb_server.port = port; + m_pending_gdb_server.socket_name = socket_name; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 1f4d08c64e0..472d86e3a15 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -24,110 +24,90 @@ namespace lldb_private { namespace process_gdb_remote { -class GDBRemoteCommunicationServerPlatform : - public GDBRemoteCommunicationServerCommon -{ +class GDBRemoteCommunicationServerPlatform + : public GDBRemoteCommunicationServerCommon { public: - typedef std::map<uint16_t, lldb::pid_t> PortMap; + typedef std::map<uint16_t, lldb::pid_t> PortMap; - GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, - const char* socket_scheme); + GDBRemoteCommunicationServerPlatform( + const Socket::SocketProtocol socket_protocol, const char *socket_scheme); - ~GDBRemoteCommunicationServerPlatform() override; + ~GDBRemoteCommunicationServerPlatform() override; - Error - LaunchProcess () override; + Error LaunchProcess() override; - // Set both ports to zero to let the platform automatically bind to - // a port chosen by the OS. - void - SetPortMap (PortMap &&port_map); + // Set both ports to zero to let the platform automatically bind to + // a port chosen by the OS. + void SetPortMap(PortMap &&port_map); - //---------------------------------------------------------------------- - // If we are using a port map where we can only use certain ports, - // get the next available port. - // - // If we are using a port map and we are out of ports, return UINT16_MAX - // - // If we aren't using a port map, return 0 to indicate we should bind to - // port 0 and then figure out which port we used. - //---------------------------------------------------------------------- - uint16_t - GetNextAvailablePort (); + //---------------------------------------------------------------------- + // If we are using a port map where we can only use certain ports, + // get the next available port. + // + // If we are using a port map and we are out of ports, return UINT16_MAX + // + // If we aren't using a port map, return 0 to indicate we should bind to + // port 0 and then figure out which port we used. + //---------------------------------------------------------------------- + uint16_t GetNextAvailablePort(); - bool - AssociatePortWithProcess (uint16_t port, lldb::pid_t pid); + bool AssociatePortWithProcess(uint16_t port, lldb::pid_t pid); - bool - FreePort (uint16_t port); + bool FreePort(uint16_t port); - bool - FreePortForProcess (lldb::pid_t pid); + bool FreePortForProcess(lldb::pid_t pid); - void - SetPortOffset (uint16_t port_offset); + void SetPortOffset(uint16_t port_offset); - void - SetInferiorArguments (const lldb_private::Args& args); + void SetInferiorArguments(const lldb_private::Args &args); - Error - LaunchGDBServer(const lldb_private::Args& args, - std::string hostname, - lldb::pid_t& pid, - uint16_t& port, - std::string& socket_name); + Error LaunchGDBServer(const lldb_private::Args &args, std::string hostname, + lldb::pid_t &pid, uint16_t &port, + std::string &socket_name); - void - SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name); + void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, + const std::string &socket_name); protected: - const Socket::SocketProtocol m_socket_protocol; - const std::string m_socket_scheme; - std::recursive_mutex m_spawned_pids_mutex; - std::set<lldb::pid_t> m_spawned_pids; + const Socket::SocketProtocol m_socket_protocol; + const std::string m_socket_scheme; + std::recursive_mutex m_spawned_pids_mutex; + std::set<lldb::pid_t> m_spawned_pids; - PortMap m_port_map; - uint16_t m_port_offset; - struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server; + PortMap m_port_map; + uint16_t m_port_offset; + struct { + lldb::pid_t pid; + uint16_t port; + std::string socket_name; + } m_pending_gdb_server; - PacketResult - Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet); + PacketResult Handle_qLaunchGDBServer(StringExtractorGDBRemote &packet); - PacketResult - Handle_qQueryGDBServer (StringExtractorGDBRemote &packet); + PacketResult Handle_qQueryGDBServer(StringExtractorGDBRemote &packet); - PacketResult - Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); + PacketResult Handle_qKillSpawnedProcess(StringExtractorGDBRemote &packet); - PacketResult - Handle_qProcessInfo (StringExtractorGDBRemote &packet); + PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet); - PacketResult - Handle_qGetWorkingDir (StringExtractorGDBRemote &packet); + PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); - PacketResult - Handle_QSetWorkingDir (StringExtractorGDBRemote &packet); + PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet); - PacketResult - Handle_qC (StringExtractorGDBRemote &packet); + PacketResult Handle_qC(StringExtractorGDBRemote &packet); - PacketResult - Handle_jSignalsInfo(StringExtractorGDBRemote &packet); + PacketResult Handle_jSignalsInfo(StringExtractorGDBRemote &packet); private: - bool - KillSpawnedProcess (lldb::pid_t pid); + bool KillSpawnedProcess(lldb::pid_t pid); - bool - DebugserverProcessReaped (lldb::pid_t pid); + bool DebugserverProcessReaped(lldb::pid_t pid); - static const FileSpec& - GetDomainSocketDir(); + static const FileSpec &GetDomainSocketDir(); - static FileSpec - GetDomainSocketPath(const char* prefix); + static FileSpec GetDomainSocketPath(const char *prefix); - DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform); + DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerPlatform); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 78e1956c26f..27ce67ded78 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -21,12 +21,12 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/Utils.h" // Project includes -#include "Utility/StringExtractorGDBRemote.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "ThreadGDBRemote.h" #include "Utility/ARM_DWARF_Registers.h" #include "Utility/ARM_ehframe_Registers.h" +#include "Utility/StringExtractorGDBRemote.h" using namespace lldb; using namespace lldb_private; @@ -35,762 +35,735 @@ using namespace lldb_private::process_gdb_remote; //---------------------------------------------------------------------- // GDBRemoteRegisterContext constructor //---------------------------------------------------------------------- -GDBRemoteRegisterContext::GDBRemoteRegisterContext -( - ThreadGDBRemote &thread, - uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, - bool read_all_at_once -) : - RegisterContext (thread, concrete_frame_idx), - m_reg_info (reg_info), - m_reg_valid (), - m_reg_data (), - m_read_all_at_once (read_all_at_once) -{ - // Resize our vector of bools to contain one bool for every register. - // We will use these boolean values to know when a register value - // is valid in m_reg_data. - m_reg_valid.resize (reg_info.GetNumRegisters()); - - // Make a heap based buffer that is big enough to store all registers - DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0)); - m_reg_data.SetData (reg_data_sp); - m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder()); +GDBRemoteRegisterContext::GDBRemoteRegisterContext( + ThreadGDBRemote &thread, uint32_t concrete_frame_idx, + GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once) + : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info), + m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) { + // Resize our vector of bools to contain one bool for every register. + // We will use these boolean values to know when a register value + // is valid in m_reg_data. + m_reg_valid.resize(reg_info.GetNumRegisters()); + + // Make a heap based buffer that is big enough to store all registers + DataBufferSP reg_data_sp( + new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0)); + m_reg_data.SetData(reg_data_sp); + m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder()); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -GDBRemoteRegisterContext::~GDBRemoteRegisterContext() -{ -} +GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {} -void -GDBRemoteRegisterContext::InvalidateAllRegisters () -{ - SetAllRegisterValid (false); +void GDBRemoteRegisterContext::InvalidateAllRegisters() { + SetAllRegisterValid(false); } -void -GDBRemoteRegisterContext::SetAllRegisterValid (bool b) -{ - std::vector<bool>::iterator pos, end = m_reg_valid.end(); - for (pos = m_reg_valid.begin(); pos != end; ++pos) - *pos = b; +void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) { + std::vector<bool>::iterator pos, end = m_reg_valid.end(); + for (pos = m_reg_valid.begin(); pos != end; ++pos) + *pos = b; } -size_t -GDBRemoteRegisterContext::GetRegisterCount () -{ - return m_reg_info.GetNumRegisters (); +size_t GDBRemoteRegisterContext::GetRegisterCount() { + return m_reg_info.GetNumRegisters(); } const RegisterInfo * -GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg) -{ - RegisterInfo* reg_info = m_reg_info.GetRegisterInfoAtIndex (reg); - - if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) - { - const ArchSpec &arch = m_thread.GetProcess ()->GetTarget ().GetArchitecture (); - uint8_t reg_size = UpdateDynamicRegisterSize (arch, reg_info); - reg_info->byte_size = reg_size; - } - return reg_info; +GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) { + RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg); + + if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) { + const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); + uint8_t reg_size = UpdateDynamicRegisterSize(arch, reg_info); + reg_info->byte_size = reg_size; + } + return reg_info; } -size_t -GDBRemoteRegisterContext::GetRegisterSetCount () -{ - return m_reg_info.GetNumRegisterSets (); +size_t GDBRemoteRegisterContext::GetRegisterSetCount() { + return m_reg_info.GetNumRegisterSets(); } - - -const RegisterSet * -GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set) -{ - return m_reg_info.GetRegisterSet (reg_set); +const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) { + return m_reg_info.GetRegisterSet(reg_set); } +bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + // Read the register + if (ReadRegisterBytes(reg_info, m_reg_data)) { + const bool partial_data_ok = false; + Error error(value.SetValueFromData(reg_info, m_reg_data, + reg_info->byte_offset, partial_data_ok)); + return error.Success(); + } + return false; +} - -bool -GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) -{ - // Read the register - if (ReadRegisterBytes (reg_info, m_reg_data)) - { - const bool partial_data_ok = false; - Error error (value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); - return error.Success(); - } +bool GDBRemoteRegisterContext::PrivateSetRegisterValue( + uint32_t reg, llvm::ArrayRef<uint8_t> data) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info == NULL) return false; -} -bool -GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data) -{ - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); - if (reg_info == NULL) - return false; - - // Invalidate if needed - InvalidateIfNeeded(false); - - const size_t reg_byte_size = reg_info->byte_size; - memcpy(const_cast<uint8_t *>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), data.data(), - std::min(data.size(), reg_byte_size)); - bool success = data.size() >= reg_byte_size; - if (success) - { - SetRegisterIsValid(reg, true); - } - else if (data.size() > 0) - { - // Only set register is valid to false if we copied some bytes, else - // leave it as it was. - SetRegisterIsValid(reg, false); - } - return success; + // Invalidate if needed + InvalidateIfNeeded(false); + + const size_t reg_byte_size = reg_info->byte_size; + memcpy(const_cast<uint8_t *>( + m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), + data.data(), std::min(data.size(), reg_byte_size)); + bool success = data.size() >= reg_byte_size; + if (success) { + SetRegisterIsValid(reg, true); + } else if (data.size() > 0) { + // Only set register is valid to false if we copied some bytes, else + // leave it as it was. + SetRegisterIsValid(reg, false); + } + return success; } -bool -GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val) -{ - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); - if (reg_info == NULL) - return false; - - // Early in process startup, we can get a thread that has an invalid byte order - // because the process hasn't been completely set up yet (see the ctor where the - // byte order is setfrom the process). If that's the case, we can't set the - // value here. - if (m_reg_data.GetByteOrder() == eByteOrderInvalid) - { - return false; - } - - // Invalidate if needed - InvalidateIfNeeded (false); +bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, + uint64_t new_reg_val) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info == NULL) + return false; - DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val))); - DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*)); + // Early in process startup, we can get a thread that has an invalid byte + // order + // because the process hasn't been completely set up yet (see the ctor where + // the + // byte order is setfrom the process). If that's the case, we can't set the + // value here. + if (m_reg_data.GetByteOrder() == eByteOrderInvalid) { + return false; + } - // If our register context and our register info disagree, which should never happen, don't - // overwrite past the end of the buffer. - if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) - return false; + // Invalidate if needed + InvalidateIfNeeded(false); - // Grab a pointer to where we are going to put this register - uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); + DataBufferSP buffer_sp(new DataBufferHeap(&new_reg_val, sizeof(new_reg_val))); + DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *)); - if (dst == NULL) - return false; + // If our register context and our register info disagree, which should never + // happen, don't + // overwrite past the end of the buffer. + if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) + return false; + // Grab a pointer to where we are going to put this register + uint8_t *dst = const_cast<uint8_t *>( + m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (data.CopyByteOrderedData (0, // src offset - reg_info->byte_size, // src length - dst, // dst - reg_info->byte_size, // dst length - m_reg_data.GetByteOrder())) // dst byte order - { - SetRegisterIsValid (reg, true); - return true; - } + if (dst == NULL) return false; + + if (data.CopyByteOrderedData(0, // src offset + reg_info->byte_size, // src length + dst, // dst + reg_info->byte_size, // dst length + m_reg_data.GetByteOrder())) // dst byte order + { + SetRegisterIsValid(reg, true); + return true; + } + return false; } // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes(). -bool -GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info, - GDBRemoteCommunicationClient &gdb_comm) -{ - const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB]; - const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin]; - StringExtractorGDBRemote response; - if (DataBufferSP buffer_sp = gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg)) - return PrivateSetRegisterValue(lldb_reg, - llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(), buffer_sp->GetByteSize())); - return false; +bool GDBRemoteRegisterContext::GetPrimordialRegister( + const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) { + const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin]; + StringExtractorGDBRemote response; + if (DataBufferSP buffer_sp = + gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg)) + return PrivateSetRegisterValue( + lldb_reg, llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(), + buffer_sp->GetByteSize())); + return false; } -bool -GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data) -{ - ExecutionContext exe_ctx (CalculateThread()); +bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, + DataExtractor &data) { + ExecutionContext exe_ctx(CalculateThread()); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) - return false; - - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + if (process == NULL || thread == NULL) + return false; - InvalidateIfNeeded(false); + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + InvalidateIfNeeded(false); - if (!GetRegisterIsValid(reg)) - { - if (m_read_all_at_once) - { - if (DataBufferSP buffer_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) - { - memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()), buffer_sp->GetBytes(), - std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize())); - if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) - { - SetAllRegisterValid(true); - return true; - } - } - return false; - } - if (reg_info->value_regs) - { - // Process this composite register request by delegating to the constituent - // primordial registers. - - // Index of the primordial register. - bool success = true; - for (uint32_t idx = 0; success; ++idx) - { - const uint32_t prim_reg = reg_info->value_regs[idx]; - if (prim_reg == LLDB_INVALID_REGNUM) - break; - // We have a valid primordial register as our constituent. - // Grab the corresponding register info. - const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg); - if (prim_reg_info == NULL) - success = false; - else - { - // Read the containing register if it hasn't already been read - if (!GetRegisterIsValid(prim_reg)) - success = GetPrimordialRegister(prim_reg_info, gdb_comm); - } - } + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (success) - { - // If we reach this point, all primordial register requests have succeeded. - // Validate this composite register. - SetRegisterIsValid (reg_info, true); - } + if (!GetRegisterIsValid(reg)) { + if (m_read_all_at_once) { + if (DataBufferSP buffer_sp = + gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) { + memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()), + buffer_sp->GetBytes(), + std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize())); + if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) { + SetAllRegisterValid(true); + return true; } - else - { - // Get each register individually - GetPrimordialRegister(reg_info, gdb_comm); + } + return false; + } + if (reg_info->value_regs) { + // Process this composite register request by delegating to the + // constituent + // primordial registers. + + // Index of the primordial register. + bool success = true; + for (uint32_t idx = 0; success; ++idx) { + const uint32_t prim_reg = reg_info->value_regs[idx]; + if (prim_reg == LLDB_INVALID_REGNUM) + break; + // We have a valid primordial register as our constituent. + // Grab the corresponding register info. + const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg); + if (prim_reg_info == NULL) + success = false; + else { + // Read the containing register if it hasn't already been read + if (!GetRegisterIsValid(prim_reg)) + success = GetPrimordialRegister(prim_reg_info, gdb_comm); } - - // Make sure we got a valid register value after reading it - if (!GetRegisterIsValid(reg)) - return false; + } + + if (success) { + // If we reach this point, all primordial register requests have + // succeeded. + // Validate this composite register. + SetRegisterIsValid(reg_info, true); + } + } else { + // Get each register individually + GetPrimordialRegister(reg_info, gdb_comm); } - if (&data != &m_reg_data) - { -#if defined (LLDB_CONFIGURATION_DEBUG) - assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size); -#endif - // If our register context and our register info disagree, which should never happen, don't - // read past the end of the buffer. - if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) - return false; - - // If we aren't extracting into our own buffer (which - // only happens when this function is called from - // ReadRegisterValue(uint32_t, Scalar&)) then - // we transfer bytes from our buffer into the data - // buffer that was passed in - - data.SetByteOrder (m_reg_data.GetByteOrder()); - data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size); - } - return true; + // Make sure we got a valid register value after reading it + if (!GetRegisterIsValid(reg)) + return false; + } + + if (&data != &m_reg_data) { +#if defined(LLDB_CONFIGURATION_DEBUG) + assert(m_reg_data.GetByteSize() >= + reg_info->byte_offset + reg_info->byte_size); +#endif + // If our register context and our register info disagree, which should + // never happen, don't + // read past the end of the buffer. + if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) + return false; + + // If we aren't extracting into our own buffer (which + // only happens when this function is called from + // ReadRegisterValue(uint32_t, Scalar&)) then + // we transfer bytes from our buffer into the data + // buffer that was passed in + + data.SetByteOrder(m_reg_data.GetByteOrder()); + data.SetData(m_reg_data, reg_info->byte_offset, reg_info->byte_size); + } + return true; } -bool -GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) -{ - DataExtractor data; - if (value.GetData (data)) - return WriteRegisterBytes (reg_info, data, 0); - return false; +bool GDBRemoteRegisterContext::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + DataExtractor data; + if (value.GetData(data)) + return WriteRegisterBytes(reg_info, data, 0); + return false; } // Helper function for GDBRemoteRegisterContext::WriteRegisterBytes(). -bool -GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info, - GDBRemoteCommunicationClient &gdb_comm) -{ - StreamString packet; - StringExtractorGDBRemote response; - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - // Invalidate just this register - SetRegisterIsValid(reg, false); - - return gdb_comm.WriteRegister( - m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin], - {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size}); +bool GDBRemoteRegisterContext::SetPrimordialRegister( + const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) { + StreamString packet; + StringExtractorGDBRemote response; + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + // Invalidate just this register + SetRegisterIsValid(reg, false); + + return gdb_comm.WriteRegister( + m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin], + {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), + reg_info->byte_size}); } -bool -GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset) -{ - ExecutionContext exe_ctx (CalculateThread()); +bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, + DataExtractor &data, + uint32_t data_offset) { + ExecutionContext exe_ctx(CalculateThread()); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) - return false; + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + if (process == NULL || thread == NULL) + return false; - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); -#if defined (LLDB_CONFIGURATION_DEBUG) - assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size); +#if defined(LLDB_CONFIGURATION_DEBUG) + assert(m_reg_data.GetByteSize() >= + reg_info->byte_offset + reg_info->byte_size); #endif - // If our register context and our register info disagree, which should never happen, don't - // overwrite past the end of the buffer. - if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) - return false; + // If our register context and our register info disagree, which should never + // happen, don't + // overwrite past the end of the buffer. + if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) + return false; - // Grab a pointer to where we are going to put this register - uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); + // Grab a pointer to where we are going to put this register + uint8_t *dst = const_cast<uint8_t *>( + m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (dst == NULL) - return false; + if (dst == NULL) + return false; + + if (data.CopyByteOrderedData(data_offset, // src offset + reg_info->byte_size, // src length + dst, // dst + reg_info->byte_size, // dst length + m_reg_data.GetByteOrder())) // dst byte order + { + GDBRemoteClientBase::Lock lock(gdb_comm, false); + if (lock) { + if (m_read_all_at_once) { + // Invalidate all register values + InvalidateIfNeeded(true); + // Set all registers in one packet + if (gdb_comm.WriteAllRegisters( + m_thread.GetProtocolID(), + {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())})) - if (data.CopyByteOrderedData (data_offset, // src offset - reg_info->byte_size, // src length - dst, // dst - reg_info->byte_size, // dst length - m_reg_data.GetByteOrder())) // dst byte order - { - GDBRemoteClientBase::Lock lock(gdb_comm, false); - if (lock) { - if (m_read_all_at_once) - { - // Invalidate all register values - InvalidateIfNeeded (true); - - // Set all registers in one packet - if (gdb_comm.WriteAllRegisters(m_thread.GetProtocolID(), - {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())})) - - { - SetAllRegisterValid (false); - return true; - } - } - else - { - bool success = true; - - if (reg_info->value_regs) - { - // This register is part of another register. In this case we read the actual - // register data for any "value_regs", and once all that data is read, we will - // have enough data in our register context bytes for the value of this register - - // Invalidate this composite register first. - - for (uint32_t idx = 0; success; ++idx) - { - const uint32_t reg = reg_info->value_regs[idx]; - if (reg == LLDB_INVALID_REGNUM) - break; - // We have a valid primordial register as our constituent. - // Grab the corresponding register info. - const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg); - if (value_reg_info == NULL) - success = false; - else - success = SetPrimordialRegister(value_reg_info, gdb_comm); - } - } - else - { - // This is an actual register, write it - success = SetPrimordialRegister(reg_info, gdb_comm); - } - - // Check if writing this register will invalidate any other register values? - // If so, invalidate them - if (reg_info->invalidate_regs) - { - for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0]; - reg != LLDB_INVALID_REGNUM; - reg = reg_info->invalidate_regs[++idx]) - { - SetRegisterIsValid(reg, false); - } - } - - return success; - } + SetAllRegisterValid(false); + return true; } - else - { - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); - if (log) - { - if (log->GetVerbose()) - { - StreamString strm; - gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\":\n%s", reg_info->name, strm.GetData()); - } - else - log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\"", reg_info->name); - } + } else { + bool success = true; + + if (reg_info->value_regs) { + // This register is part of another register. In this case we read the + // actual + // register data for any "value_regs", and once all that data is read, + // we will + // have enough data in our register context bytes for the value of + // this register + + // Invalidate this composite register first. + + for (uint32_t idx = 0; success; ++idx) { + const uint32_t reg = reg_info->value_regs[idx]; + if (reg == LLDB_INVALID_REGNUM) + break; + // We have a valid primordial register as our constituent. + // Grab the corresponding register info. + const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg); + if (value_reg_info == NULL) + success = false; + else + success = SetPrimordialRegister(value_reg_info, gdb_comm); + } + } else { + // This is an actual register, write it + success = SetPrimordialRegister(reg_info, gdb_comm); } + + // Check if writing this register will invalidate any other register + // values? + // If so, invalidate them + if (reg_info->invalidate_regs) { + for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0]; + reg != LLDB_INVALID_REGNUM; + reg = reg_info->invalidate_regs[++idx]) { + SetRegisterIsValid(reg, false); + } + } + + return success; + } + } else { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | + GDBR_LOG_PACKETS)); + if (log) { + if (log->GetVerbose()) { + StreamString strm; + gdb_comm.DumpHistory(strm); + log->Printf("error: failed to get packet sequence mutex, not sending " + "write register for \"%s\":\n%s", + reg_info->name, strm.GetData()); + } else + log->Printf("error: failed to get packet sequence mutex, not sending " + "write register for \"%s\"", + reg_info->name); + } } + } + return false; +} + +bool GDBRemoteRegisterContext::ReadAllRegisterValues( + RegisterCheckpoint ®_checkpoint) { + ExecutionContext exe_ctx(CalculateThread()); + + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + if (process == NULL || thread == NULL) return false; + + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); + + uint32_t save_id = 0; + if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id)) { + reg_checkpoint.SetID(save_id); + reg_checkpoint.GetData().reset(); + return true; + } else { + reg_checkpoint.SetID(0); // Invalid save ID is zero + return ReadAllRegisterValues(reg_checkpoint.GetData()); + } } -bool -GDBRemoteRegisterContext::ReadAllRegisterValues (RegisterCheckpoint ®_checkpoint) -{ - ExecutionContext exe_ctx (CalculateThread()); - +bool GDBRemoteRegisterContext::WriteAllRegisterValues( + const RegisterCheckpoint ®_checkpoint) { + uint32_t save_id = reg_checkpoint.GetID(); + if (save_id != 0) { + ExecutionContext exe_ctx(CalculateThread()); + Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); if (process == NULL || thread == NULL) - return false; - - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); - - uint32_t save_id = 0; - if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id)) - { - reg_checkpoint.SetID(save_id); - reg_checkpoint.GetData().reset(); - return true; - } - else - { - reg_checkpoint.SetID(0); // Invalid save ID is zero - return ReadAllRegisterValues(reg_checkpoint.GetData()); - } -} + return false; -bool -GDBRemoteRegisterContext::WriteAllRegisterValues (const RegisterCheckpoint ®_checkpoint) -{ - uint32_t save_id = reg_checkpoint.GetID(); - if (save_id != 0) - { - ExecutionContext exe_ctx (CalculateThread()); - - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) - return false; - - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); - - return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id); - } - else - { - return WriteAllRegisterValues(reg_checkpoint.GetData()); - } + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); + + return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id); + } else { + return WriteAllRegisterValues(reg_checkpoint.GetData()); + } } -bool -GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - ExecutionContext exe_ctx (CalculateThread()); +bool GDBRemoteRegisterContext::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + ExecutionContext exe_ctx(CalculateThread()); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) - return false; + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + if (process == NULL || thread == NULL) + return false; - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); - const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false; + const bool use_g_packet = + gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false; - GDBRemoteClientBase::Lock lock(gdb_comm, false); - if (lock) - { - if (gdb_comm.SyncThreadState(m_thread.GetProtocolID())) - InvalidateAllRegisters(); + GDBRemoteClientBase::Lock lock(gdb_comm, false); + if (lock) { + if (gdb_comm.SyncThreadState(m_thread.GetProtocolID())) + InvalidateAllRegisters(); - if (use_g_packet && (data_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID()))) - return true; + if (use_g_packet && + (data_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID()))) + return true; - // We're going to read each register - // individually and store them as binary data in a buffer. - const RegisterInfo *reg_info; + // We're going to read each register + // individually and store them as binary data in a buffer. + const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) - { - if (reg_info->value_regs) // skip registers that are slices of real registers - continue; - ReadRegisterBytes(reg_info, m_reg_data); - // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer - } - data_sp.reset(new DataBufferHeap(m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize())); - return true; + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) { + if (reg_info + ->value_regs) // skip registers that are slices of real registers + continue; + ReadRegisterBytes(reg_info, m_reg_data); + // ReadRegisterBytes saves the contents of the register in to the + // m_reg_data buffer } - else - { - - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); - if (log) - { - if (log->GetVerbose()) - { - StreamString strm; - gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending read all registers:\n%s", strm.GetData()); - } - else - log->Printf("error: failed to get packet sequence mutex, not sending read all registers"); - } + data_sp.reset(new DataBufferHeap(m_reg_data.GetDataStart(), + m_reg_info.GetRegisterDataByteSize())); + return true; + } else { + + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | + GDBR_LOG_PACKETS)); + if (log) { + if (log->GetVerbose()) { + StreamString strm; + gdb_comm.DumpHistory(strm); + log->Printf("error: failed to get packet sequence mutex, not sending " + "read all registers:\n%s", + strm.GetData()); + } else + log->Printf("error: failed to get packet sequence mutex, not sending " + "read all registers"); } + } - data_sp.reset(); - return false; + data_sp.reset(); + return false; } -bool -GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0) - return false; +bool GDBRemoteRegisterContext::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0) + return false; - ExecutionContext exe_ctx (CalculateThread()); + ExecutionContext exe_ctx(CalculateThread()); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) - return false; + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + if (process == NULL || thread == NULL) + return false; - GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote()); + GDBRemoteCommunicationClient &gdb_comm( + ((ProcessGDBRemote *)process)->GetGDBRemote()); - const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false; + const bool use_g_packet = + gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false; - GDBRemoteClientBase::Lock lock(gdb_comm, false); - if (lock) - { - // The data_sp contains the G response packet. - if (use_g_packet) - { - if (gdb_comm.WriteAllRegisters(m_thread.GetProtocolID(), - {data_sp->GetBytes(), size_t(data_sp->GetByteSize())})) - return true; - - uint32_t num_restored = 0; - // We need to manually go through all of the registers and - // restore them manually - DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(), m_reg_data.GetAddressByteSize()); - - const RegisterInfo *reg_info; - - // The g packet contents may either include the slice registers (registers defined in - // terms of other registers, e.g. eax is a subset of rax) or not. The slice registers - // should NOT be in the g packet, but some implementations may incorrectly include them. - // - // If the slice registers are included in the packet, we must step over the slice registers - // when parsing the packet -- relying on the RegisterInfo byte_offset field would be incorrect. - // If the slice registers are not included, then using the byte_offset values into the - // data buffer is the best way to find individual register values. - - uint64_t size_including_slice_registers = 0; - uint64_t size_not_including_slice_registers = 0; - uint64_t size_by_highest_offset = 0; - - for (uint32_t reg_idx = 0; (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; ++reg_idx) - { - size_including_slice_registers += reg_info->byte_size; - if (reg_info->value_regs == NULL) - size_not_including_slice_registers += reg_info->byte_size; - if (reg_info->byte_offset >= size_by_highest_offset) - size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size; - } + GDBRemoteClientBase::Lock lock(gdb_comm, false); + if (lock) { + // The data_sp contains the G response packet. + if (use_g_packet) { + if (gdb_comm.WriteAllRegisters( + m_thread.GetProtocolID(), + {data_sp->GetBytes(), size_t(data_sp->GetByteSize())})) + return true; - bool use_byte_offset_into_buffer; - if (size_by_highest_offset == restore_data.GetByteSize()) - { - // The size of the packet agrees with the highest offset: + size in the register file - use_byte_offset_into_buffer = true; - } - else if (size_not_including_slice_registers == restore_data.GetByteSize()) - { - // The size of the packet is the same as concatenating all of the registers sequentially, - // skipping the slice registers - use_byte_offset_into_buffer = true; - } - else if (size_including_slice_registers == restore_data.GetByteSize()) - { - // The slice registers are present in the packet (when they shouldn't be). - // Don't try to use the RegisterInfo byte_offset into the restore_data, it will - // point to the wrong place. - use_byte_offset_into_buffer = false; - } - else - { - // None of our expected sizes match the actual g packet data we're looking at. - // The most conservative approach here is to use the running total byte offset. - use_byte_offset_into_buffer = false; - } + uint32_t num_restored = 0; + // We need to manually go through all of the registers and + // restore them manually + DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(), + m_reg_data.GetAddressByteSize()); + + const RegisterInfo *reg_info; + + // The g packet contents may either include the slice registers (registers + // defined in + // terms of other registers, e.g. eax is a subset of rax) or not. The + // slice registers + // should NOT be in the g packet, but some implementations may incorrectly + // include them. + // + // If the slice registers are included in the packet, we must step over + // the slice registers + // when parsing the packet -- relying on the RegisterInfo byte_offset + // field would be incorrect. + // If the slice registers are not included, then using the byte_offset + // values into the + // data buffer is the best way to find individual register values. + + uint64_t size_including_slice_registers = 0; + uint64_t size_not_including_slice_registers = 0; + uint64_t size_by_highest_offset = 0; + + for (uint32_t reg_idx = 0; + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; ++reg_idx) { + size_including_slice_registers += reg_info->byte_size; + if (reg_info->value_regs == NULL) + size_not_including_slice_registers += reg_info->byte_size; + if (reg_info->byte_offset >= size_by_highest_offset) + size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size; + } + + bool use_byte_offset_into_buffer; + if (size_by_highest_offset == restore_data.GetByteSize()) { + // The size of the packet agrees with the highest offset: + size in the + // register file + use_byte_offset_into_buffer = true; + } else if (size_not_including_slice_registers == + restore_data.GetByteSize()) { + // The size of the packet is the same as concatenating all of the + // registers sequentially, + // skipping the slice registers + use_byte_offset_into_buffer = true; + } else if (size_including_slice_registers == restore_data.GetByteSize()) { + // The slice registers are present in the packet (when they shouldn't + // be). + // Don't try to use the RegisterInfo byte_offset into the restore_data, + // it will + // point to the wrong place. + use_byte_offset_into_buffer = false; + } else { + // None of our expected sizes match the actual g packet data we're + // looking at. + // The most conservative approach here is to use the running total byte + // offset. + use_byte_offset_into_buffer = false; + } + + // In case our register definitions don't include the correct offsets, + // keep track of the size of each reg & compute offset based on that. + uint32_t running_byte_offset = 0; + for (uint32_t reg_idx = 0; + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; + ++reg_idx, running_byte_offset += reg_info->byte_size) { + // Skip composite aka slice registers (e.g. eax is a slice of rax). + if (reg_info->value_regs) + continue; - // In case our register definitions don't include the correct offsets, - // keep track of the size of each reg & compute offset based on that. - uint32_t running_byte_offset = 0; - for (uint32_t reg_idx = 0; (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; - ++reg_idx, running_byte_offset += reg_info->byte_size) - { - // Skip composite aka slice registers (e.g. eax is a slice of rax). - if (reg_info->value_regs) - continue; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - uint32_t register_offset; - if (use_byte_offset_into_buffer) - { - register_offset = reg_info->byte_offset; - } - else - { - register_offset = running_byte_offset; - } - - const uint32_t reg_byte_size = reg_info->byte_size; - - const uint8_t *restore_src = restore_data.PeekData(register_offset, reg_byte_size); - if (restore_src) - { - SetRegisterIsValid(reg, false); - if (gdb_comm.WriteRegister(m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin], - {restore_src, reg_byte_size})) - ++num_restored; - } - } - return num_restored > 0; + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + uint32_t register_offset; + if (use_byte_offset_into_buffer) { + register_offset = reg_info->byte_offset; + } else { + register_offset = running_byte_offset; } - else - { - // For the use_g_packet == false case, we're going to write each register - // individually. The data buffer is binary data in this case, instead of - // ascii characters. - - bool arm64_debugserver = false; - if (m_thread.GetProcess().get()) - { - const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetMachine() == llvm::Triple::aarch64 && - arch.GetTriple().getVendor() == llvm::Triple::Apple && - arch.GetTriple().getOS() == llvm::Triple::IOS) - { - arm64_debugserver = true; - } - } - uint32_t num_restored = 0; - const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) - { - if (reg_info->value_regs) // skip registers that are slices of real registers - continue; - // Skip the fpsr and fpcr floating point status/control register writing to - // work around a bug in an older version of debugserver that would lead to - // register context corruption when writing fpsr/fpcr. - if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 || strcmp(reg_info->name, "fpcr") == 0)) - { - continue; - } - - SetRegisterIsValid(reg_info, false); - if (gdb_comm.WriteRegister(m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin], - {data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size})) - ++num_restored; - } - return num_restored > 0; + + const uint32_t reg_byte_size = reg_info->byte_size; + + const uint8_t *restore_src = + restore_data.PeekData(register_offset, reg_byte_size); + if (restore_src) { + SetRegisterIsValid(reg, false); + if (gdb_comm.WriteRegister( + m_thread.GetProtocolID(), + reg_info->kinds[eRegisterKindProcessPlugin], + {restore_src, reg_byte_size})) + ++num_restored; } - } - else - { - Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); - if (log) - { - if (log->GetVerbose()) - { - StreamString strm; - gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending write all registers:\n%s", strm.GetData()); - } - else - log->Printf("error: failed to get packet sequence mutex, not sending write all registers"); + } + return num_restored > 0; + } else { + // For the use_g_packet == false case, we're going to write each register + // individually. The data buffer is binary data in this case, instead of + // ascii characters. + + bool arm64_debugserver = false; + if (m_thread.GetProcess().get()) { + const ArchSpec &arch = + m_thread.GetProcess()->GetTarget().GetArchitecture(); + if (arch.IsValid() && arch.GetMachine() == llvm::Triple::aarch64 && + arch.GetTriple().getVendor() == llvm::Triple::Apple && + arch.GetTriple().getOS() == llvm::Triple::IOS) { + arm64_debugserver = true; + } + } + uint32_t num_restored = 0; + const RegisterInfo *reg_info; + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; + i++) { + if (reg_info->value_regs) // skip registers that are slices of real + // registers + continue; + // Skip the fpsr and fpcr floating point status/control register writing + // to + // work around a bug in an older version of debugserver that would lead + // to + // register context corruption when writing fpsr/fpcr. + if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 || + strcmp(reg_info->name, "fpcr") == 0)) { + continue; } + + SetRegisterIsValid(reg_info, false); + if (gdb_comm.WriteRegister(m_thread.GetProtocolID(), + reg_info->kinds[eRegisterKindProcessPlugin], + {data_sp->GetBytes() + reg_info->byte_offset, + reg_info->byte_size})) + ++num_restored; + } + return num_restored > 0; } - return false; + } else { + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | + GDBR_LOG_PACKETS)); + if (log) { + if (log->GetVerbose()) { + StreamString strm; + gdb_comm.DumpHistory(strm); + log->Printf("error: failed to get packet sequence mutex, not sending " + "write all registers:\n%s", + strm.GetData()); + } else + log->Printf("error: failed to get packet sequence mutex, not sending " + "write all registers"); + } + } + return false; } - -uint32_t -GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) -{ - return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num); +uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num); } - -void -GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) -{ - // For Advanced SIMD and VFP register mapping. - static uint32_t g_d0_regs[] = { 26, 27, LLDB_INVALID_REGNUM }; // (s0, s1) - static uint32_t g_d1_regs[] = { 28, 29, LLDB_INVALID_REGNUM }; // (s2, s3) - static uint32_t g_d2_regs[] = { 30, 31, LLDB_INVALID_REGNUM }; // (s4, s5) - static uint32_t g_d3_regs[] = { 32, 33, LLDB_INVALID_REGNUM }; // (s6, s7) - static uint32_t g_d4_regs[] = { 34, 35, LLDB_INVALID_REGNUM }; // (s8, s9) - static uint32_t g_d5_regs[] = { 36, 37, LLDB_INVALID_REGNUM }; // (s10, s11) - static uint32_t g_d6_regs[] = { 38, 39, LLDB_INVALID_REGNUM }; // (s12, s13) - static uint32_t g_d7_regs[] = { 40, 41, LLDB_INVALID_REGNUM }; // (s14, s15) - static uint32_t g_d8_regs[] = { 42, 43, LLDB_INVALID_REGNUM }; // (s16, s17) - static uint32_t g_d9_regs[] = { 44, 45, LLDB_INVALID_REGNUM }; // (s18, s19) - static uint32_t g_d10_regs[] = { 46, 47, LLDB_INVALID_REGNUM }; // (s20, s21) - static uint32_t g_d11_regs[] = { 48, 49, LLDB_INVALID_REGNUM }; // (s22, s23) - static uint32_t g_d12_regs[] = { 50, 51, LLDB_INVALID_REGNUM }; // (s24, s25) - static uint32_t g_d13_regs[] = { 52, 53, LLDB_INVALID_REGNUM }; // (s26, s27) - static uint32_t g_d14_regs[] = { 54, 55, LLDB_INVALID_REGNUM }; // (s28, s29) - static uint32_t g_d15_regs[] = { 56, 57, LLDB_INVALID_REGNUM }; // (s30, s31) - static uint32_t g_q0_regs[] = { 26, 27, 28, 29, LLDB_INVALID_REGNUM }; // (d0, d1) -> (s0, s1, s2, s3) - static uint32_t g_q1_regs[] = { 30, 31, 32, 33, LLDB_INVALID_REGNUM }; // (d2, d3) -> (s4, s5, s6, s7) - static uint32_t g_q2_regs[] = { 34, 35, 36, 37, LLDB_INVALID_REGNUM }; // (d4, d5) -> (s8, s9, s10, s11) - static uint32_t g_q3_regs[] = { 38, 39, 40, 41, LLDB_INVALID_REGNUM }; // (d6, d7) -> (s12, s13, s14, s15) - static uint32_t g_q4_regs[] = { 42, 43, 44, 45, LLDB_INVALID_REGNUM }; // (d8, d9) -> (s16, s17, s18, s19) - static uint32_t g_q5_regs[] = { 46, 47, 48, 49, LLDB_INVALID_REGNUM }; // (d10, d11) -> (s20, s21, s22, s23) - static uint32_t g_q6_regs[] = { 50, 51, 52, 53, LLDB_INVALID_REGNUM }; // (d12, d13) -> (s24, s25, s26, s27) - static uint32_t g_q7_regs[] = { 54, 55, 56, 57, LLDB_INVALID_REGNUM }; // (d14, d15) -> (s28, s29, s30, s31) - static uint32_t g_q8_regs[] = { 59, 60, LLDB_INVALID_REGNUM }; // (d16, d17) - static uint32_t g_q9_regs[] = { 61, 62, LLDB_INVALID_REGNUM }; // (d18, d19) - static uint32_t g_q10_regs[] = { 63, 64, LLDB_INVALID_REGNUM }; // (d20, d21) - static uint32_t g_q11_regs[] = { 65, 66, LLDB_INVALID_REGNUM }; // (d22, d23) - static uint32_t g_q12_regs[] = { 67, 68, LLDB_INVALID_REGNUM }; // (d24, d25) - static uint32_t g_q13_regs[] = { 69, 70, LLDB_INVALID_REGNUM }; // (d26, d27) - static uint32_t g_q14_regs[] = { 71, 72, LLDB_INVALID_REGNUM }; // (d28, d29) - static uint32_t g_q15_regs[] = { 73, 74, LLDB_INVALID_REGNUM }; // (d30, d31) - - // This is our array of composite registers, with each element coming from the above register mappings. - static uint32_t *g_composites[] = { - g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs, g_d6_regs, g_d7_regs, - g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs, g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs, - g_q0_regs, g_q1_regs, g_q2_regs, g_q3_regs, g_q4_regs, g_q5_regs, g_q6_regs, g_q7_regs, - g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs, g_q14_regs, g_q15_regs - }; - - // clang-format off +void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) { + // For Advanced SIMD and VFP register mapping. + static uint32_t g_d0_regs[] = {26, 27, LLDB_INVALID_REGNUM}; // (s0, s1) + static uint32_t g_d1_regs[] = {28, 29, LLDB_INVALID_REGNUM}; // (s2, s3) + static uint32_t g_d2_regs[] = {30, 31, LLDB_INVALID_REGNUM}; // (s4, s5) + static uint32_t g_d3_regs[] = {32, 33, LLDB_INVALID_REGNUM}; // (s6, s7) + static uint32_t g_d4_regs[] = {34, 35, LLDB_INVALID_REGNUM}; // (s8, s9) + static uint32_t g_d5_regs[] = {36, 37, LLDB_INVALID_REGNUM}; // (s10, s11) + static uint32_t g_d6_regs[] = {38, 39, LLDB_INVALID_REGNUM}; // (s12, s13) + static uint32_t g_d7_regs[] = {40, 41, LLDB_INVALID_REGNUM}; // (s14, s15) + static uint32_t g_d8_regs[] = {42, 43, LLDB_INVALID_REGNUM}; // (s16, s17) + static uint32_t g_d9_regs[] = {44, 45, LLDB_INVALID_REGNUM}; // (s18, s19) + static uint32_t g_d10_regs[] = {46, 47, LLDB_INVALID_REGNUM}; // (s20, s21) + static uint32_t g_d11_regs[] = {48, 49, LLDB_INVALID_REGNUM}; // (s22, s23) + static uint32_t g_d12_regs[] = {50, 51, LLDB_INVALID_REGNUM}; // (s24, s25) + static uint32_t g_d13_regs[] = {52, 53, LLDB_INVALID_REGNUM}; // (s26, s27) + static uint32_t g_d14_regs[] = {54, 55, LLDB_INVALID_REGNUM}; // (s28, s29) + static uint32_t g_d15_regs[] = {56, 57, LLDB_INVALID_REGNUM}; // (s30, s31) + static uint32_t g_q0_regs[] = { + 26, 27, 28, 29, LLDB_INVALID_REGNUM}; // (d0, d1) -> (s0, s1, s2, s3) + static uint32_t g_q1_regs[] = { + 30, 31, 32, 33, LLDB_INVALID_REGNUM}; // (d2, d3) -> (s4, s5, s6, s7) + static uint32_t g_q2_regs[] = { + 34, 35, 36, 37, LLDB_INVALID_REGNUM}; // (d4, d5) -> (s8, s9, s10, s11) + static uint32_t g_q3_regs[] = { + 38, 39, 40, 41, LLDB_INVALID_REGNUM}; // (d6, d7) -> (s12, s13, s14, s15) + static uint32_t g_q4_regs[] = { + 42, 43, 44, 45, LLDB_INVALID_REGNUM}; // (d8, d9) -> (s16, s17, s18, s19) + static uint32_t g_q5_regs[] = { + 46, 47, 48, 49, + LLDB_INVALID_REGNUM}; // (d10, d11) -> (s20, s21, s22, s23) + static uint32_t g_q6_regs[] = { + 50, 51, 52, 53, + LLDB_INVALID_REGNUM}; // (d12, d13) -> (s24, s25, s26, s27) + static uint32_t g_q7_regs[] = { + 54, 55, 56, 57, + LLDB_INVALID_REGNUM}; // (d14, d15) -> (s28, s29, s30, s31) + static uint32_t g_q8_regs[] = {59, 60, LLDB_INVALID_REGNUM}; // (d16, d17) + static uint32_t g_q9_regs[] = {61, 62, LLDB_INVALID_REGNUM}; // (d18, d19) + static uint32_t g_q10_regs[] = {63, 64, LLDB_INVALID_REGNUM}; // (d20, d21) + static uint32_t g_q11_regs[] = {65, 66, LLDB_INVALID_REGNUM}; // (d22, d23) + static uint32_t g_q12_regs[] = {67, 68, LLDB_INVALID_REGNUM}; // (d24, d25) + static uint32_t g_q13_regs[] = {69, 70, LLDB_INVALID_REGNUM}; // (d26, d27) + static uint32_t g_q14_regs[] = {71, 72, LLDB_INVALID_REGNUM}; // (d28, d29) + static uint32_t g_q15_regs[] = {73, 74, LLDB_INVALID_REGNUM}; // (d30, d31) + + // This is our array of composite registers, with each element coming from the + // above register mappings. + static uint32_t *g_composites[] = { + g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs, + g_d6_regs, g_d7_regs, g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs, + g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs, g_q0_regs, g_q1_regs, + g_q2_regs, g_q3_regs, g_q4_regs, g_q5_regs, g_q6_regs, g_q7_regs, + g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs, + g_q14_regs, g_q15_regs}; + + // clang-format off static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS SIZE EXPR SIZE LEN // ====== ====== === === ============= ========== =================== =================== ====================== ============= ==== ========== =============== ========= ======== @@ -902,121 +875,113 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) { "q14", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, nullptr, nullptr, 0 }, { "q15", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, nullptr, nullptr, 0 } }; - // clang-format on - - static const uint32_t num_registers = llvm::array_lengthof(g_register_infos); - static ConstString gpr_reg_set ("General Purpose Registers"); - static ConstString sfp_reg_set ("Software Floating Point Registers"); - static ConstString vfp_reg_set ("Floating Point Registers"); - size_t i; - if (from_scratch) - { - // Calculate the offsets of the registers - // Note that the layout of the "composite" registers (d0-d15 and q0-q15) which comes after the - // "primordial" registers is important. This enables us to calculate the offset of the composite - // register by using the offset of its first primordial register. For example, to calculate the - // offset of q0, use s0's offset. - if (g_register_infos[2].byte_offset == 0) - { - uint32_t byte_offset = 0; - for (i=0; i<num_registers; ++i) - { - // For primordial registers, increment the byte_offset by the byte_size to arrive at the - // byte_offset for the next register. Otherwise, we have a composite register whose - // offset can be calculated by consulting the offset of its first primordial register. - if (!g_register_infos[i].value_regs) - { - g_register_infos[i].byte_offset = byte_offset; - byte_offset += g_register_infos[i].byte_size; - } - else - { - const uint32_t first_primordial_reg = g_register_infos[i].value_regs[0]; - g_register_infos[i].byte_offset = g_register_infos[first_primordial_reg].byte_offset; - } - } - } - for (i=0; i<num_registers; ++i) - { - ConstString name; - ConstString alt_name; - if (g_register_infos[i].name && g_register_infos[i].name[0]) - name.SetCString(g_register_infos[i].name); - if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0]) - alt_name.SetCString(g_register_infos[i].alt_name); - - if (i <= 15 || i == 25) - AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set); - else if (i <= 24) - AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set); - else - AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set); + // clang-format on + + static const uint32_t num_registers = llvm::array_lengthof(g_register_infos); + static ConstString gpr_reg_set("General Purpose Registers"); + static ConstString sfp_reg_set("Software Floating Point Registers"); + static ConstString vfp_reg_set("Floating Point Registers"); + size_t i; + if (from_scratch) { + // Calculate the offsets of the registers + // Note that the layout of the "composite" registers (d0-d15 and q0-q15) + // which comes after the + // "primordial" registers is important. This enables us to calculate the + // offset of the composite + // register by using the offset of its first primordial register. For + // example, to calculate the + // offset of q0, use s0's offset. + if (g_register_infos[2].byte_offset == 0) { + uint32_t byte_offset = 0; + for (i = 0; i < num_registers; ++i) { + // For primordial registers, increment the byte_offset by the byte_size + // to arrive at the + // byte_offset for the next register. Otherwise, we have a composite + // register whose + // offset can be calculated by consulting the offset of its first + // primordial register. + if (!g_register_infos[i].value_regs) { + g_register_infos[i].byte_offset = byte_offset; + byte_offset += g_register_infos[i].byte_size; + } else { + const uint32_t first_primordial_reg = + g_register_infos[i].value_regs[0]; + g_register_infos[i].byte_offset = + g_register_infos[first_primordial_reg].byte_offset; } + } } - else - { - // Add composite registers to our primordial registers, then. - const size_t num_composites = llvm::array_lengthof(g_composites); - const size_t num_dynamic_regs = GetNumRegisters(); - const size_t num_common_regs = num_registers - num_composites; - RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs; - - // First we need to validate that all registers that we already have match the non composite regs. - // If so, then we can add the registers, else we need to bail - bool match = true; - if (num_dynamic_regs == num_common_regs) - { - for (i=0; match && i<num_dynamic_regs; ++i) - { - // Make sure all register names match - if (m_regs[i].name && g_register_infos[i].name) - { - if (strcmp(m_regs[i].name, g_register_infos[i].name)) - { - match = false; - break; - } - } - - // Make sure all register byte sizes match - if (m_regs[i].byte_size != g_register_infos[i].byte_size) - { - match = false; - break; - } - } - } - else - { - // Wrong number of registers. + for (i = 0; i < num_registers; ++i) { + ConstString name; + ConstString alt_name; + if (g_register_infos[i].name && g_register_infos[i].name[0]) + name.SetCString(g_register_infos[i].name); + if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0]) + alt_name.SetCString(g_register_infos[i].alt_name); + + if (i <= 15 || i == 25) + AddRegister(g_register_infos[i], name, alt_name, gpr_reg_set); + else if (i <= 24) + AddRegister(g_register_infos[i], name, alt_name, sfp_reg_set); + else + AddRegister(g_register_infos[i], name, alt_name, vfp_reg_set); + } + } else { + // Add composite registers to our primordial registers, then. + const size_t num_composites = llvm::array_lengthof(g_composites); + const size_t num_dynamic_regs = GetNumRegisters(); + const size_t num_common_regs = num_registers - num_composites; + RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs; + + // First we need to validate that all registers that we already have match + // the non composite regs. + // If so, then we can add the registers, else we need to bail + bool match = true; + if (num_dynamic_regs == num_common_regs) { + for (i = 0; match && i < num_dynamic_regs; ++i) { + // Make sure all register names match + if (m_regs[i].name && g_register_infos[i].name) { + if (strcmp(m_regs[i].name, g_register_infos[i].name)) { match = false; + break; + } } - // If "match" is true, then we can add extra registers. - if (match) - { - for (i=0; i<num_composites; ++i) - { - ConstString name; - ConstString alt_name; - const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0]; - const char *reg_name = g_register_infos[first_primordial_reg].name; - if (reg_name && reg_name[0]) - { - for (uint32_t j = 0; j < num_dynamic_regs; ++j) - { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j); - // Find a matching primordial register info entry. - if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0) - { - // The name matches the existing primordial entry. - // Find and assign the offset, and then add this composite register entry. - g_comp_register_infos[i].byte_offset = reg_info->byte_offset; - name.SetCString(g_comp_register_infos[i].name); - AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set); - } - } - } + + // Make sure all register byte sizes match + if (m_regs[i].byte_size != g_register_infos[i].byte_size) { + match = false; + break; + } + } + } else { + // Wrong number of registers. + match = false; + } + // If "match" is true, then we can add extra registers. + if (match) { + for (i = 0; i < num_composites; ++i) { + ConstString name; + ConstString alt_name; + const uint32_t first_primordial_reg = + g_comp_register_infos[i].value_regs[0]; + const char *reg_name = g_register_infos[first_primordial_reg].name; + if (reg_name && reg_name[0]) { + for (uint32_t j = 0; j < num_dynamic_regs; ++j) { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j); + // Find a matching primordial register info entry. + if (reg_info && reg_info->name && + ::strcasecmp(reg_info->name, reg_name) == 0) { + // The name matches the existing primordial entry. + // Find and assign the offset, and then add this composite + // register entry. + g_comp_register_infos[i].byte_offset = reg_info->byte_offset; + name.SetCString(g_comp_register_infos[i].name); + AddRegister(g_comp_register_infos[i], name, alt_name, + vfp_reg_set); } + } } + } } + } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index c1d8249e5c4..5b3e04eb588 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -16,12 +16,12 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/lldb-enumerations.h" +#include "Plugins/Process/Utility/DynamicRegisterInfo.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Target/RegisterContext.h" -#include "Plugins/Process/Utility/DynamicRegisterInfo.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" #include "GDBRemoteCommunicationClient.h" @@ -33,130 +33,102 @@ namespace process_gdb_remote { class ThreadGDBRemote; class ProcessGDBRemote; -class GDBRemoteDynamicRegisterInfo : - public DynamicRegisterInfo -{ +class GDBRemoteDynamicRegisterInfo : public DynamicRegisterInfo { public: - GDBRemoteDynamicRegisterInfo () : - DynamicRegisterInfo() - { - } + GDBRemoteDynamicRegisterInfo() : DynamicRegisterInfo() {} - ~GDBRemoteDynamicRegisterInfo() override = default; + ~GDBRemoteDynamicRegisterInfo() override = default; - void - HardcodeARMRegisters(bool from_scratch); + void HardcodeARMRegisters(bool from_scratch); }; -class GDBRemoteRegisterContext : public RegisterContext -{ +class GDBRemoteRegisterContext : public RegisterContext { public: - GDBRemoteRegisterContext (ThreadGDBRemote &thread, - uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, - bool read_all_at_once); + GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx, + GDBRemoteDynamicRegisterInfo ®_info, + bool read_all_at_once); + + ~GDBRemoteRegisterContext() override; - ~GDBRemoteRegisterContext() override; + void InvalidateAllRegisters() override; - void - InvalidateAllRegisters () override; + size_t GetRegisterCount() override; - size_t - GetRegisterCount () override; + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - const RegisterInfo * - GetRegisterInfoAtIndex (size_t reg) override; + size_t GetRegisterSetCount() override; - size_t - GetRegisterSetCount () override; + const RegisterSet *GetRegisterSet(size_t reg_set) override; - const RegisterSet * - GetRegisterSet (size_t reg_set) override; + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) override; - bool - ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) override; + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) override; - bool - WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) override; - - bool - ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - bool - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - bool - ReadAllRegisterValues (RegisterCheckpoint ®_checkpoint) override; + bool ReadAllRegisterValues(RegisterCheckpoint ®_checkpoint) override; - bool - WriteAllRegisterValues (const RegisterCheckpoint ®_checkpoint) override; + bool + WriteAllRegisterValues(const RegisterCheckpoint ®_checkpoint) override; - uint32_t - ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) override; + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; protected: - friend class ThreadGDBRemote; + friend class ThreadGDBRemote; - bool - ReadRegisterBytes (const RegisterInfo *reg_info, - DataExtractor &data); + bool ReadRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data); - bool - WriteRegisterBytes (const RegisterInfo *reg_info, - DataExtractor &data, - uint32_t data_offset); + bool WriteRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data, + uint32_t data_offset); - bool - PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data); + bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data); - bool - PrivateSetRegisterValue (uint32_t reg, uint64_t val); + bool PrivateSetRegisterValue(uint32_t reg, uint64_t val); - void - SetAllRegisterValid (bool b); + void SetAllRegisterValid(bool b); - bool - GetRegisterIsValid (uint32_t reg) const - { -#if defined (LLDB_CONFIGURATION_DEBUG) - assert (reg < m_reg_valid.size()); + bool GetRegisterIsValid(uint32_t reg) const { +#if defined(LLDB_CONFIGURATION_DEBUG) + assert(reg < m_reg_valid.size()); #endif - if (reg < m_reg_valid.size()) - return m_reg_valid[reg]; - return false; - } - - void - SetRegisterIsValid (const RegisterInfo *reg_info, bool valid) - { - if (reg_info) - return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid); - } - - void - SetRegisterIsValid (uint32_t reg, bool valid) - { -#if defined (LLDB_CONFIGURATION_DEBUG) - assert (reg < m_reg_valid.size()); + if (reg < m_reg_valid.size()) + return m_reg_valid[reg]; + return false; + } + + void SetRegisterIsValid(const RegisterInfo *reg_info, bool valid) { + if (reg_info) + return SetRegisterIsValid(reg_info->kinds[lldb::eRegisterKindLLDB], + valid); + } + + void SetRegisterIsValid(uint32_t reg, bool valid) { +#if defined(LLDB_CONFIGURATION_DEBUG) + assert(reg < m_reg_valid.size()); #endif - if (reg < m_reg_valid.size()) - m_reg_valid[reg] = valid; - } + if (reg < m_reg_valid.size()) + m_reg_valid[reg] = valid; + } - GDBRemoteDynamicRegisterInfo &m_reg_info; - std::vector<bool> m_reg_valid; - DataExtractor m_reg_data; - bool m_read_all_at_once; + GDBRemoteDynamicRegisterInfo &m_reg_info; + std::vector<bool> m_reg_valid; + DataExtractor m_reg_data; + bool m_read_all_at_once; private: - // Helper function for ReadRegisterBytes(). - bool GetPrimordialRegister(const RegisterInfo *reg_info, - GDBRemoteCommunicationClient &gdb_comm); - // Helper function for WriteRegisterBytes(). - bool SetPrimordialRegister(const RegisterInfo *reg_info, - GDBRemoteCommunicationClient &gdb_comm); - - DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext); + // Helper function for ReadRegisterBytes(). + bool GetPrimordialRegister(const RegisterInfo *reg_info, + GDBRemoteCommunicationClient &gdb_comm); + // Helper function for WriteRegisterBytes(). + bool SetPrimordialRegister(const RegisterInfo *reg_info, + GDBRemoteCommunicationClient &gdb_comm); + + DISALLOW_COPY_AND_ASSIGN(GDBRemoteRegisterContext); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 3f7b64c8221..9e21e820dc7 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -14,7 +14,7 @@ #include <stdlib.h> #ifndef LLDB_DISABLE_POSIX #include <netinet/in.h> -#include <sys/mman.h> // for mmap +#include <sys/mman.h> // for mmap #include <sys/socket.h> #endif #include <sys/stat.h> @@ -28,11 +28,8 @@ #include <sstream> #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -42,6 +39,8 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/StringConvert.h" @@ -49,133 +48,111 @@ #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Host/XML.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionValueProperties.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/OptionGroupUInt64.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/Property.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/ThreadPlanCallFunction.h" -#include "lldb/Target/SystemRuntime.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/PseudoTerminal.h" // Project includes -#include "lldb/Host/Host.h" +#include "GDBRemoteRegisterContext.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "Plugins/Process/Utility/StopInfoMachException.h" -#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" -#include "Utility/StringExtractorGDBRemote.h" -#include "GDBRemoteRegisterContext.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "ThreadGDBRemote.h" +#include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Host/Host.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" -#define DEBUGSERVER_BASENAME "debugserver" +#define DEBUGSERVER_BASENAME "debugserver" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -namespace lldb -{ - // Provide a function that can easily dump the packet history if we know a - // ProcessGDBRemote * value (which we can get from logs or from debugging). - // We need the function in the lldb namespace so it makes it into the final - // executable since the LLDB shared library only exports stuff in the lldb - // namespace. This allows you to attach with a debugger and call this - // function and get the packet history dumped to a file. - void - DumpProcessGDBRemotePacketHistory (void *p, const char *path) - { - StreamFile strm; - Error error (strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)); - if (error.Success()) - ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory (strm); - } +namespace lldb { +// Provide a function that can easily dump the packet history if we know a +// ProcessGDBRemote * value (which we can get from logs or from debugging). +// We need the function in the lldb namespace so it makes it into the final +// executable since the LLDB shared library only exports stuff in the lldb +// namespace. This allows you to attach with a debugger and call this +// function and get the packet history dumped to a file. +void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { + StreamFile strm; + Error error(strm.GetFile().Open(path, File::eOpenOptionWrite | + File::eOpenOptionCanCreate)); + if (error.Success()) + ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); +} } namespace { - static PropertyDefinition - g_properties[] = - { - { "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." }, - { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." }, - { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL } - }; - - enum - { - ePropertyPacketTimeout, - ePropertyTargetDefinitionFile - }; - - class PluginProperties : public Properties - { - public: - - static ConstString - GetSettingName () - { - return ProcessGDBRemote::GetPluginNameStatic(); - } - - PluginProperties() : - Properties () - { - m_collection_sp.reset (new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } - - virtual - ~PluginProperties() - { - } +static PropertyDefinition g_properties[] = { + {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL, + "Specify the default packet timeout in seconds."}, + {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL, + "The file that provides the description for remote target registers."}, + {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; - uint64_t - GetPacketTimeout() - { - const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value); - } +enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; - bool - SetPacketTimeout(uint64_t timeout) - { - const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout); - } - - FileSpec - GetTargetDefinitionFile () const - { - const uint32_t idx = ePropertyTargetDefinitionFile; - return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx); - } - }; +class PluginProperties : public Properties { +public: + static ConstString GetSettingName() { + return ProcessGDBRemote::GetPluginNameStatic(); + } + + PluginProperties() : Properties() { + m_collection_sp.reset(new OptionValueProperties(GetSettingName())); + m_collection_sp->Initialize(g_properties); + } + + virtual ~PluginProperties() {} + + uint64_t GetPacketTimeout() { + const uint32_t idx = ePropertyPacketTimeout; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + NULL, idx, g_properties[idx].default_uint_value); + } + + bool SetPacketTimeout(uint64_t timeout) { + const uint32_t idx = ePropertyPacketTimeout; + return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout); + } + + FileSpec GetTargetDefinitionFile() const { + const uint32_t idx = ePropertyTargetDefinitionFile; + return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx); + } +}; - typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; +typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; - static const ProcessKDPPropertiesSP & - GetGlobalPluginProperties() - { - static ProcessKDPPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset (new PluginProperties ()); - return g_settings_sp; - } +static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { + static ProcessKDPPropertiesSP g_settings_sp; + if (!g_settings_sp) + g_settings_sp.reset(new PluginProperties()); + return g_settings_sp; +} } // anonymous namespace end @@ -183,3870 +160,3561 @@ namespace { // ephemeral port from the kernel and make sure we reserve it before passing // it to debugserver. -#if defined (__APPLE__) -#define LOW_PORT (IPPORT_RESERVED) -#define HIGH_PORT (IPPORT_HIFIRSTAUTO) +#if defined(__APPLE__) +#define LOW_PORT (IPPORT_RESERVED) +#define HIGH_PORT (IPPORT_HIFIRSTAUTO) #else -#define LOW_PORT (1024u) -#define HIGH_PORT (49151u) +#define LOW_PORT (1024u) +#define HIGH_PORT (49151u) #endif -#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) +#if defined(__APPLE__) && \ + (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) static bool rand_initialized = false; -static inline uint16_t -get_random_port () -{ - if (!rand_initialized) - { - time_t seed = time(NULL); +static inline uint16_t get_random_port() { + if (!rand_initialized) { + time_t seed = time(NULL); - rand_initialized = true; - srand(seed); - } - return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT; + rand_initialized = true; + srand(seed); + } + return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT; } #endif -ConstString -ProcessGDBRemote::GetPluginNameStatic() -{ - static ConstString g_name("gdb-remote"); - return g_name; +ConstString ProcessGDBRemote::GetPluginNameStatic() { + static ConstString g_name("gdb-remote"); + return g_name; } -const char * -ProcessGDBRemote::GetPluginDescriptionStatic() -{ - return "GDB Remote protocol based debugging plug-in."; +const char *ProcessGDBRemote::GetPluginDescriptionStatic() { + return "GDB Remote protocol based debugging plug-in."; } -void -ProcessGDBRemote::Terminate() -{ - PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance); +void ProcessGDBRemote::Terminate() { + PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance); } - lldb::ProcessSP -ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) -{ - lldb::ProcessSP process_sp; - if (crash_file_path == NULL) - process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp)); - return process_sp; +ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec *crash_file_path) { + lldb::ProcessSP process_sp; + if (crash_file_path == NULL) + process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp)); + return process_sp; } -bool -ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - Module *exe_module = target_sp->GetExecutableModulePointer(); - if (exe_module) - { - ObjectFile *exe_objfile = exe_module->GetObjectFile(); - // We can't debug core files... - switch (exe_objfile->GetType()) - { - case ObjectFile::eTypeInvalid: - case ObjectFile::eTypeCoreFile: - case ObjectFile::eTypeDebugInfo: - case ObjectFile::eTypeObjectFile: - case ObjectFile::eTypeSharedLibrary: - case ObjectFile::eTypeStubLibrary: - case ObjectFile::eTypeJIT: - return false; - case ObjectFile::eTypeExecutable: - case ObjectFile::eTypeDynamicLinker: - case ObjectFile::eTypeUnknown: - break; - } - return exe_module->GetFileSpec().Exists(); - } - // However, if there is no executable module, we return true since we might be preparing to attach. +bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + if (plugin_specified_by_name) return true; + + // For now we are just making sure the file exists for a given module + Module *exe_module = target_sp->GetExecutableModulePointer(); + if (exe_module) { + ObjectFile *exe_objfile = exe_module->GetObjectFile(); + // We can't debug core files... + switch (exe_objfile->GetType()) { + case ObjectFile::eTypeInvalid: + case ObjectFile::eTypeCoreFile: + case ObjectFile::eTypeDebugInfo: + case ObjectFile::eTypeObjectFile: + case ObjectFile::eTypeSharedLibrary: + case ObjectFile::eTypeStubLibrary: + case ObjectFile::eTypeJIT: + return false; + case ObjectFile::eTypeExecutable: + case ObjectFile::eTypeDynamicLinker: + case ObjectFile::eTypeUnknown: + break; + } + return exe_module->GetFileSpec().Exists(); + } + // However, if there is no executable module, we return true since we might be + // preparing to attach. + return true; } //---------------------------------------------------------------------- // ProcessGDBRemote constructor //---------------------------------------------------------------------- -ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) - : Process(target_sp, listener_sp), - m_flags(0), - m_gdb_comm(), - m_debugserver_pid(LLDB_INVALID_PROCESS_ID), - m_last_stop_packet_mutex(), +ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, + ListenerSP listener_sp) + : Process(target_sp, listener_sp), m_flags(0), m_gdb_comm(), + m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info(), m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), - m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")), - m_async_thread_state_mutex(), - m_thread_ids(), - m_thread_pcs(), - m_jstopinfo_sp(), - m_jthreadsinfo_sp(), - m_continue_c_tids(), - m_continue_C_tids(), - m_continue_s_tids(), - m_continue_S_tids(), - m_max_memory_size(0), - m_remote_stub_max_memory_size(0), - m_addr_to_mmap_size(), - m_thread_create_bp_sp(), - m_waiting_for_attach(false), - m_destroy_tried_resuming(false), - m_command_sp(), - m_breakpoint_pc_offset(0), - m_initial_tid(LLDB_INVALID_THREAD_ID) -{ - m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); - m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue"); - m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit"); - - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); - - const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; - - if (m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask) - { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__); - } - - const uint32_t gdb_event_mask = - Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; - if (m_async_listener_sp->StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask) - { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__); - } - - const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout(); - if (timeout_seconds > 0) - m_gdb_comm.SetPacketTimeout(timeout_seconds); + m_async_listener_sp( + Listener::MakeListener("lldb.process.gdb-remote.async-listener")), + m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), + m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(), + m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(), + m_max_memory_size(0), m_remote_stub_max_memory_size(0), + m_addr_to_mmap_size(), m_thread_create_bp_sp(), + m_waiting_for_attach(false), m_destroy_tried_resuming(false), + m_command_sp(), m_breakpoint_pc_offset(0), + m_initial_tid(LLDB_INVALID_THREAD_ID) { + m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, + "async thread should exit"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, + "async thread continue"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, + "async thread did exit"); + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); + + const uint32_t async_event_mask = + eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; + + if (m_async_listener_sp->StartListeningForEvents( + &m_async_broadcaster, async_event_mask) != async_event_mask) { + if (log) + log->Printf("ProcessGDBRemote::%s failed to listen for " + "m_async_broadcaster events", + __FUNCTION__); + } + + const uint32_t gdb_event_mask = + Communication::eBroadcastBitReadThreadDidExit | + GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; + if (m_async_listener_sp->StartListeningForEvents( + &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { + if (log) + log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", + __FUNCTION__); + } + + const uint64_t timeout_seconds = + GetGlobalPluginProperties()->GetPacketTimeout(); + if (timeout_seconds > 0) + m_gdb_comm.SetPacketTimeout(timeout_seconds); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ProcessGDBRemote::~ProcessGDBRemote() -{ - // m_mach_process.UnregisterNotificationCallbacks (this); - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); - - // The general Finalize is going to try to destroy the process and that SHOULD - // shut down the async thread. However, if we don't kill it it will get stranded and - // its connection will go away so when it wakes up it will crash. So kill it for sure here. - StopAsyncThread(); - KillDebugserverProcess(); +ProcessGDBRemote::~ProcessGDBRemote() { + // m_mach_process.UnregisterNotificationCallbacks (this); + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); + + // The general Finalize is going to try to destroy the process and that SHOULD + // shut down the async thread. However, if we don't kill it it will get + // stranded and + // its connection will go away so when it wakes up it will crash. So kill it + // for sure here. + StopAsyncThread(); + KillDebugserverProcess(); } //---------------------------------------------------------------------- // PluginInterface //---------------------------------------------------------------------- -ConstString -ProcessGDBRemote::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessGDBRemote::GetPluginVersion() -{ - return 1; -} - -bool -ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec) -{ - ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - Error error; - StructuredData::ObjectSP module_object_sp(interpreter->LoadPluginModule(target_definition_fspec, error)); - if (module_object_sp) - { - StructuredData::DictionarySP target_definition_sp( - interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), "gdb-server-target-definition", error)); - - if (target_definition_sp) - { - StructuredData::ObjectSP target_object(target_definition_sp->GetValueForKey("host-info")); - if (target_object) - { - if (auto host_info_dict = target_object->GetAsDictionary()) - { - StructuredData::ObjectSP triple_value = host_info_dict->GetValueForKey("triple"); - if (auto triple_string_value = triple_value->GetAsString()) - { - std::string triple_string = triple_string_value->GetValue(); - ArchSpec host_arch(triple_string.c_str()); - if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) - { - GetTarget().SetArchitecture(host_arch); - } - } - } - } - m_breakpoint_pc_offset = 0; - StructuredData::ObjectSP breakpoint_pc_offset_value = target_definition_sp->GetValueForKey("breakpoint-pc-offset"); - if (breakpoint_pc_offset_value) - { - if (auto breakpoint_pc_int_value = breakpoint_pc_offset_value->GetAsInteger()) - m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); - } - - if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0) - { - return true; +ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } + +uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; } + +bool ProcessGDBRemote::ParsePythonTargetDefinition( + const FileSpec &target_definition_fspec) { + ScriptInterpreter *interpreter = + GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + Error error; + StructuredData::ObjectSP module_object_sp( + interpreter->LoadPluginModule(target_definition_fspec, error)); + if (module_object_sp) { + StructuredData::DictionarySP target_definition_sp( + interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), + "gdb-server-target-definition", error)); + + if (target_definition_sp) { + StructuredData::ObjectSP target_object( + target_definition_sp->GetValueForKey("host-info")); + if (target_object) { + if (auto host_info_dict = target_object->GetAsDictionary()) { + StructuredData::ObjectSP triple_value = + host_info_dict->GetValueForKey("triple"); + if (auto triple_string_value = triple_value->GetAsString()) { + std::string triple_string = triple_string_value->GetValue(); + ArchSpec host_arch(triple_string.c_str()); + if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) { + GetTarget().SetArchitecture(host_arch); } + } } + } + m_breakpoint_pc_offset = 0; + StructuredData::ObjectSP breakpoint_pc_offset_value = + target_definition_sp->GetValueForKey("breakpoint-pc-offset"); + if (breakpoint_pc_offset_value) { + if (auto breakpoint_pc_int_value = + breakpoint_pc_offset_value->GetAsInteger()) + m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); + } + + if (m_register_info.SetRegisterInfo(*target_definition_sp, + GetTarget().GetArchitecture()) > 0) { + return true; + } } - return false; + } + return false; } -// If the remote stub didn't give us eh_frame or DWARF register numbers for a register, +// If the remote stub didn't give us eh_frame or DWARF register numbers for a +// register, // see if the ABI can provide them. // DWARF and eh_frame register numbers are defined as a part of the ABI. -static void -AugmentRegisterInfoViaABI (RegisterInfo ®_info, ConstString reg_name, ABISP abi_sp) -{ - if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM - || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) - { - if (abi_sp) - { - RegisterInfo abi_reg_info; - if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info)) - { - if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) - { - reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame]; - } - if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) - { - reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF]; - } - if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && - abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) - { - reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric]; - } - } - } - } -} - -static size_t -SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> ®nums, int base) -{ - regnums.clear(); - std::pair<llvm::StringRef, llvm::StringRef> value_pair; - value_pair.second = comma_separated_regiter_numbers; - do - { - value_pair = value_pair.second.split(','); - if (!value_pair.first.empty()) - { - uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, base); - if (reg != LLDB_INVALID_REGNUM) - regnums.push_back (reg); +static void AugmentRegisterInfoViaABI(RegisterInfo ®_info, + ConstString reg_name, ABISP abi_sp) { + if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM || + reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) { + if (abi_sp) { + RegisterInfo abi_reg_info; + if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) { + if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && + abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) { + reg_info.kinds[eRegisterKindEHFrame] = + abi_reg_info.kinds[eRegisterKindEHFrame]; } - } while (!value_pair.second.empty()); - return regnums.size(); -} - - -void -ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) -{ - if (!force && m_register_info.GetNumRegisters() > 0) - return; - - m_register_info.Clear(); - - // Check if qHostInfo specified a specific packet timeout for this connection. - // If so then lets update our setting so the user knows what the timeout is - // and can see it. - const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); - if (host_packet_timeout) - { - GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout); - } - - // Register info search order: - // 1 - Use the target definition python file if one is specified. - // 2 - If the target definition doesn't have any of the info from the target.xml (registers) then proceed to read the target.xml. - // 3 - Fall back on the qRegisterInfo packets. - - FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile (); - if (!target_definition_fspec.Exists()) - { - // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it. - target_definition_fspec.ResolvePath(); - } - if (target_definition_fspec) - { - // See if we can get register definitions from a python file - if (ParsePythonTargetDefinition (target_definition_fspec)) - { - return; + if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && + abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) { + reg_info.kinds[eRegisterKindDWARF] = + abi_reg_info.kinds[eRegisterKindDWARF]; } - else - { - StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); - stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str()); + if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && + abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { + reg_info.kinds[eRegisterKindGeneric] = + abi_reg_info.kinds[eRegisterKindGeneric]; } + } } + } +} - const ArchSpec &target_arch = GetTarget().GetArchitecture(); - const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); - const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); +static size_t SplitCommaSeparatedRegisterNumberString( + const llvm::StringRef &comma_separated_regiter_numbers, + std::vector<uint32_t> ®nums, int base) { + regnums.clear(); + std::pair<llvm::StringRef, llvm::StringRef> value_pair; + value_pair.second = comma_separated_regiter_numbers; + do { + value_pair = value_pair.second.split(','); + if (!value_pair.first.empty()) { + uint32_t reg = StringConvert::ToUInt32(value_pair.first.str().c_str(), + LLDB_INVALID_REGNUM, base); + if (reg != LLDB_INVALID_REGNUM) + regnums.push_back(reg); + } + } while (!value_pair.second.empty()); + return regnums.size(); +} - // Use the process' architecture instead of the host arch, if available - ArchSpec arch_to_use; - if (remote_process_arch.IsValid ()) - arch_to_use = remote_process_arch; - else - arch_to_use = remote_host_arch; - - if (!arch_to_use.IsValid()) - arch_to_use = target_arch; - - if (GetGDBServerRegisterInfo (arch_to_use)) - return; - - char packet[128]; - uint32_t reg_offset = 0; - uint32_t reg_num = 0; - for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse; - response_type == StringExtractorGDBRemote::eResponse; - ++reg_num) - { - const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num); - assert (packet_len < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success) - { - response_type = response.GetResponseType(); - if (response_type == StringExtractorGDBRemote::eResponse) +void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { + if (!force && m_register_info.GetNumRegisters() > 0) + return; + + m_register_info.Clear(); + + // Check if qHostInfo specified a specific packet timeout for this connection. + // If so then lets update our setting so the user knows what the timeout is + // and can see it. + const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); + if (host_packet_timeout) { + GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout); + } + + // Register info search order: + // 1 - Use the target definition python file if one is specified. + // 2 - If the target definition doesn't have any of the info from the + // target.xml (registers) then proceed to read the target.xml. + // 3 - Fall back on the qRegisterInfo packets. + + FileSpec target_definition_fspec = + GetGlobalPluginProperties()->GetTargetDefinitionFile(); + if (!target_definition_fspec.Exists()) { + // If the filename doesn't exist, it may be a ~ not having been expanded - + // try to resolve it. + target_definition_fspec.ResolvePath(); + } + if (target_definition_fspec) { + // See if we can get register definitions from a python file + if (ParsePythonTargetDefinition(target_definition_fspec)) { + return; + } else { + StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); + stream_sp->Printf("ERROR: target description file %s failed to parse.\n", + target_definition_fspec.GetPath().c_str()); + } + } + + const ArchSpec &target_arch = GetTarget().GetArchitecture(); + const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + + // Use the process' architecture instead of the host arch, if available + ArchSpec arch_to_use; + if (remote_process_arch.IsValid()) + arch_to_use = remote_process_arch; + else + arch_to_use = remote_host_arch; + + if (!arch_to_use.IsValid()) + arch_to_use = target_arch; + + if (GetGDBServerRegisterInfo(arch_to_use)) + return; + + char packet[128]; + uint32_t reg_offset = 0; + uint32_t reg_num = 0; + for (StringExtractorGDBRemote::ResponseType response_type = + StringExtractorGDBRemote::eResponse; + response_type == StringExtractorGDBRemote::eResponse; ++reg_num) { + const int packet_len = + ::snprintf(packet, sizeof(packet), "qRegisterInfo%x", reg_num); + assert(packet_len < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, + false) == + GDBRemoteCommunication::PacketResult::Success) { + response_type = response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + llvm::StringRef name; + llvm::StringRef value; + ConstString reg_name; + ConstString alt_name; + ConstString set_name; + std::vector<uint32_t> value_regs; + std::vector<uint32_t> invalidate_regs; + std::vector<uint8_t> dwarf_opcode_bytes; + RegisterInfo reg_info = { + NULL, // Name + NULL, // Alt name + 0, // byte size + reg_offset, // offset + eEncodingUint, // encoding + eFormatHex, // format { - llvm::StringRef name; - llvm::StringRef value; - ConstString reg_name; - ConstString alt_name; - ConstString set_name; - std::vector<uint32_t> value_regs; - std::vector<uint32_t> invalidate_regs; - std::vector<uint8_t> dwarf_opcode_bytes; - RegisterInfo reg_info = { NULL, // Name - NULL, // Alt name - 0, // byte size - reg_offset, // offset - eEncodingUint, // encoding - eFormatHex, // format - { - LLDB_INVALID_REGNUM, // eh_frame reg num - LLDB_INVALID_REGNUM, // DWARF reg num - LLDB_INVALID_REGNUM, // generic reg num - reg_num, // process plugin reg num - reg_num // native register number - }, - NULL, - NULL, - NULL, // Dwarf expression opcode bytes pointer - 0 // Dwarf expression opcode bytes length - }; - - while (response.GetNameColonValue(name, value)) - { - if (name.equals("name")) - { - reg_name.SetString(value); - } - else if (name.equals("alt-name")) - { - alt_name.SetString(value); - } - else if (name.equals("bitsize")) - { - value.getAsInteger(0, reg_info.byte_size); - reg_info.byte_size /= CHAR_BIT; - } - else if (name.equals("offset")) - { - if (value.getAsInteger(0, reg_offset)) - reg_offset = UINT32_MAX; - } - else if (name.equals("encoding")) - { - const Encoding encoding = Args::StringToEncoding(value); - if (encoding != eEncodingInvalid) - reg_info.encoding = encoding; - } - else if (name.equals("format")) - { - Format format = eFormatInvalid; - if (Args::StringToFormat(value.str().c_str(), format, NULL).Success()) - reg_info.format = format; - else - { - reg_info.format = llvm::StringSwitch<Format>(value) - .Case("binary", eFormatBinary) - .Case("decimal", eFormatDecimal) - .Case("hex", eFormatHex) - .Case("float", eFormatFloat) - .Case("vector-sint8", eFormatVectorOfSInt8) - .Case("vector-uint8", eFormatVectorOfUInt8) - .Case("vector-sint16", eFormatVectorOfSInt16) - .Case("vector-uint16", eFormatVectorOfUInt16) - .Case("vector-sint32", eFormatVectorOfSInt32) - .Case("vector-uint32", eFormatVectorOfUInt32) - .Case("vector-float32", eFormatVectorOfFloat32) - .Case("vector-uint128", eFormatVectorOfUInt128) - .Default(eFormatInvalid); - } - } - else if (name.equals("set")) - { - set_name.SetString(value); - } - else if (name.equals("gcc") || name.equals("ehframe")) - { - if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame])) - reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; - } - else if (name.equals("dwarf")) - { - if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF])) - reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; - } - else if (name.equals("generic")) - { - reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value); - } - else if (name.equals("container-regs")) - { - SplitCommaSeparatedRegisterNumberString(value, value_regs, 16); - } - else if (name.equals("invalidate-regs")) - { - SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16); - } - else if (name.equals("dynamic_size_dwarf_expr_bytes")) - { - size_t dwarf_opcode_len = value.size() / 2; - assert(dwarf_opcode_len > 0); - - dwarf_opcode_bytes.resize(dwarf_opcode_len); - reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; - - StringExtractor opcode_extractor(value); - uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); - assert(dwarf_opcode_len == ret_val); - - reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); - } - } - - reg_info.byte_offset = reg_offset; - assert (reg_info.byte_size != 0); - reg_offset += reg_info.byte_size; - if (!value_regs.empty()) - { - value_regs.push_back(LLDB_INVALID_REGNUM); - reg_info.value_regs = value_regs.data(); - } - if (!invalidate_regs.empty()) - { - invalidate_regs.push_back(LLDB_INVALID_REGNUM); - reg_info.invalidate_regs = invalidate_regs.data(); - } - - // We have to make a temporary ABI here, and not use the GetABI because this code - // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from - // the process) may be wrong. - ABISP abi_to_use = ABI::FindPlugin(arch_to_use); - - AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use); + LLDB_INVALID_REGNUM, // eh_frame reg num + LLDB_INVALID_REGNUM, // DWARF reg num + LLDB_INVALID_REGNUM, // generic reg num + reg_num, // process plugin reg num + reg_num // native register number + }, + NULL, + NULL, + NULL, // Dwarf expression opcode bytes pointer + 0 // Dwarf expression opcode bytes length + }; - m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); - } - else - { - break; // ensure exit before reg_num is incremented + while (response.GetNameColonValue(name, value)) { + if (name.equals("name")) { + reg_name.SetString(value); + } else if (name.equals("alt-name")) { + alt_name.SetString(value); + } else if (name.equals("bitsize")) { + value.getAsInteger(0, reg_info.byte_size); + reg_info.byte_size /= CHAR_BIT; + } else if (name.equals("offset")) { + if (value.getAsInteger(0, reg_offset)) + reg_offset = UINT32_MAX; + } else if (name.equals("encoding")) { + const Encoding encoding = Args::StringToEncoding(value); + if (encoding != eEncodingInvalid) + reg_info.encoding = encoding; + } else if (name.equals("format")) { + Format format = eFormatInvalid; + if (Args::StringToFormat(value.str().c_str(), format, NULL) + .Success()) + reg_info.format = format; + else { + reg_info.format = + llvm::StringSwitch<Format>(value) + .Case("binary", eFormatBinary) + .Case("decimal", eFormatDecimal) + .Case("hex", eFormatHex) + .Case("float", eFormatFloat) + .Case("vector-sint8", eFormatVectorOfSInt8) + .Case("vector-uint8", eFormatVectorOfUInt8) + .Case("vector-sint16", eFormatVectorOfSInt16) + .Case("vector-uint16", eFormatVectorOfUInt16) + .Case("vector-sint32", eFormatVectorOfSInt32) + .Case("vector-uint32", eFormatVectorOfUInt32) + .Case("vector-float32", eFormatVectorOfFloat32) + .Case("vector-uint128", eFormatVectorOfUInt128) + .Default(eFormatInvalid); } + } else if (name.equals("set")) { + set_name.SetString(value); + } else if (name.equals("gcc") || name.equals("ehframe")) { + if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame])) + reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; + } else if (name.equals("dwarf")) { + if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF])) + reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; + } else if (name.equals("generic")) { + reg_info.kinds[eRegisterKindGeneric] = + Args::StringToGenericRegister(value); + } else if (name.equals("container-regs")) { + SplitCommaSeparatedRegisterNumberString(value, value_regs, 16); + } else if (name.equals("invalidate-regs")) { + SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16); + } else if (name.equals("dynamic_size_dwarf_expr_bytes")) { + size_t dwarf_opcode_len = value.size() / 2; + assert(dwarf_opcode_len > 0); + + dwarf_opcode_bytes.resize(dwarf_opcode_len); + reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; + + StringExtractor opcode_extractor(value); + uint32_t ret_val = + opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); + assert(dwarf_opcode_len == ret_val); + + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); + } } - else - { - break; - } - } - if (m_register_info.GetNumRegisters() > 0) - { - m_register_info.Finalize(GetTarget().GetArchitecture()); - return; - } + reg_info.byte_offset = reg_offset; + assert(reg_info.byte_size != 0); + reg_offset += reg_info.byte_size; + if (!value_regs.empty()) { + value_regs.push_back(LLDB_INVALID_REGNUM); + reg_info.value_regs = value_regs.data(); + } + if (!invalidate_regs.empty()) { + invalidate_regs.push_back(LLDB_INVALID_REGNUM); + reg_info.invalidate_regs = invalidate_regs.data(); + } - // We didn't get anything if the accumulated reg_num is zero. See if we are - // debugging ARM and fill with a hard coded register set until we can get an - // updated debugserver down on the devices. - // On the other hand, if the accumulated reg_num is positive, see if we can - // add composite registers to the existing primordial ones. - bool from_scratch = (m_register_info.GetNumRegisters() == 0); + // We have to make a temporary ABI here, and not use the GetABI because + // this code + // gets called in DidAttach, when the target architecture (and + // consequently the ABI we'll get from + // the process) may be wrong. + ABISP abi_to_use = ABI::FindPlugin(arch_to_use); - if (!target_arch.IsValid()) - { - if (arch_to_use.IsValid() - && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) - && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) - m_register_info.HardcodeARMRegisters(from_scratch); - } - else if (target_arch.GetMachine() == llvm::Triple::arm - || target_arch.GetMachine() == llvm::Triple::thumb) - { - m_register_info.HardcodeARMRegisters(from_scratch); - } + AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use); - // At this point, we can finalize our register info. - m_register_info.Finalize (GetTarget().GetArchitecture()); + m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); + } else { + break; // ensure exit before reg_num is incremented + } + } else { + break; + } + } + + if (m_register_info.GetNumRegisters() > 0) { + m_register_info.Finalize(GetTarget().GetArchitecture()); + return; + } + + // We didn't get anything if the accumulated reg_num is zero. See if we are + // debugging ARM and fill with a hard coded register set until we can get an + // updated debugserver down on the devices. + // On the other hand, if the accumulated reg_num is positive, see if we can + // add composite registers to the existing primordial ones. + bool from_scratch = (m_register_info.GetNumRegisters() == 0); + + if (!target_arch.IsValid()) { + if (arch_to_use.IsValid() && + (arch_to_use.GetMachine() == llvm::Triple::arm || + arch_to_use.GetMachine() == llvm::Triple::thumb) && + arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) + m_register_info.HardcodeARMRegisters(from_scratch); + } else if (target_arch.GetMachine() == llvm::Triple::arm || + target_arch.GetMachine() == llvm::Triple::thumb) { + m_register_info.HardcodeARMRegisters(from_scratch); + } + + // At this point, we can finalize our register info. + m_register_info.Finalize(GetTarget().GetArchitecture()); } -Error -ProcessGDBRemote::WillLaunch (Module* module) -{ - return WillLaunchOrAttach (); +Error ProcessGDBRemote::WillLaunch(Module *module) { + return WillLaunchOrAttach(); } -Error -ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid) -{ - return WillLaunchOrAttach (); +Error ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) { + return WillLaunchOrAttach(); } -Error -ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) -{ - return WillLaunchOrAttach (); +Error ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { + return WillLaunchOrAttach(); } -Error -ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - Error error (WillLaunchOrAttach ()); - - if (error.Fail()) - return error; - - error = ConnectToDebugserver (remote_url); - - if (error.Fail()) - return error; - StartAsyncThread (); - - lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID (); - if (pid == LLDB_INVALID_PROCESS_ID) - { - // We don't have a valid process ID, so note that we are connected - // and could now request to launch or attach, or get remote process - // listings... - SetPrivateState (eStateConnected); - } - else - { - // We have a valid process - SetID (pid); - GetThreadList(); - StringExtractorGDBRemote response; - if (m_gdb_comm.GetStopReply(response)) - { - SetLastStopPacket(response); +Error ProcessGDBRemote::DoConnectRemote(Stream *strm, const char *remote_url) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Error error(WillLaunchOrAttach()); - // '?' Packets must be handled differently in non-stop mode - if (GetTarget().GetNonStopModeEnabled()) - HandleStopReplySequence(); + if (error.Fail()) + return error; - Target &target = GetTarget(); - if (!target.GetArchitecture().IsValid()) - { - if (m_gdb_comm.GetProcessArchitecture().IsValid()) - { - target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); - } - else - { - target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); - } - } + error = ConnectToDebugserver(remote_url); - const StateType state = SetThreadStopInfo (response); - if (state != eStateInvalid) - { - SetPrivateState (state); - } - else - error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state)); + if (error.Fail()) + return error; + StartAsyncThread(); + + lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); + if (pid == LLDB_INVALID_PROCESS_ID) { + // We don't have a valid process ID, so note that we are connected + // and could now request to launch or attach, or get remote process + // listings... + SetPrivateState(eStateConnected); + } else { + // We have a valid process + SetID(pid); + GetThreadList(); + StringExtractorGDBRemote response; + if (m_gdb_comm.GetStopReply(response)) { + SetLastStopPacket(response); + + // '?' Packets must be handled differently in non-stop mode + if (GetTarget().GetNonStopModeEnabled()) + HandleStopReplySequence(); + + Target &target = GetTarget(); + if (!target.GetArchitecture().IsValid()) { + if (m_gdb_comm.GetProcessArchitecture().IsValid()) { + target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); + } else { + target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); } - else - error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url); - } - - if (log) - log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false"); - - - if (error.Success() - && !GetTarget().GetArchitecture().IsValid() - && m_gdb_comm.GetHostArchitecture().IsValid()) - { - // Prefer the *process'* architecture over that of the *host*, if available. - if (m_gdb_comm.GetProcessArchitecture().IsValid()) - GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture()); - else - GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); - } - - if (log) - log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ()); - - if (error.Success()) - { - PlatformSP platform_sp = GetTarget().GetPlatform(); - if (platform_sp && platform_sp->IsConnected()) - SetUnixSignals(platform_sp->GetUnixSignals()); - else - SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture())); - } + } + + const StateType state = SetThreadStopInfo(response); + if (state != eStateInvalid) { + SetPrivateState(state); + } else + error.SetErrorStringWithFormat("Process %" PRIu64 + " was reported after connecting to " + "'%s', but state was not stopped: %s", + pid, remote_url, StateAsCString(state)); + } else + error.SetErrorStringWithFormat("Process %" PRIu64 + " was reported after connecting to '%s', " + "but no stop reply packet was received", + pid, remote_url); + } + + if (log) + log->Printf("ProcessGDBRemote::%s pid %" PRIu64 + ": normalizing target architecture initial triple: %s " + "(GetTarget().GetArchitecture().IsValid() %s, " + "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), + GetTarget().GetArchitecture().IsValid() ? "true" : "false", + m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); + + if (error.Success() && !GetTarget().GetArchitecture().IsValid() && + m_gdb_comm.GetHostArchitecture().IsValid()) { + // Prefer the *process'* architecture over that of the *host*, if available. + if (m_gdb_comm.GetProcessArchitecture().IsValid()) + GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture()); + else + GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); + } + + if (log) + log->Printf("ProcessGDBRemote::%s pid %" PRIu64 + ": normalized target architecture triple: %s", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); + + if (error.Success()) { + PlatformSP platform_sp = GetTarget().GetPlatform(); + if (platform_sp && platform_sp->IsConnected()) + SetUnixSignals(platform_sp->GetUnixSignals()); + else + SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture())); + } - return error; + return error; } -Error -ProcessGDBRemote::WillLaunchOrAttach () -{ - Error error; - m_stdio_communication.Clear (); - return error; +Error ProcessGDBRemote::WillLaunchOrAttach() { + Error error; + m_stdio_communication.Clear(); + return error; } //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- -Error -ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - Error error; - - if (log) - log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__); - - uint32_t launch_flags = launch_info.GetFlags().Get(); - FileSpec stdin_file_spec{}; - FileSpec stdout_file_spec{}; - FileSpec stderr_file_spec{}; - FileSpec working_dir = launch_info.GetWorkingDirectory(); - - const FileAction *file_action; - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - if (file_action) - { - if (file_action->GetAction() == FileAction::eFileActionOpen) - stdin_file_spec = file_action->GetFileSpec(); - } - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - if (file_action) - { - if (file_action->GetAction() == FileAction::eFileActionOpen) - stdout_file_spec = file_action->GetFileSpec(); - } - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - if (file_action) - { - if (file_action->GetAction() == FileAction::eFileActionOpen) - stderr_file_spec = file_action->GetFileSpec(); - } - - if (log) - { - if (stdin_file_spec || stdout_file_spec || stderr_file_spec) - log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); - else - log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__); - } - - const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; - if (stdin_file_spec || disable_stdio) - { - // the inferior will be reading stdin from the specified file - // or stdio is completely disabled - m_stdin_forward = false; - } +Error ProcessGDBRemote::DoLaunch(Module *exe_module, + ProcessLaunchInfo &launch_info) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Error error; + + if (log) + log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__); + + uint32_t launch_flags = launch_info.GetFlags().Get(); + FileSpec stdin_file_spec{}; + FileSpec stdout_file_spec{}; + FileSpec stderr_file_spec{}; + FileSpec working_dir = launch_info.GetWorkingDirectory(); + + const FileAction *file_action; + file_action = launch_info.GetFileActionForFD(STDIN_FILENO); + if (file_action) { + if (file_action->GetAction() == FileAction::eFileActionOpen) + stdin_file_spec = file_action->GetFileSpec(); + } + file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); + if (file_action) { + if (file_action->GetAction() == FileAction::eFileActionOpen) + stdout_file_spec = file_action->GetFileSpec(); + } + file_action = launch_info.GetFileActionForFD(STDERR_FILENO); + if (file_action) { + if (file_action->GetAction() == FileAction::eFileActionOpen) + stderr_file_spec = file_action->GetFileSpec(); + } + + if (log) { + if (stdin_file_spec || stdout_file_spec || stderr_file_spec) + log->Printf("ProcessGDBRemote::%s provided with STDIO paths via " + "launch_info: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); else - { - m_stdin_forward = true; - } - - // ::LogSetBitMask (GDBR_LOG_DEFAULT); - // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); - // ::LogSetLogFile ("/dev/stdout"); - - ObjectFile * object_file = exe_module->GetObjectFile(); - if (object_file) - { - error = EstablishConnectionIfNeeded (launch_info); - if (error.Success()) - { - lldb_utility::PseudoTerminal pty; - const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; - - PlatformSP platform_sp (GetTarget().GetPlatform()); - if (disable_stdio) - { - // set to /dev/null unless redirected to a file above - if (!stdin_file_spec) - stdin_file_spec.SetFile(FileSystem::DEV_NULL, false); - if (!stdout_file_spec) - stdout_file_spec.SetFile(FileSystem::DEV_NULL, false); - if (!stderr_file_spec) - stderr_file_spec.SetFile(FileSystem::DEV_NULL, false); - } - else if (platform_sp && platform_sp->IsHost()) - { - // If the debugserver is local and we aren't disabling STDIO, lets use - // a pseudo terminal to instead of relying on the 'O' packets for stdio - // since 'O' packets can really slow down debugging if the inferior - // does a lot of output. - if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) && - pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0)) - { - FileSpec slave_name{pty.GetSlaveName(NULL, 0), false}; - - if (!stdin_file_spec) - stdin_file_spec = slave_name; - - if (!stdout_file_spec) - stdout_file_spec = slave_name; - - if (!stderr_file_spec) - stderr_file_spec = slave_name; - } - if (log) - log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); - } - - if (log) - log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); - - if (stdin_file_spec) - m_gdb_comm.SetSTDIN(stdin_file_spec); - if (stdout_file_spec) - m_gdb_comm.SetSTDOUT(stdout_file_spec); - if (stderr_file_spec) - m_gdb_comm.SetSTDERR(stderr_file_spec); - - m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR); - m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError); - - m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName()); - - const char * launch_event_data = launch_info.GetLaunchEventData(); - if (launch_event_data != NULL && *launch_event_data != '\0') - m_gdb_comm.SendLaunchEventDataPacket (launch_event_data); - - if (working_dir) - { - m_gdb_comm.SetWorkingDir (working_dir); - } - - // Send the environment and the program + arguments after we connect - const Args &environment = launch_info.GetEnvironmentEntries(); - if (environment.GetArgumentCount()) - { - size_t num_environment_entries = environment.GetArgumentCount(); - for (size_t i=0; i<num_environment_entries; ++i) - { - const char *env_entry = environment.GetArgumentAtIndex(i); - if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0) - break; - } - } - - { - // Scope for the scoped timeout object - GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10); - - int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info); - if (arg_packet_err == 0) - { - std::string error_str; - if (m_gdb_comm.GetLaunchSuccess (error_str)) - { - SetID (m_gdb_comm.GetCurrentProcessID ()); - } - else - { - error.SetErrorString (error_str.c_str()); - } - } - else - { - error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); - } - } - - if (GetID() == LLDB_INVALID_PROCESS_ID) - { - if (log) - log->Printf("failed to connect to debugserver: %s", error.AsCString()); - KillDebugserverProcess (); - return error; - } - - StringExtractorGDBRemote response; - if (m_gdb_comm.GetStopReply(response)) - { - SetLastStopPacket(response); - // '?' Packets must be handled differently in non-stop mode - if (GetTarget().GetNonStopModeEnabled()) - HandleStopReplySequence(); - - const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture(); - - if (process_arch.IsValid()) - { - GetTarget().MergeArchitecture(process_arch); - } - else - { - const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture(); - if (host_arch.IsValid()) - GetTarget().MergeArchitecture(host_arch); - } - - SetPrivateState (SetThreadStopInfo (response)); - - if (!disable_stdio) - { - if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) - SetSTDIOFileDescriptor (pty.ReleaseMasterFileDescriptor()); - } - } + log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info", + __FUNCTION__); + } + + const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; + if (stdin_file_spec || disable_stdio) { + // the inferior will be reading stdin from the specified file + // or stdio is completely disabled + m_stdin_forward = false; + } else { + m_stdin_forward = true; + } + + // ::LogSetBitMask (GDBR_LOG_DEFAULT); + // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | + // LLDB_LOG_OPTION_PREPEND_TIMESTAMP | + // LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); + // ::LogSetLogFile ("/dev/stdout"); + + ObjectFile *object_file = exe_module->GetObjectFile(); + if (object_file) { + error = EstablishConnectionIfNeeded(launch_info); + if (error.Success()) { + lldb_utility::PseudoTerminal pty; + const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; + + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (disable_stdio) { + // set to /dev/null unless redirected to a file above + if (!stdin_file_spec) + stdin_file_spec.SetFile(FileSystem::DEV_NULL, false); + if (!stdout_file_spec) + stdout_file_spec.SetFile(FileSystem::DEV_NULL, false); + if (!stderr_file_spec) + stderr_file_spec.SetFile(FileSystem::DEV_NULL, false); + } else if (platform_sp && platform_sp->IsHost()) { + // If the debugserver is local and we aren't disabling STDIO, lets use + // a pseudo terminal to instead of relying on the 'O' packets for stdio + // since 'O' packets can really slow down debugging if the inferior + // does a lot of output. + if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) && + pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) { + FileSpec slave_name{pty.GetSlaveName(NULL, 0), false}; + + if (!stdin_file_spec) + stdin_file_spec = slave_name; + + if (!stdout_file_spec) + stdout_file_spec = slave_name; + + if (!stderr_file_spec) + stderr_file_spec = slave_name; } - else - { - if (log) - log->Printf("failed to connect to debugserver: %s", error.AsCString()); + if (log) + log->Printf( + "ProcessGDBRemote::%s adjusted STDIO paths for local platform " + "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + } + + if (log) + log->Printf("ProcessGDBRemote::%s final STDIO paths after all " + "adjustments: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() + : "<null>"); + + if (stdin_file_spec) + m_gdb_comm.SetSTDIN(stdin_file_spec); + if (stdout_file_spec) + m_gdb_comm.SetSTDOUT(stdout_file_spec); + if (stderr_file_spec) + m_gdb_comm.SetSTDERR(stderr_file_spec); + + m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR); + m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError); + + m_gdb_comm.SendLaunchArchPacket( + GetTarget().GetArchitecture().GetArchitectureName()); + + const char *launch_event_data = launch_info.GetLaunchEventData(); + if (launch_event_data != NULL && *launch_event_data != '\0') + m_gdb_comm.SendLaunchEventDataPacket(launch_event_data); + + if (working_dir) { + m_gdb_comm.SetWorkingDir(working_dir); + } + + // Send the environment and the program + arguments after we connect + const Args &environment = launch_info.GetEnvironmentEntries(); + if (environment.GetArgumentCount()) { + size_t num_environment_entries = environment.GetArgumentCount(); + for (size_t i = 0; i < num_environment_entries; ++i) { + const char *env_entry = environment.GetArgumentAtIndex(i); + if (env_entry == NULL || + m_gdb_comm.SendEnvironmentPacket(env_entry) != 0) + break; } - } - else - { - // Set our user ID to an invalid process ID. - SetID(LLDB_INVALID_PROCESS_ID); - error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s", - exe_module->GetFileSpec().GetFilename().AsCString(), - exe_module->GetArchitecture().GetArchitectureName()); - } - return error; - -} + } + { + // Scope for the scoped timeout object + GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10); + + int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info); + if (arg_packet_err == 0) { + std::string error_str; + if (m_gdb_comm.GetLaunchSuccess(error_str)) { + SetID(m_gdb_comm.GetCurrentProcessID()); + } else { + error.SetErrorString(error_str.c_str()); + } + } else { + error.SetErrorStringWithFormat("'A' packet returned an error: %i", + arg_packet_err); + } + } -Error -ProcessGDBRemote::ConnectToDebugserver (const char *connect_url) -{ - Error error; - // Only connect if we have a valid connect URL - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - - if (connect_url && connect_url[0]) - { + if (GetID() == LLDB_INVALID_PROCESS_ID) { if (log) - log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url); - std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); - if (conn_ap.get()) - { - const uint32_t max_retry_count = 50; - uint32_t retry_count = 0; - while (!m_gdb_comm.IsConnected()) - { - if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) - { - m_gdb_comm.SetConnection (conn_ap.release()); - break; - } - else if (error.WasInterrupted()) - { - // If we were interrupted, don't keep retrying. - break; - } + log->Printf("failed to connect to debugserver: %s", + error.AsCString()); + KillDebugserverProcess(); + return error; + } - retry_count++; + StringExtractorGDBRemote response; + if (m_gdb_comm.GetStopReply(response)) { + SetLastStopPacket(response); + // '?' Packets must be handled differently in non-stop mode + if (GetTarget().GetNonStopModeEnabled()) + HandleStopReplySequence(); + + const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture(); + + if (process_arch.IsValid()) { + GetTarget().MergeArchitecture(process_arch); + } else { + const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture(); + if (host_arch.IsValid()) + GetTarget().MergeArchitecture(host_arch); + } - if (retry_count >= max_retry_count) - break; + SetPrivateState(SetThreadStopInfo(response)); - usleep (100000); - } + if (!disable_stdio) { + if (pty.GetMasterFileDescriptor() != + lldb_utility::PseudoTerminal::invalid_fd) + SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor()); } - } + } + } else { + if (log) + log->Printf("failed to connect to debugserver: %s", error.AsCString()); + } + } else { + // Set our user ID to an invalid process ID. + SetID(LLDB_INVALID_PROCESS_ID); + error.SetErrorStringWithFormat( + "failed to get object file from '%s' for arch %s", + exe_module->GetFileSpec().GetFilename().AsCString(), + exe_module->GetArchitecture().GetArchitectureName()); + } + return error; +} - if (!m_gdb_comm.IsConnected()) - { - if (error.Success()) - error.SetErrorString("not connected to remote gdb server"); - return error; - } +Error ProcessGDBRemote::ConnectToDebugserver(const char *connect_url) { + Error error; + // Only connect if we have a valid connect URL + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (connect_url && connect_url[0]) { + if (log) + log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, + connect_url); + std::unique_ptr<ConnectionFileDescriptor> conn_ap( + new ConnectionFileDescriptor()); + if (conn_ap.get()) { + const uint32_t max_retry_count = 50; + uint32_t retry_count = 0; + while (!m_gdb_comm.IsConnected()) { + if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) { + m_gdb_comm.SetConnection(conn_ap.release()); + break; + } else if (error.WasInterrupted()) { + // If we were interrupted, don't keep retrying. + break; + } - // Start the communications read thread so all incoming data can be - // parsed into packets and queued as they arrive. - if (GetTarget().GetNonStopModeEnabled()) - m_gdb_comm.StartReadThread(); + retry_count++; - // We always seem to be able to open a connection to a local port - // so we need to make sure we can then send data to it. If we can't - // then we aren't actually connected to anything, so try and do the - // handshake with the remote GDB server and make sure that goes - // alright. - if (!m_gdb_comm.HandshakeWithServer (&error)) - { - m_gdb_comm.Disconnect(); - if (error.Success()) - error.SetErrorString("not connected to remote gdb server"); - return error; + if (retry_count >= max_retry_count) + break; + + usleep(100000); + } } + } - // Send $QNonStop:1 packet on startup if required - if (GetTarget().GetNonStopModeEnabled()) - GetTarget().SetNonStopModeEnabled (m_gdb_comm.SetNonStopMode(true)); + if (!m_gdb_comm.IsConnected()) { + if (error.Success()) + error.SetErrorString("not connected to remote gdb server"); + return error; + } + + // Start the communications read thread so all incoming data can be + // parsed into packets and queued as they arrive. + if (GetTarget().GetNonStopModeEnabled()) + m_gdb_comm.StartReadThread(); + + // We always seem to be able to open a connection to a local port + // so we need to make sure we can then send data to it. If we can't + // then we aren't actually connected to anything, so try and do the + // handshake with the remote GDB server and make sure that goes + // alright. + if (!m_gdb_comm.HandshakeWithServer(&error)) { + m_gdb_comm.Disconnect(); + if (error.Success()) + error.SetErrorString("not connected to remote gdb server"); + return error; + } - m_gdb_comm.GetEchoSupported (); - m_gdb_comm.GetThreadSuffixSupported (); - m_gdb_comm.GetListThreadsInStopReplySupported (); - m_gdb_comm.GetHostInfo (); - m_gdb_comm.GetVContSupported ('c'); - m_gdb_comm.GetVAttachOrWaitSupported(); + // Send $QNonStop:1 packet on startup if required + if (GetTarget().GetNonStopModeEnabled()) + GetTarget().SetNonStopModeEnabled(m_gdb_comm.SetNonStopMode(true)); - // Ask the remote server for the default thread id - if (GetTarget().GetNonStopModeEnabled()) - m_gdb_comm.GetDefaultThreadId(m_initial_tid); + m_gdb_comm.GetEchoSupported(); + m_gdb_comm.GetThreadSuffixSupported(); + m_gdb_comm.GetListThreadsInStopReplySupported(); + m_gdb_comm.GetHostInfo(); + m_gdb_comm.GetVContSupported('c'); + m_gdb_comm.GetVAttachOrWaitSupported(); + // Ask the remote server for the default thread id + if (GetTarget().GetNonStopModeEnabled()) + m_gdb_comm.GetDefaultThreadId(m_initial_tid); - size_t num_cmds = GetExtraStartupCommands().GetArgumentCount(); - for (size_t idx = 0; idx < num_cmds; idx++) - { - StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse (GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false); - } - return error; + size_t num_cmds = GetExtraStartupCommands().GetArgumentCount(); + for (size_t idx = 0; idx < num_cmds; idx++) { + StringExtractorGDBRemote response; + m_gdb_comm.SendPacketAndWaitForResponse( + GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false); + } + return error; } -void -ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__); - if (GetID() != LLDB_INVALID_PROCESS_ID) - { - BuildDynamicRegisterInfo (false); - - // See if the GDB server supports the qHostInfo information +void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + if (GetID() != LLDB_INVALID_PROCESS_ID) { + BuildDynamicRegisterInfo(false); + // See if the GDB server supports the qHostInfo information - // See if the GDB server supports the qProcessInfo packet, if so - // prefer that over the Host information as it will be more specific - // to our process. + // See if the GDB server supports the qProcessInfo packet, if so + // prefer that over the Host information as it will be more specific + // to our process. - const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); - if (remote_process_arch.IsValid()) - { - process_arch = remote_process_arch; - if (log) - log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s", - __FUNCTION__, - process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", - process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); - } - else - { - process_arch = m_gdb_comm.GetHostArchitecture(); - if (log) - log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s", - __FUNCTION__, - process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", - process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); - } - - if (process_arch.IsValid()) - { - const ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid()) - { - if (log) - log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s", - __FUNCTION__, - target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>", - target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>"); - - // If the remote host is ARM and we have apple as the vendor, then - // ARM executables and shared libraries can have mixed ARM architectures. - // You can have an armv6 executable, and if the host is armv7, then the - // system will load the best possible architecture for all shared libraries - // it has, so we really need to take the remote host architecture as our - // defacto architecture in this case. - - if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb) - && process_arch.GetTriple().getVendor() == llvm::Triple::Apple) - { - GetTarget().SetArchitecture (process_arch); - if (log) - log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s", - __FUNCTION__, - process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", - process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); - } - else - { - // Fill in what is missing in the triple - const llvm::Triple &remote_triple = process_arch.GetTriple(); - llvm::Triple new_target_triple = target_arch.GetTriple(); - if (new_target_triple.getVendorName().size() == 0) - { - new_target_triple.setVendor (remote_triple.getVendor()); - - if (new_target_triple.getOSName().size() == 0) - { - new_target_triple.setOS (remote_triple.getOS()); - - if (new_target_triple.getEnvironmentName().size() == 0) - new_target_triple.setEnvironment (remote_triple.getEnvironment()); - } - - ArchSpec new_target_arch = target_arch; - new_target_arch.SetTriple(new_target_triple); - GetTarget().SetArchitecture(new_target_arch); - } - } - - if (log) - log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s", - __FUNCTION__, - target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>", - target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>"); - } - else - { - // The target doesn't have a valid architecture yet, set it from - // the architecture we got from the remote GDB server - GetTarget().SetArchitecture (process_arch); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + if (remote_process_arch.IsValid()) { + process_arch = remote_process_arch; + if (log) + log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, " + "using %s %s", + __FUNCTION__, process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); + } else { + process_arch = m_gdb_comm.GetHostArchitecture(); + if (log) + log->Printf("ProcessGDBRemote::%s gdb-remote did not have process " + "architecture, using gdb-remote host architecture %s %s", + __FUNCTION__, process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); + } + + if (process_arch.IsValid()) { + const ArchSpec &target_arch = GetTarget().GetArchitecture(); + if (target_arch.IsValid()) { + if (log) + log->Printf( + "ProcessGDBRemote::%s analyzing target arch, currently %s %s", + __FUNCTION__, target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); + + // If the remote host is ARM and we have apple as the vendor, then + // ARM executables and shared libraries can have mixed ARM + // architectures. + // You can have an armv6 executable, and if the host is armv7, then the + // system will load the best possible architecture for all shared + // libraries + // it has, so we really need to take the remote host architecture as our + // defacto architecture in this case. + + if ((process_arch.GetMachine() == llvm::Triple::arm || + process_arch.GetMachine() == llvm::Triple::thumb) && + process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { + GetTarget().SetArchitecture(process_arch); + if (log) + log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, " + "setting target arch to %s %s", + __FUNCTION__, process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); + } else { + // Fill in what is missing in the triple + const llvm::Triple &remote_triple = process_arch.GetTriple(); + llvm::Triple new_target_triple = target_arch.GetTriple(); + if (new_target_triple.getVendorName().size() == 0) { + new_target_triple.setVendor(remote_triple.getVendor()); + + if (new_target_triple.getOSName().size() == 0) { + new_target_triple.setOS(remote_triple.getOS()); + + if (new_target_triple.getEnvironmentName().size() == 0) + new_target_triple.setEnvironment( + remote_triple.getEnvironment()); } + + ArchSpec new_target_arch = target_arch; + new_target_arch.SetTriple(new_target_triple); + GetTarget().SetArchitecture(new_target_arch); + } } - // Find out which StructuredDataPlugins are supported by the - // debug monitor. These plugins transmit data over async $J packets. - auto supported_packets_array = - m_gdb_comm.GetSupportedStructuredDataPlugins(); - if (supported_packets_array) - MapSupportedStructuredDataPlugins(*supported_packets_array); - } + if (log) + log->Printf("ProcessGDBRemote::%s final target arch after " + "adjustments for remote architecture: %s %s", + __FUNCTION__, target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); + } else { + // The target doesn't have a valid architecture yet, set it from + // the architecture we got from the remote GDB server + GetTarget().SetArchitecture(process_arch); + } + } + + // Find out which StructuredDataPlugins are supported by the + // debug monitor. These plugins transmit data over async $J packets. + auto supported_packets_array = + m_gdb_comm.GetSupportedStructuredDataPlugins(); + if (supported_packets_array) + MapSupportedStructuredDataPlugins(*supported_packets_array); + } } -void -ProcessGDBRemote::DidLaunch () -{ - ArchSpec process_arch; - DidLaunchOrAttach (process_arch); +void ProcessGDBRemote::DidLaunch() { + ArchSpec process_arch; + DidLaunchOrAttach(process_arch); } -Error -ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - Error error; - - if (log) - log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__); - - // Clear out and clean up from any current state - Clear(); - if (attach_pid != LLDB_INVALID_PROCESS_ID) - { - error = EstablishConnectionIfNeeded (attach_info); - if (error.Success()) - { - m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); - - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); - SetID (attach_pid); - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len)); - } - else - SetExitStatus (-1, error.AsCString()); - } - - return error; +Error ProcessGDBRemote::DoAttachToProcessWithID( + lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Error error; + + if (log) + log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + + // Clear out and clean up from any current state + Clear(); + if (attach_pid != LLDB_INVALID_PROCESS_ID) { + error = EstablishConnectionIfNeeded(attach_info); + if (error.Success()) { + m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); + + char packet[64]; + const int packet_len = + ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); + SetID(attach_pid); + m_async_broadcaster.BroadcastEvent( + eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len)); + } else + SetExitStatus(-1, error.AsCString()); + } + + return error; } -Error -ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info) -{ - Error error; - // Clear out and clean up from any current state - Clear(); - - if (process_name && process_name[0]) - { - error = EstablishConnectionIfNeeded (attach_info); - if (error.Success()) - { - StreamString packet; - - m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); - - if (attach_info.GetWaitForLaunch()) - { - if (!m_gdb_comm.GetVAttachOrWaitSupported()) - { - packet.PutCString ("vAttachWait"); - } - else - { - if (attach_info.GetIgnoreExisting()) - packet.PutCString("vAttachWait"); - else - packet.PutCString ("vAttachOrWait"); - } - } - else - packet.PutCString("vAttachName"); - packet.PutChar(';'); - packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder()); - - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize())); - +Error ProcessGDBRemote::DoAttachToProcessWithName( + const char *process_name, const ProcessAttachInfo &attach_info) { + Error error; + // Clear out and clean up from any current state + Clear(); + + if (process_name && process_name[0]) { + error = EstablishConnectionIfNeeded(attach_info); + if (error.Success()) { + StreamString packet; + + m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); + + if (attach_info.GetWaitForLaunch()) { + if (!m_gdb_comm.GetVAttachOrWaitSupported()) { + packet.PutCString("vAttachWait"); + } else { + if (attach_info.GetIgnoreExisting()) + packet.PutCString("vAttachWait"); + else + packet.PutCString("vAttachOrWait"); } - else - SetExitStatus (-1, error.AsCString()); - } - return error; + } else + packet.PutCString("vAttachName"); + packet.PutChar(';'); + packet.PutBytesAsRawHex8(process_name, strlen(process_name), + endian::InlHostByteOrder(), + endian::InlHostByteOrder()); + + m_async_broadcaster.BroadcastEvent( + eBroadcastBitAsyncContinue, + new EventDataBytes(packet.GetData(), packet.GetSize())); + + } else + SetExitStatus(-1, error.AsCString()); + } + return error; } -void -ProcessGDBRemote::DidExit () -{ - // When we exit, disconnect from the GDB server communications - m_gdb_comm.Disconnect(); +void ProcessGDBRemote::DidExit() { + // When we exit, disconnect from the GDB server communications + m_gdb_comm.Disconnect(); } -void -ProcessGDBRemote::DidAttach (ArchSpec &process_arch) -{ - // If you can figure out what the architecture is, fill it in here. - process_arch.Clear(); - DidLaunchOrAttach (process_arch); +void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) { + // If you can figure out what the architecture is, fill it in here. + process_arch.Clear(); + DidLaunchOrAttach(process_arch); } - -Error -ProcessGDBRemote::WillResume () -{ - m_continue_c_tids.clear(); - m_continue_C_tids.clear(); - m_continue_s_tids.clear(); - m_continue_S_tids.clear(); - m_jstopinfo_sp.reset(); - m_jthreadsinfo_sp.reset(); - return Error(); +Error ProcessGDBRemote::WillResume() { + m_continue_c_tids.clear(); + m_continue_C_tids.clear(); + m_continue_s_tids.clear(); + m_continue_S_tids.clear(); + m_jstopinfo_sp.reset(); + m_jthreadsinfo_sp.reset(); + return Error(); } -Error -ProcessGDBRemote::DoResume () -{ - Error error; - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::Resume()"); - - ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent")); - if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) - { - listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); - - const size_t num_threads = GetThreadList().GetSize(); - - StreamString continue_packet; - bool continue_packet_error = false; - if (m_gdb_comm.HasAnyVContSupport ()) - { - if (!GetTarget().GetNonStopModeEnabled() && - (m_continue_c_tids.size() == num_threads || - (m_continue_c_tids.empty() && - m_continue_C_tids.empty() && - m_continue_s_tids.empty() && - m_continue_S_tids.empty()))) - { - // All threads are continuing, just send a "c" packet - continue_packet.PutCString ("c"); - } - else - { - continue_packet.PutCString ("vCont"); - - if (!m_continue_c_tids.empty()) - { - if (m_gdb_comm.GetVContSupported ('c')) - { - for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos) - continue_packet.Printf(";c:%4.4" PRIx64, *t_pos); - } - else - continue_packet_error = true; - } - - if (!continue_packet_error && !m_continue_C_tids.empty()) - { - if (m_gdb_comm.GetVContSupported ('C')) - { - for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos) - continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first); - } - else - continue_packet_error = true; - } - - if (!continue_packet_error && !m_continue_s_tids.empty()) - { - if (m_gdb_comm.GetVContSupported ('s')) - { - for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos) - continue_packet.Printf(";s:%4.4" PRIx64, *t_pos); - } - else - continue_packet_error = true; - } +Error ProcessGDBRemote::DoResume() { + Error error; + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::Resume()"); + + ListenerSP listener_sp( + Listener::MakeListener("gdb-remote.resume-packet-sent")); + if (listener_sp->StartListeningForEvents( + &m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) { + listener_sp->StartListeningForEvents( + &m_async_broadcaster, + ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); + + const size_t num_threads = GetThreadList().GetSize(); + + StreamString continue_packet; + bool continue_packet_error = false; + if (m_gdb_comm.HasAnyVContSupport()) { + if (!GetTarget().GetNonStopModeEnabled() && + (m_continue_c_tids.size() == num_threads || + (m_continue_c_tids.empty() && m_continue_C_tids.empty() && + m_continue_s_tids.empty() && m_continue_S_tids.empty()))) { + // All threads are continuing, just send a "c" packet + continue_packet.PutCString("c"); + } else { + continue_packet.PutCString("vCont"); + + if (!m_continue_c_tids.empty()) { + if (m_gdb_comm.GetVContSupported('c')) { + for (tid_collection::const_iterator + t_pos = m_continue_c_tids.begin(), + t_end = m_continue_c_tids.end(); + t_pos != t_end; ++t_pos) + continue_packet.Printf(";c:%4.4" PRIx64, *t_pos); + } else + continue_packet_error = true; + } - if (!continue_packet_error && !m_continue_S_tids.empty()) - { - if (m_gdb_comm.GetVContSupported ('S')) - { - for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos) - continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first); - } - else - continue_packet_error = true; - } + if (!continue_packet_error && !m_continue_C_tids.empty()) { + if (m_gdb_comm.GetVContSupported('C')) { + for (tid_sig_collection::const_iterator + s_pos = m_continue_C_tids.begin(), + s_end = m_continue_C_tids.end(); + s_pos != s_end; ++s_pos) + continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, + s_pos->first); + } else + continue_packet_error = true; + } - if (continue_packet_error) - continue_packet.GetString().clear(); - } + if (!continue_packet_error && !m_continue_s_tids.empty()) { + if (m_gdb_comm.GetVContSupported('s')) { + for (tid_collection::const_iterator + t_pos = m_continue_s_tids.begin(), + t_end = m_continue_s_tids.end(); + t_pos != t_end; ++t_pos) + continue_packet.Printf(";s:%4.4" PRIx64, *t_pos); + } else + continue_packet_error = true; } - else + + if (!continue_packet_error && !m_continue_S_tids.empty()) { + if (m_gdb_comm.GetVContSupported('S')) { + for (tid_sig_collection::const_iterator + s_pos = m_continue_S_tids.begin(), + s_end = m_continue_S_tids.end(); + s_pos != s_end; ++s_pos) + continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, + s_pos->first); + } else continue_packet_error = true; + } if (continue_packet_error) - { - // Either no vCont support, or we tried to use part of the vCont - // packet that wasn't supported by the remote GDB server. - // We need to try and make a simple packet that can do our continue - const size_t num_continue_c_tids = m_continue_c_tids.size(); - const size_t num_continue_C_tids = m_continue_C_tids.size(); - const size_t num_continue_s_tids = m_continue_s_tids.size(); - const size_t num_continue_S_tids = m_continue_S_tids.size(); - if (num_continue_c_tids > 0) - { - if (num_continue_c_tids == num_threads) - { - // All threads are resuming... - m_gdb_comm.SetCurrentThreadForRun (-1); - continue_packet.PutChar ('c'); - continue_packet_error = false; - } - else if (num_continue_c_tids == 1 && - num_continue_C_tids == 0 && - num_continue_s_tids == 0 && - num_continue_S_tids == 0 ) - { - // Only one thread is continuing - m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front()); - continue_packet.PutChar ('c'); - continue_packet_error = false; - } - } - - if (continue_packet_error && num_continue_C_tids > 0) - { - if ((num_continue_C_tids + num_continue_c_tids) == num_threads && - num_continue_C_tids > 0 && - num_continue_s_tids == 0 && - num_continue_S_tids == 0 ) - { - const int continue_signo = m_continue_C_tids.front().second; - // Only one thread is continuing - if (num_continue_C_tids > 1) - { - // More that one thread with a signal, yet we don't have - // vCont support and we are being asked to resume each - // thread with a signal, we need to make sure they are - // all the same signal, or we can't issue the continue - // accurately with the current support... - if (num_continue_C_tids > 1) - { - continue_packet_error = false; - for (size_t i=1; i<m_continue_C_tids.size(); ++i) - { - if (m_continue_C_tids[i].second != continue_signo) - continue_packet_error = true; - } - } - if (!continue_packet_error) - m_gdb_comm.SetCurrentThreadForRun (-1); - } - else - { - // Set the continue thread ID - continue_packet_error = false; - m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first); - } - if (!continue_packet_error) - { - // Add threads continuing with the same signo... - continue_packet.Printf("C%2.2x", continue_signo); - } - } + continue_packet.GetString().clear(); + } + } else + continue_packet_error = true; + + if (continue_packet_error) { + // Either no vCont support, or we tried to use part of the vCont + // packet that wasn't supported by the remote GDB server. + // We need to try and make a simple packet that can do our continue + const size_t num_continue_c_tids = m_continue_c_tids.size(); + const size_t num_continue_C_tids = m_continue_C_tids.size(); + const size_t num_continue_s_tids = m_continue_s_tids.size(); + const size_t num_continue_S_tids = m_continue_S_tids.size(); + if (num_continue_c_tids > 0) { + if (num_continue_c_tids == num_threads) { + // All threads are resuming... + m_gdb_comm.SetCurrentThreadForRun(-1); + continue_packet.PutChar('c'); + continue_packet_error = false; + } else if (num_continue_c_tids == 1 && num_continue_C_tids == 0 && + num_continue_s_tids == 0 && num_continue_S_tids == 0) { + // Only one thread is continuing + m_gdb_comm.SetCurrentThreadForRun(m_continue_c_tids.front()); + continue_packet.PutChar('c'); + continue_packet_error = false; + } + } + + if (continue_packet_error && num_continue_C_tids > 0) { + if ((num_continue_C_tids + num_continue_c_tids) == num_threads && + num_continue_C_tids > 0 && num_continue_s_tids == 0 && + num_continue_S_tids == 0) { + const int continue_signo = m_continue_C_tids.front().second; + // Only one thread is continuing + if (num_continue_C_tids > 1) { + // More that one thread with a signal, yet we don't have + // vCont support and we are being asked to resume each + // thread with a signal, we need to make sure they are + // all the same signal, or we can't issue the continue + // accurately with the current support... + if (num_continue_C_tids > 1) { + continue_packet_error = false; + for (size_t i = 1; i < m_continue_C_tids.size(); ++i) { + if (m_continue_C_tids[i].second != continue_signo) + continue_packet_error = true; + } } + if (!continue_packet_error) + m_gdb_comm.SetCurrentThreadForRun(-1); + } else { + // Set the continue thread ID + continue_packet_error = false; + m_gdb_comm.SetCurrentThreadForRun(m_continue_C_tids.front().first); + } + if (!continue_packet_error) { + // Add threads continuing with the same signo... + continue_packet.Printf("C%2.2x", continue_signo); + } + } + } - if (continue_packet_error && num_continue_s_tids > 0) - { - if (num_continue_s_tids == num_threads) - { - // All threads are resuming... - m_gdb_comm.SetCurrentThreadForRun (-1); - - // If in Non-Stop-Mode use vCont when stepping - if (GetTarget().GetNonStopModeEnabled()) - { - if (m_gdb_comm.GetVContSupported('s')) - continue_packet.PutCString("vCont;s"); - else - continue_packet.PutChar('s'); - } - else - continue_packet.PutChar('s'); - - continue_packet_error = false; - } - else if (num_continue_c_tids == 0 && - num_continue_C_tids == 0 && - num_continue_s_tids == 1 && - num_continue_S_tids == 0 ) - { - // Only one thread is stepping - m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front()); - continue_packet.PutChar ('s'); - continue_packet_error = false; - } - } + if (continue_packet_error && num_continue_s_tids > 0) { + if (num_continue_s_tids == num_threads) { + // All threads are resuming... + m_gdb_comm.SetCurrentThreadForRun(-1); - if (!continue_packet_error && num_continue_S_tids > 0) - { - if (num_continue_S_tids == num_threads) - { - const int step_signo = m_continue_S_tids.front().second; - // Are all threads trying to step with the same signal? - continue_packet_error = false; - if (num_continue_S_tids > 1) - { - for (size_t i=1; i<num_threads; ++i) - { - if (m_continue_S_tids[i].second != step_signo) - continue_packet_error = true; - } - } - if (!continue_packet_error) - { - // Add threads stepping with the same signo... - m_gdb_comm.SetCurrentThreadForRun (-1); - continue_packet.Printf("S%2.2x", step_signo); - } - } - else if (num_continue_c_tids == 0 && - num_continue_C_tids == 0 && - num_continue_s_tids == 0 && - num_continue_S_tids == 1 ) - { - // Only one thread is stepping with signal - m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first); - continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second); - continue_packet_error = false; - } + // If in Non-Stop-Mode use vCont when stepping + if (GetTarget().GetNonStopModeEnabled()) { + if (m_gdb_comm.GetVContSupported('s')) + continue_packet.PutCString("vCont;s"); + else + continue_packet.PutChar('s'); + } else + continue_packet.PutChar('s'); + + continue_packet_error = false; + } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && + num_continue_s_tids == 1 && num_continue_S_tids == 0) { + // Only one thread is stepping + m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front()); + continue_packet.PutChar('s'); + continue_packet_error = false; + } + } + + if (!continue_packet_error && num_continue_S_tids > 0) { + if (num_continue_S_tids == num_threads) { + const int step_signo = m_continue_S_tids.front().second; + // Are all threads trying to step with the same signal? + continue_packet_error = false; + if (num_continue_S_tids > 1) { + for (size_t i = 1; i < num_threads; ++i) { + if (m_continue_S_tids[i].second != step_signo) + continue_packet_error = true; } + } + if (!continue_packet_error) { + // Add threads stepping with the same signo... + m_gdb_comm.SetCurrentThreadForRun(-1); + continue_packet.Printf("S%2.2x", step_signo); + } + } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && + num_continue_s_tids == 0 && num_continue_S_tids == 1) { + // Only one thread is stepping with signal + m_gdb_comm.SetCurrentThreadForRun(m_continue_S_tids.front().first); + continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second); + continue_packet_error = false; } + } + } - if (continue_packet_error) - { - error.SetErrorString ("can't make continue packet for this resume"); - } - else - { - EventSP event_sp; - if (!m_async_thread.IsJoinable()) - { - error.SetErrorString ("Trying to resume but the async thread is dead."); - if (log) - log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead."); - return error; - } + if (continue_packet_error) { + error.SetErrorString("can't make continue packet for this resume"); + } else { + EventSP event_sp; + if (!m_async_thread.IsJoinable()) { + error.SetErrorString("Trying to resume but the async thread is dead."); + if (log) + log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the " + "async thread is dead."); + return error; + } - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize())); + m_async_broadcaster.BroadcastEvent( + eBroadcastBitAsyncContinue, + new EventDataBytes(continue_packet.GetData(), + continue_packet.GetSize())); - if (listener_sp->WaitForEvent(std::chrono::seconds(5), event_sp) == false) - { - error.SetErrorString("Resume timed out."); - if (log) - log->Printf ("ProcessGDBRemote::DoResume: Resume timed out."); - } - else if (event_sp->BroadcasterIs (&m_async_broadcaster)) - { - error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back."); - if (log) - log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back."); - return error; - } - } + if (listener_sp->WaitForEvent(std::chrono::seconds(5), event_sp) == + false) { + error.SetErrorString("Resume timed out."); + if (log) + log->Printf("ProcessGDBRemote::DoResume: Resume timed out."); + } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { + error.SetErrorString("Broadcast continue, but the async thread was " + "killed before we got an ack back."); + if (log) + log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the " + "async thread was killed before we got an ack back."); + return error; + } } + } - return error; + return error; } -void -ProcessGDBRemote::HandleStopReplySequence () -{ - while(true) - { - // Send vStopped - StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); +void ProcessGDBRemote::HandleStopReplySequence() { + while (true) { + // Send vStopped + StringExtractorGDBRemote response; + m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); - // OK represents end of signal list - if (response.IsOKResponse()) - break; + // OK represents end of signal list + if (response.IsOKResponse()) + break; - // If not OK or a normal packet we have a problem - if (!response.IsNormalResponse()) - break; + // If not OK or a normal packet we have a problem + if (!response.IsNormalResponse()) + break; - SetLastStopPacket(response); - } + SetLastStopPacket(response); + } } -void -ProcessGDBRemote::ClearThreadIDList () -{ - std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); - m_thread_ids.clear(); - m_thread_pcs.clear(); +void ProcessGDBRemote::ClearThreadIDList() { + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + m_thread_ids.clear(); + m_thread_pcs.clear(); } size_t -ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value) -{ - m_thread_ids.clear(); - m_thread_pcs.clear(); - size_t comma_pos; - lldb::tid_t tid; - while ((comma_pos = value.find(',')) != std::string::npos) - { - value[comma_pos] = '\0'; - // thread in big endian hex - tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); - if (tid != LLDB_INVALID_THREAD_ID) - m_thread_ids.push_back (tid); - value.erase(0, comma_pos + 1); - } - tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); +ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) { + m_thread_ids.clear(); + m_thread_pcs.clear(); + size_t comma_pos; + lldb::tid_t tid; + while ((comma_pos = value.find(',')) != std::string::npos) { + value[comma_pos] = '\0'; + // thread in big endian hex + tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) - m_thread_ids.push_back (tid); - return m_thread_ids.size(); + m_thread_ids.push_back(tid); + value.erase(0, comma_pos + 1); + } + tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); + if (tid != LLDB_INVALID_THREAD_ID) + m_thread_ids.push_back(tid); + return m_thread_ids.size(); } size_t -ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value) -{ - m_thread_pcs.clear(); - size_t comma_pos; - lldb::addr_t pc; - while ((comma_pos = value.find(',')) != std::string::npos) - { - value[comma_pos] = '\0'; - pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); - if (pc != LLDB_INVALID_ADDRESS) - m_thread_pcs.push_back (pc); - value.erase(0, comma_pos + 1); - } - pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); - if (pc != LLDB_INVALID_THREAD_ID) - m_thread_pcs.push_back (pc); - return m_thread_pcs.size(); +ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) { + m_thread_pcs.clear(); + size_t comma_pos; + lldb::addr_t pc; + while ((comma_pos = value.find(',')) != std::string::npos) { + value[comma_pos] = '\0'; + pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16); + if (pc != LLDB_INVALID_ADDRESS) + m_thread_pcs.push_back(pc); + value.erase(0, comma_pos + 1); + } + pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16); + if (pc != LLDB_INVALID_THREAD_ID) + m_thread_pcs.push_back(pc); + return m_thread_pcs.size(); } -bool -ProcessGDBRemote::UpdateThreadIDList () -{ - std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); - - if (m_jthreadsinfo_sp) - { - // If we have the JSON threads info, we can get the thread list from that - StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); - if (thread_infos && thread_infos->GetSize() > 0) - { - m_thread_ids.clear(); - m_thread_pcs.clear(); - thread_infos->ForEach([this](StructuredData::Object* object) -> bool { - StructuredData::Dictionary *thread_dict = object->GetAsDictionary(); - if (thread_dict) - { - // Set the thread stop info from the JSON dictionary - SetThreadStopInfo (thread_dict); - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid)) - m_thread_ids.push_back(tid); - } - return true; // Keep iterating through all thread_info objects - }); +bool ProcessGDBRemote::UpdateThreadIDList() { + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + + if (m_jthreadsinfo_sp) { + // If we have the JSON threads info, we can get the thread list from that + StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); + if (thread_infos && thread_infos->GetSize() > 0) { + m_thread_ids.clear(); + m_thread_pcs.clear(); + thread_infos->ForEach([this](StructuredData::Object *object) -> bool { + StructuredData::Dictionary *thread_dict = object->GetAsDictionary(); + if (thread_dict) { + // Set the thread stop info from the JSON dictionary + SetThreadStopInfo(thread_dict); + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid)) + m_thread_ids.push_back(tid); + } + return true; // Keep iterating through all thread_info objects + }); + } + if (!m_thread_ids.empty()) + return true; + } else { + // See if we can get the thread IDs from the current stop reply packets + // that might contain a "threads" key/value pair + + // Lock the thread stack while we access it + // Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + std::unique_lock<std::recursive_mutex> stop_stack_lock( + m_last_stop_packet_mutex, std::defer_lock); + if (stop_stack_lock.try_lock()) { + // Get the number of stop packets on the stack + int nItems = m_stop_packet_stack.size(); + // Iterate over them + for (int i = 0; i < nItems; i++) { + // Get the thread stop info + StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; + const std::string &stop_info_str = stop_info.GetStringRef(); + + m_thread_pcs.clear(); + const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); + if (thread_pcs_pos != std::string::npos) { + const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); + const size_t end = stop_info_str.find(';', start); + if (end != std::string::npos) { + std::string value = stop_info_str.substr(start, end - start); + UpdateThreadPCsFromStopReplyThreadsValue(value); + } } - if (!m_thread_ids.empty()) - return true; - } - else - { - // See if we can get the thread IDs from the current stop reply packets - // that might contain a "threads" key/value pair - - // Lock the thread stack while we access it - //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); - std::unique_lock<std::recursive_mutex> stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock); - if (stop_stack_lock.try_lock()) - { - // Get the number of stop packets on the stack - int nItems = m_stop_packet_stack.size(); - // Iterate over them - for (int i = 0; i < nItems; i++) - { - // Get the thread stop info - StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; - const std::string &stop_info_str = stop_info.GetStringRef(); - - m_thread_pcs.clear(); - const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); - if (thread_pcs_pos != std::string::npos) - { - const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); - const size_t end = stop_info_str.find(';', start); - if (end != std::string::npos) - { - std::string value = stop_info_str.substr(start, end - start); - UpdateThreadPCsFromStopReplyThreadsValue(value); - } - } - const size_t threads_pos = stop_info_str.find(";threads:"); - if (threads_pos != std::string::npos) - { - const size_t start = threads_pos + strlen(";threads:"); - const size_t end = stop_info_str.find(';', start); - if (end != std::string::npos) - { - std::string value = stop_info_str.substr(start, end - start); - if (UpdateThreadIDsFromStopReplyThreadsValue(value)) - return true; - } - } - } + const size_t threads_pos = stop_info_str.find(";threads:"); + if (threads_pos != std::string::npos) { + const size_t start = threads_pos + strlen(";threads:"); + const size_t end = stop_info_str.find(';', start); + if (end != std::string::npos) { + std::string value = stop_info_str.substr(start, end - start); + if (UpdateThreadIDsFromStopReplyThreadsValue(value)) + return true; + } } + } } + } - bool sequence_mutex_unavailable = false; - m_gdb_comm.GetCurrentThreadIDs (m_thread_ids, sequence_mutex_unavailable); - if (sequence_mutex_unavailable) - { - return false; // We just didn't get the list - } - return true; + bool sequence_mutex_unavailable = false; + m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable); + if (sequence_mutex_unavailable) { + return false; // We just didn't get the list + } + return true; } -bool -ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - // locker will keep a mutex locked until it goes out of scope - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD)); - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); - - size_t num_thread_ids = m_thread_ids.size(); - // The "m_thread_ids" thread ID list should always be updated after each stop - // reply packet, but in case it isn't, update it here. - if (num_thread_ids == 0) - { - if (!UpdateThreadIDList ()) - return false; - num_thread_ids = m_thread_ids.size(); - } - - ThreadList old_thread_list_copy(old_thread_list); - if (num_thread_ids > 0) - { - for (size_t i=0; i<num_thread_ids; ++i) - { - tid_t tid = m_thread_ids[i]; - ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); - if (!thread_sp) - { - thread_sp.reset (new ThreadGDBRemote (*this, tid)); - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf( - "ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n", - __FUNCTION__, static_cast<void*>(thread_sp.get()), - thread_sp->GetID()); - } - else - { - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf( - "ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n", - __FUNCTION__, static_cast<void*>(thread_sp.get()), - thread_sp->GetID()); - } - // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most - // of the register read/write packets in gdb-remote protocol. - // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these; - // they are a performance improvement over fetching thread register values individually, the - // method we will fall back to if needed. - if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid) - { - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext()); - if (reg_ctx_sp) - { - uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber - (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - if (pc_regnum != LLDB_INVALID_REGNUM) - { - gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]); - } - } - } - new_thread_list.AddThreadSortedByIndexID (thread_sp); +bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + // locker will keep a mutex locked until it goes out of scope + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD)); + if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) + log->Printf("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, + GetID()); + + size_t num_thread_ids = m_thread_ids.size(); + // The "m_thread_ids" thread ID list should always be updated after each stop + // reply packet, but in case it isn't, update it here. + if (num_thread_ids == 0) { + if (!UpdateThreadIDList()) + return false; + num_thread_ids = m_thread_ids.size(); + } + + ThreadList old_thread_list_copy(old_thread_list); + if (num_thread_ids > 0) { + for (size_t i = 0; i < num_thread_ids; ++i) { + tid_t tid = m_thread_ids[i]; + ThreadSP thread_sp( + old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); + if (!thread_sp) { + thread_sp.reset(new ThreadGDBRemote(*this, tid)); + if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) + log->Printf("ProcessGDBRemote::%s Making new thread: %p for thread " + "ID: 0x%" PRIx64 ".\n", + __FUNCTION__, static_cast<void *>(thread_sp.get()), + thread_sp->GetID()); + } else { + if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) + log->Printf("ProcessGDBRemote::%s Found old thread: %p for thread " + "ID: 0x%" PRIx64 ".\n", + __FUNCTION__, static_cast<void *>(thread_sp.get()), + thread_sp->GetID()); + } + // The m_thread_pcs vector has pc values in big-endian order, not + // target-endian, unlike most + // of the register read/write packets in gdb-remote protocol. + // Early in the process startup, we may not yet have set the process + // ByteOrder so we ignore these; + // they are a performance improvement over fetching thread register values + // individually, the + // method we will fall back to if needed. + if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && + GetByteOrder() != eByteOrderInvalid) { + ThreadGDBRemote *gdb_thread = + static_cast<ThreadGDBRemote *>(thread_sp.get()); + RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); + if (reg_ctx_sp) { + uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_regnum != LLDB_INVALID_REGNUM) { + gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[i]); + } } + } + new_thread_list.AddThreadSortedByIndexID(thread_sp); } + } - // Whatever that is left in old_thread_list_copy are not - // present in new_thread_list. Remove non-existent threads from internal id table. - size_t old_num_thread_ids = old_thread_list_copy.GetSize(false); - for (size_t i=0; i<old_num_thread_ids; i++) - { - ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false)); - if (old_thread_sp) - { - lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); - m_thread_id_to_index_id_map.erase(old_thread_id); - } + // Whatever that is left in old_thread_list_copy are not + // present in new_thread_list. Remove non-existent threads from internal id + // table. + size_t old_num_thread_ids = old_thread_list_copy.GetSize(false); + for (size_t i = 0; i < old_num_thread_ids; i++) { + ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); + if (old_thread_sp) { + lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); + m_thread_id_to_index_id_map.erase(old_thread_id); } + } - return true; + return true; } - -bool -ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) -{ - // See if we got thread stop infos for all threads via the "jThreadsInfo" packet - if (thread_infos_sp) - { - StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray(); - if (thread_infos) - { - lldb::tid_t tid; - const size_t n = thread_infos->GetSize(); - for (size_t i=0; i<n; ++i) - { - StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); - if (thread_dict) - { - if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID)) - { - if (tid == thread->GetID()) - return (bool)SetThreadStopInfo(thread_dict); - } - } - } +bool ProcessGDBRemote::GetThreadStopInfoFromJSON( + ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) { + // See if we got thread stop infos for all threads via the "jThreadsInfo" + // packet + if (thread_infos_sp) { + StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray(); + if (thread_infos) { + lldb::tid_t tid; + const size_t n = thread_infos->GetSize(); + for (size_t i = 0; i < n; ++i) { + StructuredData::Dictionary *thread_dict = + thread_infos->GetItemAtIndex(i)->GetAsDictionary(); + if (thread_dict) { + if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>( + "tid", tid, LLDB_INVALID_THREAD_ID)) { + if (tid == thread->GetID()) + return (bool)SetThreadStopInfo(thread_dict); + } } + } } - return false; + } + return false; } -bool -ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) -{ - // See if we got thread stop infos for all threads via the "jThreadsInfo" packet - if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp)) - return true; +bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) { + // See if we got thread stop infos for all threads via the "jThreadsInfo" + // packet + if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp)) + return true; - // See if we got thread stop info for any threads valid stop info reasons threads - // via the "jstopinfo" packet stop reply packet key/value pair? - if (m_jstopinfo_sp) - { - // If we have "jstopinfo" then we have stop descriptions for all threads - // that have stop reasons, and if there is no entry for a thread, then - // it has no stop reason. - thread->GetRegisterContext()->InvalidateIfNeeded(true); - if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp)) - { - thread->SetStopInfo (StopInfoSP()); - } - return true; + // See if we got thread stop info for any threads valid stop info reasons + // threads + // via the "jstopinfo" packet stop reply packet key/value pair? + if (m_jstopinfo_sp) { + // If we have "jstopinfo" then we have stop descriptions for all threads + // that have stop reasons, and if there is no entry for a thread, then + // it has no stop reason. + thread->GetRegisterContext()->InvalidateIfNeeded(true); + if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) { + thread->SetStopInfo(StopInfoSP()); } + return true; + } - // Fall back to using the qThreadStopInfo packet - StringExtractorGDBRemote stop_packet; - if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) - return SetThreadStopInfo (stop_packet) == eStateStopped; - return false; + // Fall back to using the qThreadStopInfo packet + StringExtractorGDBRemote stop_packet; + if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) + return SetThreadStopInfo(stop_packet) == eStateStopped; + return false; } - -ThreadSP -ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, - ExpeditedRegisterMap &expedited_register_map, - uint8_t signo, - const std::string &thread_name, - const std::string &reason, - const std::string &description, - uint32_t exc_type, - const std::vector<addr_t> &exc_data, - addr_t thread_dispatch_qaddr, - bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid - LazyBool associated_with_dispatch_queue, - addr_t dispatch_queue_t, - std::string &queue_name, - QueueKind queue_kind, - uint64_t queue_serial) -{ - ThreadSP thread_sp; - if (tid != LLDB_INVALID_THREAD_ID) - { - // Scope for "locker" below - { - // m_thread_list_real does have its own mutex, but we need to - // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) - // and the m_thread_list_real.AddThread(...) so it doesn't change on us - std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); - thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); - - if (!thread_sp) - { - // Create the thread if we need to - thread_sp.reset (new ThreadGDBRemote (*this, tid)); - m_thread_list_real.AddThread(thread_sp); +ThreadSP ProcessGDBRemote::SetThreadStopInfo( + lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map, + uint8_t signo, const std::string &thread_name, const std::string &reason, + const std::string &description, uint32_t exc_type, + const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr, + bool queue_vars_valid, // Set to true if queue_name, queue_kind and + // queue_serial are valid + LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t, + std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) { + ThreadSP thread_sp; + if (tid != LLDB_INVALID_THREAD_ID) { + // Scope for "locker" below + { + // m_thread_list_real does have its own mutex, but we need to + // hold onto the mutex between the call to + // m_thread_list_real.FindThreadByID(...) + // and the m_thread_list_real.AddThread(...) so it doesn't change on us + std::lock_guard<std::recursive_mutex> guard( + m_thread_list_real.GetMutex()); + thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); + + if (!thread_sp) { + // Create the thread if we need to + thread_sp.reset(new ThreadGDBRemote(*this, tid)); + m_thread_list_real.AddThread(thread_sp); + } + } + + if (thread_sp) { + ThreadGDBRemote *gdb_thread = + static_cast<ThreadGDBRemote *>(thread_sp.get()); + gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); + + for (const auto &pair : expedited_register_map) { + StringExtractor reg_value_extractor; + reg_value_extractor.GetStringRef() = pair.second; + DataBufferSP buffer_sp(new DataBufferHeap( + reg_value_extractor.GetStringRef().size() / 2, 0)); + reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); + gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); + } + + thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str()); + + gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); + // Check if the GDB server was able to provide the queue name, kind and + // serial number + if (queue_vars_valid) + gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, + queue_serial, dispatch_queue_t, + associated_with_dispatch_queue); + else + gdb_thread->ClearQueueInfo(); + + gdb_thread->SetAssociatedWithLibdispatchQueue( + associated_with_dispatch_queue); + + if (dispatch_queue_t != LLDB_INVALID_ADDRESS) + gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); + + // Make sure we update our thread stop reason just once + if (!thread_sp->StopInfoIsUpToDate()) { + thread_sp->SetStopInfo(StopInfoSP()); + // If there's a memory thread backed by this thread, we need to use it + // to calcualte StopInfo. + ThreadSP memory_thread_sp = + m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID()); + if (memory_thread_sp) + thread_sp = memory_thread_sp; + + if (exc_type != 0) { + const size_t exc_data_size = exc_data.size(); + + thread_sp->SetStopInfo( + StopInfoMachException::CreateStopReasonWithMachException( + *thread_sp, exc_type, exc_data_size, + exc_data_size >= 1 ? exc_data[0] : 0, + exc_data_size >= 2 ? exc_data[1] : 0, + exc_data_size >= 3 ? exc_data[2] : 0)); + } else { + bool handled = false; + bool did_exec = false; + if (!reason.empty()) { + if (reason.compare("trace") == 0) { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() + ->GetBreakpointSiteList() + .FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should + // be set to Breakpoint + // Otherwise, it will be set to Trace. + if (bp_site_sp && + bp_site_sp->ValidForThisThread(thread_sp.get())) { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + } else + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonToTrace(*thread_sp)); + handled = true; + } else if (reason.compare("breakpoint") == 0) { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() + ->GetBreakpointSiteList() + .FindByAddress(pc); + if (bp_site_sp) { + // If the breakpoint is for this thread, then we'll report the + // hit, but if it is for another thread, + // we can just report no reason. We don't need to worry about + // stepping over the breakpoint here, that + // will be taken care of when the thread resumes and notices + // that there's a breakpoint under the pc. + handled = true; + if (bp_site_sp->ValidForThisThread(thread_sp.get())) { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + } else { + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo(invalid_stop_info_sp); + } + } + } else if (reason.compare("trap") == 0) { + // Let the trap just use the standard signal stop reason below... + } else if (reason.compare("watchpoint") == 0) { + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) { + WatchpointSP wp_sp; + ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); + if ((core >= ArchSpec::kCore_mips_first && + core <= ArchSpec::kCore_mips_last) || + (core >= ArchSpec::eCore_arm_generic && + core <= ArchSpec::eCore_arm_aarch64)) + wp_sp = GetTarget().GetWatchpointList().FindByAddress( + wp_hit_addr); + if (!wp_sp) + wp_sp = + GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); + } + } + if (watch_id == LLDB_INVALID_WATCH_ID) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( + GDBR_LOG_WATCHPOINTS)); + if (log) + log->Printf("failed to find watchpoint"); + } + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( + *thread_sp, watch_id, wp_hit_addr)); + handled = true; + } else if (reason.compare("exception") == 0) { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( + *thread_sp, description.c_str())); + handled = true; + } else if (reason.compare("exec") == 0) { + did_exec = true; + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithExec(*thread_sp)); + handled = true; } - } - - if (thread_sp) - { - ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); - gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); - - for (const auto &pair : expedited_register_map) - { - StringExtractor reg_value_extractor; - reg_value_extractor.GetStringRef() = pair.second; - DataBufferSP buffer_sp(new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); - reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); - gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); + } else if (!signo) { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( + pc); + + // If the current pc is a breakpoint site then the StopInfo should + // be set to Breakpoint + // even though the remote stub did not set it as such. This can + // happen when + // the thread is involuntarily interrupted (e.g. due to stops on + // other + // threads) just as it is about to execute the breakpoint + // instruction. + if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + handled = true; } - - thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str()); - - gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); - // Check if the GDB server was able to provide the queue name, kind and serial number - if (queue_vars_valid) - gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue); - else - gdb_thread->ClearQueueInfo(); - - gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue); - - if (dispatch_queue_t != LLDB_INVALID_ADDRESS) - gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t); - - // Make sure we update our thread stop reason just once - if (!thread_sp->StopInfoIsUpToDate()) - { - thread_sp->SetStopInfo (StopInfoSP()); - // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo. - ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID()); - if (memory_thread_sp) - thread_sp = memory_thread_sp; - - if (exc_type != 0) - { - const size_t exc_data_size = exc_data.size(); - - thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, - exc_type, - exc_data_size, - exc_data_size >= 1 ? exc_data[0] : 0, - exc_data_size >= 2 ? exc_data[1] : 0, - exc_data_size >= 3 ? exc_data[2] : 0)); + } + + if (!handled && signo && did_exec == false) { + if (signo == SIGTRAP) { + // Currently we are going to assume SIGTRAP means we are either + // hitting a breakpoint or hardware single stepping. + handled = true; + addr_t pc = thread_sp->GetRegisterContext()->GetPC() + + m_breakpoint_pc_offset; + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() + ->GetBreakpointSiteList() + .FindByAddress(pc); + + if (bp_site_sp) { + // If the breakpoint is for this thread, then we'll report the + // hit, but if it is for another thread, + // we can just report no reason. We don't need to worry about + // stepping over the breakpoint here, that + // will be taken care of when the thread resumes and notices + // that there's a breakpoint under the pc. + if (bp_site_sp->ValidForThisThread(thread_sp.get())) { + if (m_breakpoint_pc_offset != 0) + thread_sp->GetRegisterContext()->SetPC(pc); + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + } else { + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo(invalid_stop_info_sp); } + } else { + // If we were stepping then assume the stop was the result of + // the trace. If we were + // not stepping then report the SIGTRAP. + // FIXME: We are still missing the case where we single step + // over a trap instruction. + if (thread_sp->GetTemporaryResumeState() == eStateStepping) + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonToTrace(*thread_sp)); else - { - bool handled = false; - bool did_exec = false; - if (!reason.empty()) - { - if (reason.compare("trace") == 0) - { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - - // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint - // Otherwise, it will be set to Trace. - if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) - { - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); - } - else - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); - handled = true; - } - else if (reason.compare("breakpoint") == 0) - { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp) - { - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - handled = true; - if (bp_site_sp->ValidForThisThread (thread_sp.get())) - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); - } - else - { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo (invalid_stop_info_sp); - } - } - } - else if (reason.compare("trap") == 0) - { - // Let the trap just use the standard signal stop reason below... - } - else if (reason.compare("watchpoint") == 0) - { - StringExtractor desc_extractor(description.c_str()); - addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); - addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - watch_id_t watch_id = LLDB_INVALID_WATCH_ID; - if (wp_addr != LLDB_INVALID_ADDRESS) - { - WatchpointSP wp_sp; - ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) || - (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64)) - wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); - if (!wp_sp) - wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); - if (wp_sp) - { - wp_sp->SetHardwareIndex(wp_index); - watch_id = wp_sp->GetID(); - } - } - if (watch_id == LLDB_INVALID_WATCH_ID) - { - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); - if (log) log->Printf ("failed to find watchpoint"); - } - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr)); - handled = true; - } - else if (reason.compare("exception") == 0) - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); - handled = true; - } - else if (reason.compare("exec") == 0) - { - did_exec = true; - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); - handled = true; - } - } - else if (!signo) - { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = - thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - - // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint - // even though the remote stub did not set it as such. This can happen when - // the thread is involuntarily interrupted (e.g. due to stops on other - // threads) just as it is about to execute the breakpoint instruction. - if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) - { - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); - handled = true; - } - } - - if (!handled && signo && did_exec == false) - { - if (signo == SIGTRAP) - { - // Currently we are going to assume SIGTRAP means we are either - // hitting a breakpoint or hardware single stepping. - handled = true; - addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - - if (bp_site_sp) - { - // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - if (bp_site_sp->ValidForThisThread (thread_sp.get())) - { - if(m_breakpoint_pc_offset != 0) - thread_sp->GetRegisterContext()->SetPC(pc); - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); - } - else - { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo (invalid_stop_info_sp); - } - } - else - { - // If we were stepping then assume the stop was the result of the trace. If we were - // not stepping then report the SIGTRAP. - // FIXME: We are still missing the case where we single step over a trap instruction. - if (thread_sp->GetTemporaryResumeState() == eStateStepping) - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); - else - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str())); - } - } - if (!handled) - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str())); - } - - if (!description.empty()) - { - lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); - if (stop_info_sp) - { - const char *stop_info_desc = stop_info_sp->GetDescription(); - if (!stop_info_desc || !stop_info_desc[0]) - stop_info_sp->SetDescription (description.c_str()); - } - else - { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); - } - } - } + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *thread_sp, signo, description.c_str())); + } + } + if (!handled) + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *thread_sp, signo, description.c_str())); + } + + if (!description.empty()) { + lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); + if (stop_info_sp) { + const char *stop_info_desc = stop_info_sp->GetDescription(); + if (!stop_info_desc || !stop_info_desc[0]) + stop_info_sp->SetDescription(description.c_str()); + } else { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( + *thread_sp, description.c_str())); } + } } + } } - return thread_sp; + } + return thread_sp; } lldb::ThreadSP -ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict) -{ - static ConstString g_key_tid("tid"); - static ConstString g_key_name("name"); - static ConstString g_key_reason("reason"); - static ConstString g_key_metype("metype"); - static ConstString g_key_medata("medata"); - static ConstString g_key_qaddr("qaddr"); - static ConstString g_key_dispatch_queue_t("dispatch_queue_t"); - static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue"); - static ConstString g_key_queue_name("qname"); - static ConstString g_key_queue_kind("qkind"); - static ConstString g_key_queue_serial_number("qserialnum"); - static ConstString g_key_registers("registers"); - static ConstString g_key_memory("memory"); - static ConstString g_key_address("address"); - static ConstString g_key_bytes("bytes"); - static ConstString g_key_description("description"); - static ConstString g_key_signal("signal"); +ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { + static ConstString g_key_tid("tid"); + static ConstString g_key_name("name"); + static ConstString g_key_reason("reason"); + static ConstString g_key_metype("metype"); + static ConstString g_key_medata("medata"); + static ConstString g_key_qaddr("qaddr"); + static ConstString g_key_dispatch_queue_t("dispatch_queue_t"); + static ConstString g_key_associated_with_dispatch_queue( + "associated_with_dispatch_queue"); + static ConstString g_key_queue_name("qname"); + static ConstString g_key_queue_kind("qkind"); + static ConstString g_key_queue_serial_number("qserialnum"); + static ConstString g_key_registers("registers"); + static ConstString g_key_memory("memory"); + static ConstString g_key_address("address"); + static ConstString g_key_bytes("bytes"); + static ConstString g_key_description("description"); + static ConstString g_key_signal("signal"); + + // Stop with signal and thread info + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + uint8_t signo = 0; + std::string value; + std::string thread_name; + std::string reason; + std::string description; + uint32_t exc_type = 0; + std::vector<addr_t> exc_data; + addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; + ExpeditedRegisterMap expedited_register_map; + bool queue_vars_valid = false; + addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; + LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; + std::string queue_name; + QueueKind queue_kind = eQueueKindUnknown; + uint64_t queue_serial_number = 0; + // Iterate through all of the thread dictionary key/value pairs from the + // structured data dictionary + + thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name, + &signo, &reason, &description, &exc_type, &exc_data, + &thread_dispatch_qaddr, &queue_vars_valid, + &associated_with_dispatch_queue, &dispatch_queue_t, + &queue_name, &queue_kind, &queue_serial_number]( + ConstString key, + StructuredData::Object *object) -> bool { + if (key == g_key_tid) { + // thread in big endian hex + tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID); + } else if (key == g_key_metype) { + // exception type in big endian hex + exc_type = object->GetIntegerValue(0); + } else if (key == g_key_medata) { + // exception data in big endian hex + StructuredData::Array *array = object->GetAsArray(); + if (array) { + array->ForEach([&exc_data](StructuredData::Object *object) -> bool { + exc_data.push_back(object->GetIntegerValue()); + return true; // Keep iterating through all array items + }); + } + } else if (key == g_key_name) { + thread_name = object->GetStringValue(); + } else if (key == g_key_qaddr) { + thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS); + } else if (key == g_key_queue_name) { + queue_vars_valid = true; + queue_name = object->GetStringValue(); + } else if (key == g_key_queue_kind) { + std::string queue_kind_str = object->GetStringValue(); + if (queue_kind_str == "serial") { + queue_vars_valid = true; + queue_kind = eQueueKindSerial; + } else if (queue_kind_str == "concurrent") { + queue_vars_valid = true; + queue_kind = eQueueKindConcurrent; + } + } else if (key == g_key_queue_serial_number) { + queue_serial_number = object->GetIntegerValue(0); + if (queue_serial_number != 0) + queue_vars_valid = true; + } else if (key == g_key_dispatch_queue_t) { + dispatch_queue_t = object->GetIntegerValue(0); + if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS) + queue_vars_valid = true; + } else if (key == g_key_associated_with_dispatch_queue) { + queue_vars_valid = true; + bool associated = object->GetBooleanValue(); + if (associated) + associated_with_dispatch_queue = eLazyBoolYes; + else + associated_with_dispatch_queue = eLazyBoolNo; + } else if (key == g_key_reason) { + reason = object->GetStringValue(); + } else if (key == g_key_description) { + description = object->GetStringValue(); + } else if (key == g_key_registers) { + StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); + + if (registers_dict) { + registers_dict->ForEach( + [&expedited_register_map](ConstString key, + StructuredData::Object *object) -> bool { + const uint32_t reg = + StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10); + if (reg != UINT32_MAX) + expedited_register_map[reg] = object->GetStringValue(); + return true; // Keep iterating through all array items + }); + } + } else if (key == g_key_memory) { + StructuredData::Array *array = object->GetAsArray(); + if (array) { + array->ForEach([this](StructuredData::Object *object) -> bool { + StructuredData::Dictionary *mem_cache_dict = + object->GetAsDictionary(); + if (mem_cache_dict) { + lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; + if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>( + "address", mem_cache_addr)) { + if (mem_cache_addr != LLDB_INVALID_ADDRESS) { + StringExtractor bytes; + if (mem_cache_dict->GetValueForKeyAsString( + "bytes", bytes.GetStringRef())) { + bytes.SetFilePos(0); + + const size_t byte_size = bytes.GetStringRef().size() / 2; + DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); + const size_t bytes_copied = + bytes.GetHexBytes(data_buffer_sp->GetData(), 0); + if (bytes_copied == byte_size) + m_memory_cache.AddL1CacheData(mem_cache_addr, + data_buffer_sp); + } + } + } + } + return true; // Keep iterating through all array items + }); + } + + } else if (key == g_key_signal) + signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER); + return true; // Keep iterating through all dictionary key/value pairs + }); + + return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name, + reason, description, exc_type, exc_data, + thread_dispatch_qaddr, queue_vars_valid, + associated_with_dispatch_queue, dispatch_queue_t, + queue_name, queue_kind, queue_serial_number); +} +StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { + stop_packet.SetFilePos(0); + const char stop_type = stop_packet.GetChar(); + switch (stop_type) { + case 'T': + case 'S': { + // This is a bit of a hack, but is is required. If we did exec, we + // need to clear our thread lists and also know to rebuild our dynamic + // register info before we lookup and threads and populate the expedited + // register values so we need to know this right away so we can cleanup + // and update our registers. + const uint32_t stop_id = GetStopID(); + if (stop_id == 0) { + // Our first stop, make sure we have a process ID, and also make + // sure we know about our registers + if (GetID() == LLDB_INVALID_PROCESS_ID) { + lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) + SetID(pid); + } + BuildDynamicRegisterInfo(true); + } // Stop with signal and thread info lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - uint8_t signo = 0; - std::string value; + const uint8_t signo = stop_packet.GetHexU8(); + llvm::StringRef key; + llvm::StringRef value; std::string thread_name; std::string reason; std::string description; uint32_t exc_type = 0; std::vector<addr_t> exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; - ExpeditedRegisterMap expedited_register_map; - bool queue_vars_valid = false; + bool queue_vars_valid = + false; // says if locals below that start with "queue_" are valid addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; std::string queue_name; QueueKind queue_kind = eQueueKindUnknown; uint64_t queue_serial_number = 0; - // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary - - thread_dict->ForEach([this, - &tid, - &expedited_register_map, - &thread_name, - &signo, - &reason, - &description, - &exc_type, - &exc_data, - &thread_dispatch_qaddr, - &queue_vars_valid, - &associated_with_dispatch_queue, - &dispatch_queue_t, - &queue_name, - &queue_kind, - &queue_serial_number] - (ConstString key, StructuredData::Object* object) -> bool - { - if (key == g_key_tid) - { - // thread in big endian hex - tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID); - } - else if (key == g_key_metype) - { - // exception type in big endian hex - exc_type = object->GetIntegerValue(0); - } - else if (key == g_key_medata) - { - // exception data in big endian hex - StructuredData::Array *array = object->GetAsArray(); - if (array) - { - array->ForEach([&exc_data](StructuredData::Object* object) -> bool { - exc_data.push_back(object->GetIntegerValue()); - return true; // Keep iterating through all array items - }); - } - } - else if (key == g_key_name) - { - thread_name = object->GetStringValue(); - } - else if (key == g_key_qaddr) - { - thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS); - } - else if (key == g_key_queue_name) - { - queue_vars_valid = true; - queue_name = object->GetStringValue(); - } - else if (key == g_key_queue_kind) - { - std::string queue_kind_str = object->GetStringValue(); - if (queue_kind_str == "serial") - { - queue_vars_valid = true; - queue_kind = eQueueKindSerial; - } - else if (queue_kind_str == "concurrent") - { - queue_vars_valid = true; - queue_kind = eQueueKindConcurrent; - } - } - else if (key == g_key_queue_serial_number) - { - queue_serial_number = object->GetIntegerValue(0); - if (queue_serial_number != 0) - queue_vars_valid = true; - } - else if (key == g_key_dispatch_queue_t) - { - dispatch_queue_t = object->GetIntegerValue(0); - if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS) - queue_vars_valid = true; - } - else if (key == g_key_associated_with_dispatch_queue) - { - queue_vars_valid = true; - bool associated = object->GetBooleanValue (); - if (associated) - associated_with_dispatch_queue = eLazyBoolYes; - else - associated_with_dispatch_queue = eLazyBoolNo; - } - else if (key == g_key_reason) - { - reason = object->GetStringValue(); + ExpeditedRegisterMap expedited_register_map; + while (stop_packet.GetNameColonValue(key, value)) { + if (key.compare("metype") == 0) { + // exception type in big endian hex + value.getAsInteger(16, exc_type); + } else if (key.compare("medata") == 0) { + // exception data in big endian hex + uint64_t x; + value.getAsInteger(16, x); + exc_data.push_back(x); + } else if (key.compare("thread") == 0) { + // thread in big endian hex + if (value.getAsInteger(16, tid)) + tid = LLDB_INVALID_THREAD_ID; + } else if (key.compare("threads") == 0) { + std::lock_guard<std::recursive_mutex> guard( + m_thread_list_real.GetMutex()); + + m_thread_ids.clear(); + // A comma separated list of all threads in the current + // process that includes the thread for this stop reply + // packet + lldb::tid_t tid; + while (!value.empty()) { + llvm::StringRef tid_str; + std::tie(tid_str, value) = value.split(','); + if (tid_str.getAsInteger(16, tid)) + tid = LLDB_INVALID_THREAD_ID; + m_thread_ids.push_back(tid); } - else if (key == g_key_description) - { - description = object->GetStringValue(); + } else if (key.compare("thread-pcs") == 0) { + m_thread_pcs.clear(); + // A comma separated list of all threads in the current + // process that includes the thread for this stop reply + // packet + lldb::addr_t pc; + while (!value.empty()) { + llvm::StringRef pc_str; + std::tie(pc_str, value) = value.split(','); + if (pc_str.getAsInteger(16, pc)) + pc = LLDB_INVALID_ADDRESS; + m_thread_pcs.push_back(pc); } - else if (key == g_key_registers) - { - StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); - - if (registers_dict) - { - registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool { - const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10); - if (reg != UINT32_MAX) - expedited_register_map[reg] = object->GetStringValue(); - return true; // Keep iterating through all array items - }); - } - } - else if (key == g_key_memory) - { - StructuredData::Array *array = object->GetAsArray(); - if (array) - { - array->ForEach([this](StructuredData::Object* object) -> bool { - StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary(); - if (mem_cache_dict) - { - lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; - if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>("address", mem_cache_addr)) - { - if (mem_cache_addr != LLDB_INVALID_ADDRESS) - { - StringExtractor bytes; - if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef())) - { - bytes.SetFilePos(0); - - const size_t byte_size = bytes.GetStringRef().size()/2; - DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); - const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetData(), 0); - if (bytes_copied == byte_size) - m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); - } - } - } - } - return true; // Keep iterating through all array items - }); - } - + } else if (key.compare("jstopinfo") == 0) { + StringExtractor json_extractor(value); + std::string json; + // Now convert the HEX bytes into a string value + json_extractor.GetHexByteString(json); + + // This JSON contains thread IDs and thread stop info for all threads. + // It doesn't contain expedited registers, memory or queue info. + m_jstopinfo_sp = StructuredData::ParseJSON(json); + } else if (key.compare("hexname") == 0) { + StringExtractor name_extractor(value); + std::string name; + // Now convert the HEX bytes into a string value + name_extractor.GetHexByteString(thread_name); + } else if (key.compare("name") == 0) { + thread_name = value; + } else if (key.compare("qaddr") == 0) { + value.getAsInteger(16, thread_dispatch_qaddr); + } else if (key.compare("dispatch_queue_t") == 0) { + queue_vars_valid = true; + value.getAsInteger(16, dispatch_queue_t); + } else if (key.compare("qname") == 0) { + queue_vars_valid = true; + StringExtractor name_extractor(value); + // Now convert the HEX bytes into a string value + name_extractor.GetHexByteString(queue_name); + } else if (key.compare("qkind") == 0) { + queue_kind = llvm::StringSwitch<QueueKind>(value) + .Case("serial", eQueueKindSerial) + .Case("concurrent", eQueueKindConcurrent) + .Default(eQueueKindUnknown); + queue_vars_valid = queue_kind != eQueueKindUnknown; + } else if (key.compare("qserialnum") == 0) { + if (!value.getAsInteger(0, queue_serial_number)) + queue_vars_valid = true; + } else if (key.compare("reason") == 0) { + reason = value; + } else if (key.compare("description") == 0) { + StringExtractor desc_extractor(value); + // Now convert the HEX bytes into a string value + desc_extractor.GetHexByteString(description); + } else if (key.compare("memory") == 0) { + // Expedited memory. GDB servers can choose to send back expedited + // memory + // that can populate the L1 memory cache in the process so that things + // like + // the frame pointer backchain can be expedited. This will help stack + // backtracing be more efficient by not having to send as many memory + // read + // requests down the remote GDB server. + + // Key/value pair format: memory:<addr>=<bytes>; + // <addr> is a number whose base will be interpreted by the prefix: + // "0x[0-9a-fA-F]+" for hex + // "0[0-7]+" for octal + // "[1-9]+" for decimal + // <bytes> is native endian ASCII hex bytes just like the register + // values + llvm::StringRef addr_str, bytes_str; + std::tie(addr_str, bytes_str) = value.split('='); + if (!addr_str.empty() && !bytes_str.empty()) { + lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; + if (!addr_str.getAsInteger(0, mem_cache_addr)) { + StringExtractor bytes(bytes_str); + const size_t byte_size = bytes.GetBytesLeft() / 2; + DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); + const size_t bytes_copied = + bytes.GetHexBytes(data_buffer_sp->GetData(), 0); + if (bytes_copied == byte_size) + m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); + } } - else if (key == g_key_signal) - signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER); - return true; // Keep iterating through all dictionary key/value pairs - }); - - return SetThreadStopInfo (tid, - expedited_register_map, - signo, - thread_name, - reason, - description, - exc_type, - exc_data, - thread_dispatch_qaddr, - queue_vars_valid, - associated_with_dispatch_queue, - dispatch_queue_t, - queue_name, - queue_kind, - queue_serial_number); + } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || + key.compare("awatch") == 0) { + // Support standard GDB remote stop reply packet 'TAAwatch:addr' + lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; + value.getAsInteger(16, wp_addr); + + WatchpointSP wp_sp = + GetTarget().GetWatchpointList().FindByAddress(wp_addr); + uint32_t wp_index = LLDB_INVALID_INDEX32; + + if (wp_sp) + wp_index = wp_sp->GetHardwareIndex(); + + reason = "watchpoint"; + StreamString ostr; + ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); + description = ostr.GetString().c_str(); + } else if (key.compare("library") == 0) { + LoadModules(); + } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { + uint32_t reg = UINT32_MAX; + if (!key.getAsInteger(16, reg)) + expedited_register_map[reg] = std::move(value); + } + } + + if (tid == LLDB_INVALID_THREAD_ID) { + // A thread id may be invalid if the response is old style 'S' packet + // which does not provide the + // thread information. So update the thread list and choose the first one. + UpdateThreadIDList(); + + if (!m_thread_ids.empty()) { + tid = m_thread_ids.front(); + } + } + + ThreadSP thread_sp = SetThreadStopInfo( + tid, expedited_register_map, signo, thread_name, reason, description, + exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, + associated_with_dispatch_queue, dispatch_queue_t, queue_name, + queue_kind, queue_serial_number); + + return eStateStopped; + } break; + + case 'W': + case 'X': + // process exited + return eStateExited; + + default: + break; + } + return eStateInvalid; } -StateType -ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) -{ - stop_packet.SetFilePos (0); - const char stop_type = stop_packet.GetChar(); - switch (stop_type) - { - case 'T': - case 'S': - { - // This is a bit of a hack, but is is required. If we did exec, we - // need to clear our thread lists and also know to rebuild our dynamic - // register info before we lookup and threads and populate the expedited - // register values so we need to know this right away so we can cleanup - // and update our registers. - const uint32_t stop_id = GetStopID(); - if (stop_id == 0) - { - // Our first stop, make sure we have a process ID, and also make - // sure we know about our registers - if (GetID() == LLDB_INVALID_PROCESS_ID) - { - lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID (); - if (pid != LLDB_INVALID_PROCESS_ID) - SetID (pid); - } - BuildDynamicRegisterInfo (true); - } - // Stop with signal and thread info - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - const uint8_t signo = stop_packet.GetHexU8(); - llvm::StringRef key; - llvm::StringRef value; - std::string thread_name; - std::string reason; - std::string description; - uint32_t exc_type = 0; - std::vector<addr_t> exc_data; - addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; - bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid - addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; - LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; - std::string queue_name; - QueueKind queue_kind = eQueueKindUnknown; - uint64_t queue_serial_number = 0; - ExpeditedRegisterMap expedited_register_map; - while (stop_packet.GetNameColonValue(key, value)) - { - if (key.compare("metype") == 0) - { - // exception type in big endian hex - value.getAsInteger(16, exc_type); - } - else if (key.compare("medata") == 0) - { - // exception data in big endian hex - uint64_t x; - value.getAsInteger(16, x); - exc_data.push_back(x); - } - else if (key.compare("thread") == 0) - { - // thread in big endian hex - if (value.getAsInteger(16, tid)) - tid = LLDB_INVALID_THREAD_ID; - } - else if (key.compare("threads") == 0) - { - std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); - - m_thread_ids.clear(); - // A comma separated list of all threads in the current - // process that includes the thread for this stop reply - // packet - lldb::tid_t tid; - while (!value.empty()) - { - llvm::StringRef tid_str; - std::tie(tid_str, value) = value.split(','); - if (tid_str.getAsInteger(16, tid)) - tid = LLDB_INVALID_THREAD_ID; - m_thread_ids.push_back(tid); - } - } - else if (key.compare("thread-pcs") == 0) - { - m_thread_pcs.clear(); - // A comma separated list of all threads in the current - // process that includes the thread for this stop reply - // packet - lldb::addr_t pc; - while (!value.empty()) - { - llvm::StringRef pc_str; - std::tie(pc_str, value) = value.split(','); - if (pc_str.getAsInteger(16, pc)) - pc = LLDB_INVALID_ADDRESS; - m_thread_pcs.push_back(pc); - } - } - else if (key.compare("jstopinfo") == 0) - { - StringExtractor json_extractor(value); - std::string json; - // Now convert the HEX bytes into a string value - json_extractor.GetHexByteString(json); - - // This JSON contains thread IDs and thread stop info for all threads. - // It doesn't contain expedited registers, memory or queue info. - m_jstopinfo_sp = StructuredData::ParseJSON(json); - } - else if (key.compare("hexname") == 0) - { - StringExtractor name_extractor(value); - std::string name; - // Now convert the HEX bytes into a string value - name_extractor.GetHexByteString(thread_name); - } - else if (key.compare("name") == 0) - { - thread_name = value; - } - else if (key.compare("qaddr") == 0) - { - value.getAsInteger(16, thread_dispatch_qaddr); - } - else if (key.compare("dispatch_queue_t") == 0) - { - queue_vars_valid = true; - value.getAsInteger(16, dispatch_queue_t); - } - else if (key.compare("qname") == 0) - { - queue_vars_valid = true; - StringExtractor name_extractor(value); - // Now convert the HEX bytes into a string value - name_extractor.GetHexByteString(queue_name); - } - else if (key.compare("qkind") == 0) - { - queue_kind = llvm::StringSwitch<QueueKind>(value) - .Case("serial", eQueueKindSerial) - .Case("concurrent", eQueueKindConcurrent) - .Default(eQueueKindUnknown); - queue_vars_valid = queue_kind != eQueueKindUnknown; - } - else if (key.compare("qserialnum") == 0) - { - if (!value.getAsInteger(0, queue_serial_number)) - queue_vars_valid = true; - } - else if (key.compare("reason") == 0) - { - reason = value; - } - else if (key.compare("description") == 0) - { - StringExtractor desc_extractor(value); - // Now convert the HEX bytes into a string value - desc_extractor.GetHexByteString(description); - } - else if (key.compare("memory") == 0) - { - // Expedited memory. GDB servers can choose to send back expedited memory - // that can populate the L1 memory cache in the process so that things like - // the frame pointer backchain can be expedited. This will help stack - // backtracing be more efficient by not having to send as many memory read - // requests down the remote GDB server. - - // Key/value pair format: memory:<addr>=<bytes>; - // <addr> is a number whose base will be interpreted by the prefix: - // "0x[0-9a-fA-F]+" for hex - // "0[0-7]+" for octal - // "[1-9]+" for decimal - // <bytes> is native endian ASCII hex bytes just like the register values - llvm::StringRef addr_str, bytes_str; - std::tie(addr_str, bytes_str) = value.split('='); - if (!addr_str.empty() && !bytes_str.empty()) - { - lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; - if (!addr_str.getAsInteger(0, mem_cache_addr)) - { - StringExtractor bytes(bytes_str); - const size_t byte_size = bytes.GetBytesLeft() / 2; - DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); - const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetData(), 0); - if (bytes_copied == byte_size) - m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); - } - } - } - else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || key.compare("awatch") == 0) - { - // Support standard GDB remote stop reply packet 'TAAwatch:addr' - lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; - value.getAsInteger(16, wp_addr); - - WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); - uint32_t wp_index = LLDB_INVALID_INDEX32; - - if (wp_sp) - wp_index = wp_sp->GetHardwareIndex(); - - reason = "watchpoint"; - StreamString ostr; - ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); - description = ostr.GetString().c_str(); - } - else if (key.compare("library") == 0) - { - LoadModules(); - } - else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) - { - uint32_t reg = UINT32_MAX; - if (!key.getAsInteger(16, reg)) - expedited_register_map[reg] = std::move(value); - } - } - - if (tid == LLDB_INVALID_THREAD_ID) - { - // A thread id may be invalid if the response is old style 'S' packet which does not provide the - // thread information. So update the thread list and choose the first one. - UpdateThreadIDList (); - - if (!m_thread_ids.empty ()) - { - tid = m_thread_ids.front (); - } - } - - ThreadSP thread_sp = SetThreadStopInfo (tid, - expedited_register_map, - signo, - thread_name, - reason, - description, - exc_type, - exc_data, - thread_dispatch_qaddr, - queue_vars_valid, - associated_with_dispatch_queue, - dispatch_queue_t, - queue_name, - queue_kind, - queue_serial_number); - - return eStateStopped; - } - break; - - case 'W': - case 'X': - // process exited - return eStateExited; - - default: - break; - } - return eStateInvalid; +void ProcessGDBRemote::RefreshStateAfterStop() { + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + + m_thread_ids.clear(); + m_thread_pcs.clear(); + // Set the thread stop info. It might have a "threads" key whose value is + // a list of all thread IDs in the current process, so m_thread_ids might + // get set. + + // Scope for the lock + { + // Lock the thread stack while we access it + std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); + // Get the number of stop packets on the stack + int nItems = m_stop_packet_stack.size(); + // Iterate over them + for (int i = 0; i < nItems; i++) { + // Get the thread stop info + StringExtractorGDBRemote stop_info = m_stop_packet_stack[i]; + // Process thread stop info + SetThreadStopInfo(stop_info); + } + // Clear the thread stop stack + m_stop_packet_stack.clear(); + } + + // Check to see if SetThreadStopInfo() filled in m_thread_ids? + if (m_thread_ids.empty()) { + // No, we need to fetch the thread list manually + UpdateThreadIDList(); + } + + // If we have queried for a default thread id + if (m_initial_tid != LLDB_INVALID_THREAD_ID) { + m_thread_list.SetSelectedThreadByID(m_initial_tid); + m_initial_tid = LLDB_INVALID_THREAD_ID; + } + + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + m_thread_list_real.RefreshStateAfterStop(); } -void -ProcessGDBRemote::RefreshStateAfterStop () -{ - std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); - - m_thread_ids.clear(); - m_thread_pcs.clear(); - // Set the thread stop info. It might have a "threads" key whose value is - // a list of all thread IDs in the current process, so m_thread_ids might - // get set. - - // Scope for the lock - { - // Lock the thread stack while we access it - std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); - // Get the number of stop packets on the stack - int nItems = m_stop_packet_stack.size(); - // Iterate over them - for (int i = 0; i < nItems; i++) - { - // Get the thread stop info - StringExtractorGDBRemote stop_info = m_stop_packet_stack[i]; - // Process thread stop info - SetThreadStopInfo(stop_info); - } - // Clear the thread stop stack - m_stop_packet_stack.clear(); - } - - // Check to see if SetThreadStopInfo() filled in m_thread_ids? - if (m_thread_ids.empty()) - { - // No, we need to fetch the thread list manually - UpdateThreadIDList(); - } - - // If we have queried for a default thread id - if (m_initial_tid != LLDB_INVALID_THREAD_ID) - { - m_thread_list.SetSelectedThreadByID(m_initial_tid); - m_initial_tid = LLDB_INVALID_THREAD_ID; - } - - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - m_thread_list_real.RefreshStateAfterStop(); +Error ProcessGDBRemote::DoHalt(bool &caused_stop) { + Error error; + if (m_public_state.GetValue() == eStateAttaching) { + // We are being asked to halt during an attach. We need to just close + // our file handle and debugserver will go away, and we can be done... + m_gdb_comm.Disconnect(); + } else + caused_stop = m_gdb_comm.Interrupt(); + return error; } -Error -ProcessGDBRemote::DoHalt (bool &caused_stop) -{ - Error error; +Error ProcessGDBRemote::DoDetach(bool keep_stopped) { + Error error; + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); - if (m_public_state.GetValue() == eStateAttaching) - { - // We are being asked to halt during an attach. We need to just close - // our file handle and debugserver will go away, and we can be done... - m_gdb_comm.Disconnect(); - } + error = m_gdb_comm.Detach(keep_stopped); + if (log) { + if (error.Success()) + log->PutCString( + "ProcessGDBRemote::DoDetach() detach packet sent successfully"); else - caused_stop = m_gdb_comm.Interrupt(); - return error; -} + log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s", + error.AsCString() ? error.AsCString() : "<unknown error>"); + } -Error -ProcessGDBRemote::DoDetach(bool keep_stopped) -{ - Error error; - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); - - error = m_gdb_comm.Detach (keep_stopped); - if (log) - { - if (error.Success()) - log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully"); - else - log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>"); - } - - if (!error.Success()) - return error; + if (!error.Success()) + return error; - // Sleep for one second to let the process get all detached... - StopAsyncThread (); + // Sleep for one second to let the process get all detached... + StopAsyncThread(); - SetPrivateState (eStateDetached); - ResumePrivateStateThread(); + SetPrivateState(eStateDetached); + ResumePrivateStateThread(); - //KillDebugserverProcess (); - return error; + // KillDebugserverProcess (); + return error; } +Error ProcessGDBRemote::DoDestroy() { + Error error; + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::DoDestroy()"); + + // There is a bug in older iOS debugservers where they don't shut down the + // process + // they are debugging properly. If the process is sitting at a breakpoint or + // an exception, + // this can cause problems with restarting. So we check to see if any of our + // threads are stopped + // at a breakpoint, and if so we remove all the breakpoints, resume the + // process, and THEN + // destroy it again. + // + // Note, we don't have a good way to test the version of debugserver, but I + // happen to know that + // the set of all the iOS debugservers which don't support + // GetThreadSuffixSupported() and that of + // the debugservers with this bug are equal. There really should be a better + // way to test this! + // + // We also use m_destroy_tried_resuming to make sure we only do this once, if + // we resume and then halt and + // get called here to destroy again and we're still at a breakpoint or + // exception, then we should + // just do the straight-forward kill. + // + // And of course, if we weren't able to stop the process by the time we get + // here, it isn't + // necessary (or helpful) to do any of this. + + if (!m_gdb_comm.GetThreadSuffixSupported() && + m_public_state.GetValue() != eStateRunning) { + PlatformSP platform_sp = GetTarget().GetPlatform(); + + // FIXME: These should be ConstStrings so we aren't doing strcmp'ing. + if (platform_sp && platform_sp->GetName() && + platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) { + if (m_destroy_tried_resuming) { + if (log) + log->PutCString("ProcessGDBRemote::DoDestroy() - Tried resuming to " + "destroy once already, not doing it again."); + } else { + // At present, the plans are discarded and the breakpoints disabled + // Process::Destroy, + // but we really need it to happen here and it doesn't matter if we do + // it twice. + m_thread_list.DiscardThreadPlans(); + DisableAllBreakpointSites(); + + bool stop_looks_like_crash = false; + ThreadList &threads = GetThreadList(); -Error -ProcessGDBRemote::DoDestroy () -{ - Error error; - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::DoDestroy()"); - - // There is a bug in older iOS debugservers where they don't shut down the process - // they are debugging properly. If the process is sitting at a breakpoint or an exception, - // this can cause problems with restarting. So we check to see if any of our threads are stopped - // at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN - // destroy it again. - // - // Note, we don't have a good way to test the version of debugserver, but I happen to know that - // the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of - // the debugservers with this bug are equal. There really should be a better way to test this! - // - // We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and - // get called here to destroy again and we're still at a breakpoint or exception, then we should - // just do the straight-forward kill. - // - // And of course, if we weren't able to stop the process by the time we get here, it isn't - // necessary (or helpful) to do any of this. - - if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning) - { - PlatformSP platform_sp = GetTarget().GetPlatform(); - - // FIXME: These should be ConstStrings so we aren't doing strcmp'ing. - if (platform_sp - && platform_sp->GetName() - && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) { - if (m_destroy_tried_resuming) - { - if (log) - log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again."); + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); + + size_t num_threads = threads.GetSize(); + for (size_t i = 0; i < num_threads; i++) { + ThreadSP thread_sp = threads.GetThreadAtIndex(i); + StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); + StopReason reason = eStopReasonInvalid; + if (stop_info_sp) + reason = stop_info_sp->GetStopReason(); + if (reason == eStopReasonBreakpoint || + reason == eStopReasonException) { + if (log) + log->Printf( + "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 + " stopped with reason: %s.", + thread_sp->GetProtocolID(), stop_info_sp->GetDescription()); + stop_looks_like_crash = true; + break; } - else - { - // At present, the plans are discarded and the breakpoints disabled Process::Destroy, - // but we really need it to happen here and it doesn't matter if we do it twice. - m_thread_list.DiscardThreadPlans(); - DisableAllBreakpointSites(); - - bool stop_looks_like_crash = false; - ThreadList &threads = GetThreadList(); - - { - std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); - - size_t num_threads = threads.GetSize(); - for (size_t i = 0; i < num_threads; i++) - { - ThreadSP thread_sp = threads.GetThreadAtIndex(i); - StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); - StopReason reason = eStopReasonInvalid; - if (stop_info_sp) - reason = stop_info_sp->GetStopReason(); - if (reason == eStopReasonBreakpoint - || reason == eStopReasonException) - { - if (log) - log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.", - thread_sp->GetProtocolID(), - stop_info_sp->GetDescription()); - stop_looks_like_crash = true; - break; - } - } - } + } + } - if (stop_looks_like_crash) - { - if (log) - log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill."); - m_destroy_tried_resuming = true; - - // If we are going to run again before killing, it would be good to suspend all the threads - // before resuming so they won't get into more trouble. Sadly, for the threads stopped with - // the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do - // have to run the risk of letting those threads proceed a bit. - - { - std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); - - size_t num_threads = threads.GetSize(); - for (size_t i = 0; i < num_threads; i++) - { - ThreadSP thread_sp = threads.GetThreadAtIndex(i); - StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); - StopReason reason = eStopReasonInvalid; - if (stop_info_sp) - reason = stop_info_sp->GetStopReason(); - if (reason != eStopReasonBreakpoint - && reason != eStopReasonException) - { - if (log) - log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.", - thread_sp->GetProtocolID()); - thread_sp->SetResumeState(eStateSuspended); - } - } - } - Resume (); - return Destroy(false); - } + if (stop_looks_like_crash) { + if (log) + log->PutCString("ProcessGDBRemote::DoDestroy() - Stopped at a " + "breakpoint, continue and then kill."); + m_destroy_tried_resuming = true; + + // If we are going to run again before killing, it would be good to + // suspend all the threads + // before resuming so they won't get into more trouble. Sadly, for + // the threads stopped with + // the breakpoint or exception, the exception doesn't get cleared if + // it is suspended, so we do + // have to run the risk of letting those threads proceed a bit. + + { + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); + + size_t num_threads = threads.GetSize(); + for (size_t i = 0; i < num_threads; i++) { + ThreadSP thread_sp = threads.GetThreadAtIndex(i); + StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); + StopReason reason = eStopReasonInvalid; + if (stop_info_sp) + reason = stop_info_sp->GetStopReason(); + if (reason != eStopReasonBreakpoint && + reason != eStopReasonException) { + if (log) + log->Printf("ProcessGDBRemote::DoDestroy() - Suspending " + "thread: 0x%4.4" PRIx64 " before running.", + thread_sp->GetProtocolID()); + thread_sp->SetResumeState(eStateSuspended); + } } + } + Resume(); + return Destroy(false); } + } } + } - // Interrupt if our inferior is running... - int exit_status = SIGABRT; - std::string exit_string; + // Interrupt if our inferior is running... + int exit_status = SIGABRT; + std::string exit_string; - if (m_gdb_comm.IsConnected()) - { - if (m_public_state.GetValue() != eStateAttaching) - { - StringExtractorGDBRemote response; - bool send_async = true; - GDBRemoteCommunication::ScopedTimeout (m_gdb_comm, 3); + if (m_gdb_comm.IsConnected()) { + if (m_public_state.GetValue() != eStateAttaching) { + StringExtractorGDBRemote response; + bool send_async = true; + GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, 3); - if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async) == GDBRemoteCommunication::PacketResult::Success) - { - char packet_cmd = response.GetChar(0); + if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, + send_async) == + GDBRemoteCommunication::PacketResult::Success) { + char packet_cmd = response.GetChar(0); - if (packet_cmd == 'W' || packet_cmd == 'X') - { + if (packet_cmd == 'W' || packet_cmd == 'X') { #if defined(__APPLE__) - // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off - // to debugserver, which becomes the parent process through "PT_ATTACH". Then when we go to kill - // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns - // with no error and the correct status. But amusingly enough that doesn't seem to actually reap - // the process, but instead it is left around as a Zombie. Probably the kernel is in the process of - // switching ownership back to lldb which was the original parent, and gets confused in the handoff. - // Anyway, so call waitpid here to finally reap it. - PlatformSP platform_sp(GetTarget().GetPlatform()); - if (platform_sp && platform_sp->IsHost()) - { - int status; - ::pid_t reap_pid; - reap_pid = waitpid (GetID(), &status, WNOHANG); - if (log) - log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status); - } -#endif - SetLastStopPacket (response); - ClearThreadIDList (); - exit_status = response.GetHexU8(); - } - else - { - if (log) - log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str()); - exit_string.assign("got unexpected response to k packet: "); - exit_string.append(response.GetStringRef()); - } - } - else - { - if (log) - log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet"); - exit_string.assign("failed to send the k packet"); - } - } - else - { + // For Native processes on Mac OS X, we launch through the Host + // Platform, then hand the process off + // to debugserver, which becomes the parent process through + // "PT_ATTACH". Then when we go to kill + // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we + // call waitpid which returns + // with no error and the correct status. But amusingly enough that + // doesn't seem to actually reap + // the process, but instead it is left around as a Zombie. Probably + // the kernel is in the process of + // switching ownership back to lldb which was the original parent, and + // gets confused in the handoff. + // Anyway, so call waitpid here to finally reap it. + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (platform_sp && platform_sp->IsHost()) { + int status; + ::pid_t reap_pid; + reap_pid = waitpid(GetID(), &status, WNOHANG); if (log) - log->Printf ("ProcessGDBRemote::DoDestroy - killed or interrupted while attaching"); - exit_string.assign ("killed or interrupted while attaching."); + log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status); + } +#endif + SetLastStopPacket(response); + ClearThreadIDList(); + exit_status = response.GetHexU8(); + } else { + if (log) + log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response " + "to k packet: %s", + response.GetStringRef().c_str()); + exit_string.assign("got unexpected response to k packet: "); + exit_string.append(response.GetStringRef()); } - } - else - { - // If we missed setting the exit status on the way out, do it here. - // NB set exit status can be called multiple times, the first one sets the status. - exit_string.assign("destroying when not connected to debugserver"); - } - - SetExitStatus(exit_status, exit_string.c_str()); - - StopAsyncThread (); - KillDebugserverProcess (); - return error; -} - -void -ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response) -{ - const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos; - if (did_exec) - { - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + } else { if (log) - log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec"); + log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet"); + exit_string.assign("failed to send the k packet"); + } + } else { + if (log) + log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while " + "attaching"); + exit_string.assign("killed or interrupted while attaching."); + } + } else { + // If we missed setting the exit status on the way out, do it here. + // NB set exit status can be called multiple times, the first one sets the + // status. + exit_string.assign("destroying when not connected to debugserver"); + } + + SetExitStatus(exit_status, exit_string.c_str()); + + StopAsyncThread(); + KillDebugserverProcess(); + return error; +} - m_thread_list_real.Clear(); - m_thread_list.Clear(); - BuildDynamicRegisterInfo (true); - m_gdb_comm.ResetDiscoverableSettings (did_exec); - } +void ProcessGDBRemote::SetLastStopPacket( + const StringExtractorGDBRemote &response) { + const bool did_exec = + response.GetStringRef().find(";reason:exec;") != std::string::npos; + if (did_exec) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec"); - // Scope the lock - { - // Lock the thread stack while we access it - std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); - - // We are are not using non-stop mode, there can only be one last stop - // reply packet, so clear the list. - if (GetTarget().GetNonStopModeEnabled() == false) - m_stop_packet_stack.clear(); - - // Add this stop packet to the stop packet stack - // This stack will get popped and examined when we switch to the - // Stopped state - m_stop_packet_stack.push_back(response); - } + m_thread_list_real.Clear(); + m_thread_list.Clear(); + BuildDynamicRegisterInfo(true); + m_gdb_comm.ResetDiscoverableSettings(did_exec); + } + + // Scope the lock + { + // Lock the thread stack while we access it + std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); + + // We are are not using non-stop mode, there can only be one last stop + // reply packet, so clear the list. + if (GetTarget().GetNonStopModeEnabled() == false) + m_stop_packet_stack.clear(); + + // Add this stop packet to the stop packet stack + // This stack will get popped and examined when we switch to the + // Stopped state + m_stop_packet_stack.push_back(response); + } } -void -ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) -{ - Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); +void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) { + Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); } //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ -bool -ProcessGDBRemote::IsAlive () -{ - return m_gdb_comm.IsConnected() && Process::IsAlive(); +bool ProcessGDBRemote::IsAlive() { + return m_gdb_comm.IsConnected() && Process::IsAlive(); } -addr_t -ProcessGDBRemote::GetImageInfoAddress() -{ - // request the link map address via the $qShlibInfoAddr packet - lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr(); +addr_t ProcessGDBRemote::GetImageInfoAddress() { + // request the link map address via the $qShlibInfoAddr packet + lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr(); - // the loaded module list can also provides a link map address - if (addr == LLDB_INVALID_ADDRESS) - { - LoadedModuleInfoList list; - if (GetLoadedModuleList (list).Success()) - addr = list.m_link_map; - } + // the loaded module list can also provides a link map address + if (addr == LLDB_INVALID_ADDRESS) { + LoadedModuleInfoList list; + if (GetLoadedModuleList(list).Success()) + addr = list.m_link_map; + } - return addr; + return addr; } -void -ProcessGDBRemote::WillPublicStop () -{ - // See if the GDB remote client supports the JSON threads info. - // If so, we gather stop info for all threads, expedited registers, - // expedited memory, runtime queue information (iOS and MacOSX only), - // and more. Expediting memory will help stack backtracing be much - // faster. Expediting registers will make sure we don't have to read - // the thread registers for GPRs. - m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); - - if (m_jthreadsinfo_sp) - { - // Now set the stop info for each thread and also expedite any registers - // and memory that was in the jThreadsInfo response. - StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); - if (thread_infos) - { - const size_t n = thread_infos->GetSize(); - for (size_t i=0; i<n; ++i) - { - StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); - if (thread_dict) - SetThreadStopInfo(thread_dict); - } - } - } +void ProcessGDBRemote::WillPublicStop() { + // See if the GDB remote client supports the JSON threads info. + // If so, we gather stop info for all threads, expedited registers, + // expedited memory, runtime queue information (iOS and MacOSX only), + // and more. Expediting memory will help stack backtracing be much + // faster. Expediting registers will make sure we don't have to read + // the thread registers for GPRs. + m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); + + if (m_jthreadsinfo_sp) { + // Now set the stop info for each thread and also expedite any registers + // and memory that was in the jThreadsInfo response. + StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); + if (thread_infos) { + const size_t n = thread_infos->GetSize(); + for (size_t i = 0; i < n; ++i) { + StructuredData::Dictionary *thread_dict = + thread_infos->GetItemAtIndex(i)->GetAsDictionary(); + if (thread_dict) + SetThreadStopInfo(thread_dict); + } + } + } } //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ -size_t -ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) -{ - GetMaxMemorySize (); - if (size > m_max_memory_size) - { - // Keep memory read sizes down to a sane limit. This function will be - // called multiple times in order to complete the task by - // lldb_private::Process so it is ok to do this. - size = m_max_memory_size; - } - - char packet[64]; - int packet_len; - bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); - packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, - binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size); - assert (packet_len + 1 < (int)sizeof(packet)); - StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success) - { - if (response.IsNormalResponse()) - { - error.Clear(); - if (binary_memory_read) - { - // The lower level GDBRemoteCommunication packet receive layer has already de-quoted any - // 0x7d character escaping that was present in the packet - - size_t data_received_size = response.GetBytesLeft(); - if (data_received_size > size) - { - // Don't write past the end of BUF if the remote debug server gave us too - // much data for some reason. - data_received_size = size; - } - memcpy (buf, response.GetStringRef().data(), data_received_size); - return data_received_size; - } - else - { - return response.GetHexBytes(llvm::MutableArrayRef<uint8_t>((uint8_t*)buf, size), '\xdd'); - } +size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, + Error &error) { + GetMaxMemorySize(); + if (size > m_max_memory_size) { + // Keep memory read sizes down to a sane limit. This function will be + // called multiple times in order to complete the task by + // lldb_private::Process so it is ok to do this. + size = m_max_memory_size; + } + + char packet[64]; + int packet_len; + bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); + packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, + binary_memory_read ? 'x' : 'm', (uint64_t)addr, + (uint64_t)size); + assert(packet_len + 1 < (int)sizeof(packet)); + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsNormalResponse()) { + error.Clear(); + if (binary_memory_read) { + // The lower level GDBRemoteCommunication packet receive layer has + // already de-quoted any + // 0x7d character escaping that was present in the packet + + size_t data_received_size = response.GetBytesLeft(); + if (data_received_size > size) { + // Don't write past the end of BUF if the remote debug server gave us + // too + // much data for some reason. + data_received_size = size; } - else if (response.IsErrorResponse()) - error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); - else if (response.IsUnsupportedResponse()) - error.SetErrorStringWithFormat("GDB server does not support reading memory"); - else - error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str()); - } + memcpy(buf, response.GetStringRef().data(), data_received_size); + return data_received_size; + } else { + return response.GetHexBytes( + llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd'); + } + } else if (response.IsErrorResponse()) + error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); + else if (response.IsUnsupportedResponse()) + error.SetErrorStringWithFormat( + "GDB server does not support reading memory"); else - { - error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); - } - return 0; + error.SetErrorStringWithFormat( + "unexpected response to GDB server memory read packet '%s': '%s'", + packet, response.GetStringRef().c_str()); + } else { + error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); + } + return 0; } -size_t -ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error) -{ - GetMaxMemorySize (); - if (size > m_max_memory_size) - { - // Keep memory read sizes down to a sane limit. This function will be - // called multiple times in order to complete the task by - // lldb_private::Process so it is ok to do this. - size = m_max_memory_size; - } - - StreamString packet; - packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); - packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder()); - StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success) - { - if (response.IsOKResponse()) - { - error.Clear(); - return size; - } - else if (response.IsErrorResponse()) - error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr); - else if (response.IsUnsupportedResponse()) - error.SetErrorStringWithFormat("GDB server does not support writing memory"); - else - error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str()); - } +size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, + size_t size, Error &error) { + GetMaxMemorySize(); + if (size > m_max_memory_size) { + // Keep memory read sizes down to a sane limit. This function will be + // called multiple times in order to complete the task by + // lldb_private::Process so it is ok to do this. + size = m_max_memory_size; + } + + StreamString packet; + packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); + packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), + endian::InlHostByteOrder()); + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse( + packet.GetData(), packet.GetSize(), response, true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsOKResponse()) { + error.Clear(); + return size; + } else if (response.IsErrorResponse()) + error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, + addr); + else if (response.IsUnsupportedResponse()) + error.SetErrorStringWithFormat( + "GDB server does not support writing memory"); else - { - error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str()); - } - return 0; + error.SetErrorStringWithFormat( + "unexpected response to GDB server memory write packet '%s': '%s'", + packet.GetString().c_str(), response.GetStringRef().c_str()); + } else { + error.SetErrorStringWithFormat("failed to send packet: '%s'", + packet.GetString().c_str()); + } + return 0; } -lldb::addr_t -ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) -{ - Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS)); - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) - { - allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); - if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) - return allocated_addr; - } - - if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) - { - // Call mmap() to create memory in the inferior.. - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) - m_addr_to_mmap_size[allocated_addr] = size; - else - { - allocated_addr = LLDB_INVALID_ADDRESS; - if (log) - log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__); - } - } - - if (allocated_addr == LLDB_INVALID_ADDRESS) - error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions)); - else - error.Clear(); - return allocated_addr; +lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, + uint32_t permissions, + Error &error) { + Log *log( + GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_EXPRESSIONS)); + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { + allocated_addr = m_gdb_comm.AllocateMemory(size, permissions); + if (allocated_addr != LLDB_INVALID_ADDRESS || + m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) + return allocated_addr; + } + + if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) { + // Call mmap() to create memory in the inferior.. + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) + m_addr_to_mmap_size[allocated_addr] = size; + else { + allocated_addr = LLDB_INVALID_ADDRESS; + if (log) + log->Printf("ProcessGDBRemote::%s no direct stub support for memory " + "allocation, and InferiorCallMmap also failed - is stub " + "missing register context save/restore capability?", + __FUNCTION__); + } + } + + if (allocated_addr == LLDB_INVALID_ADDRESS) + error.SetErrorStringWithFormat( + "unable to allocate %" PRIu64 " bytes of memory with permissions %s", + (uint64_t)size, GetPermissionsAsCString(permissions)); + else + error.Clear(); + return allocated_addr; } -Error -ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr, - MemoryRegionInfo ®ion_info) -{ +Error ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr, + MemoryRegionInfo ®ion_info) { - Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info)); - return error; + Error error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); + return error; } -Error -ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num) -{ +Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) { - Error error (m_gdb_comm.GetWatchpointSupportInfo (num)); - return error; + Error error(m_gdb_comm.GetWatchpointSupportInfo(num)); + return error; } -Error -ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after) -{ - Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after, GetTarget().GetArchitecture())); - return error; +Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) { + Error error(m_gdb_comm.GetWatchpointSupportInfo( + num, after, GetTarget().GetArchitecture())); + return error; } -Error -ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr) -{ - Error error; - LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); - - switch (supported) - { - case eLazyBoolCalculate: - // We should never be deallocating memory without allocating memory - // first so we should never get eLazyBoolCalculate - error.SetErrorString ("tried to deallocate memory without ever allocating memory"); - break; - - case eLazyBoolYes: - if (!m_gdb_comm.DeallocateMemory (addr)) - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); - break; - - case eLazyBoolNo: - // Call munmap() to deallocate memory in the inferior.. - { - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); - } - break; - } - - return error; +Error ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { + Error error; + LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); + + switch (supported) { + case eLazyBoolCalculate: + // We should never be deallocating memory without allocating memory + // first so we should never get eLazyBoolCalculate + error.SetErrorString( + "tried to deallocate memory without ever allocating memory"); + break; + + case eLazyBoolYes: + if (!m_gdb_comm.DeallocateMemory(addr)) + error.SetErrorStringWithFormat( + "unable to deallocate memory at 0x%" PRIx64, addr); + break; + + case eLazyBoolNo: + // Call munmap() to deallocate memory in the inferior.. + { + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); + if (pos != m_addr_to_mmap_size.end() && + InferiorCallMunmap(this, addr, pos->second)) + m_addr_to_mmap_size.erase(pos); + else + error.SetErrorStringWithFormat( + "unable to deallocate memory at 0x%" PRIx64, addr); + } + break; + } + + return error; } - //------------------------------------------------------------------ // Process STDIO //------------------------------------------------------------------ -size_t -ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error) -{ - if (m_stdio_communication.IsConnected()) - { - ConnectionStatus status; - m_stdio_communication.Write(src, src_len, status, NULL); - } - else if (m_stdin_forward) - { - m_gdb_comm.SendStdinNotification(src, src_len); - } - return 0; +size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, + Error &error) { + if (m_stdio_communication.IsConnected()) { + ConnectionStatus status; + m_stdio_communication.Write(src, src_len, status, NULL); + } else if (m_stdin_forward) { + m_gdb_comm.SendStdinNotification(src, src_len); + } + return 0; } -Error -ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) -{ - Error error; - assert(bp_site != NULL); - - // Get logging info - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); - user_id_t site_id = bp_site->GetID(); - - // Get the breakpoint address - const addr_t addr = bp_site->GetLoadAddress(); - - // Log that a breakpoint was requested - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr); - - // Breakpoint already exists and is enabled - if (bp_site->IsEnabled()) - { - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr); - return error; - } - - // Get the software breakpoint trap opcode size - const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); - - // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type - // is supported by the remote stub. These are set to true by default, and later set to false - // only after we receive an unimplemented response when sending a breakpoint packet. This means - // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will - // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which - // indicates if the user specifically asked for hardware breakpoints. If true then we will - // skip over software breakpoints. - if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired())) - { - // Try to send off a software breakpoint packet ($Z0) - uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size); - if (error_no == 0) - { - // The breakpoint was placed successfully - bp_site->SetEnabled(true); - bp_site->SetType(BreakpointSite::eExternal); - return error; - } +Error ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { + Error error; + assert(bp_site != NULL); - // SendGDBStoppointTypePacket() will return an error if it was unable to set this - // breakpoint. We need to differentiate between a error specific to placing this breakpoint - // or if we have learned that this breakpoint type is unsupported. To do this, we - // must test the support boolean for this breakpoint type to see if it now indicates that - // this breakpoint type is unsupported. If they are still supported then we should return - // with the error code. If they are now unsupported, then we would like to fall through - // and try another form of breakpoint. - if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) - { - if (error_no != UINT8_MAX) - error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno); - else - error.SetErrorString("error sending the breakpoint request"); - return error; - } - - // We reach here when software breakpoints have been found to be unsupported. For future - // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is - // known not to be supported. - if (log) - log->Printf("Software breakpoints are unsupported"); - - // So we will fall through and try a hardware breakpoint - } + // Get logging info + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); + user_id_t site_id = bp_site->GetID(); - // The process of setting a hardware breakpoint is much the same as above. We check the - // supported boolean for this breakpoint type, and if it is thought to be supported then we - // will try to set this breakpoint with a hardware breakpoint. - if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) - { - // Try to send off a hardware breakpoint packet ($Z1) - uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size); - if (error_no == 0) - { - // The breakpoint was placed successfully - bp_site->SetEnabled(true); - bp_site->SetType(BreakpointSite::eHardware); - return error; - } + // Get the breakpoint address + const addr_t addr = bp_site->GetLoadAddress(); - // Check if the error was something other then an unsupported breakpoint type - if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) - { - // Unable to set this hardware breakpoint - if (error_no != UINT8_MAX) - error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request " - "(hardware breakpoint resources might be exhausted or unavailable)", - error_no); - else - error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources " - "might be exhausted or unavailable)"); - return error; - } + // Log that a breakpoint was requested + if (log) + log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64, + site_id, (uint64_t)addr); - // We will reach here when the stub gives an unsupported response to a hardware breakpoint - if (log) - log->Printf("Hardware breakpoints are unsupported"); + // Breakpoint already exists and is enabled + if (bp_site->IsEnabled()) { + if (log) + log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", + site_id, (uint64_t)addr); + return error; + } + + // Get the software breakpoint trap opcode size + const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); + + // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this + // breakpoint type + // is supported by the remote stub. These are set to true by default, and + // later set to false + // only after we receive an unimplemented response when sending a breakpoint + // packet. This means + // initially that unless we were specifically instructed to use a hardware + // breakpoint, LLDB will + // attempt to set a software breakpoint. HardwareRequired() also queries a + // boolean variable which + // indicates if the user specifically asked for hardware breakpoints. If true + // then we will + // skip over software breakpoints. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && + (!bp_site->HardwareRequired())) { + // Try to send off a software breakpoint packet ($Z0) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( + eBreakpointSoftware, true, addr, bp_op_size); + if (error_no == 0) { + // The breakpoint was placed successfully + bp_site->SetEnabled(true); + bp_site->SetType(BreakpointSite::eExternal); + return error; + } + + // SendGDBStoppointTypePacket() will return an error if it was unable to set + // this + // breakpoint. We need to differentiate between a error specific to placing + // this breakpoint + // or if we have learned that this breakpoint type is unsupported. To do + // this, we + // must test the support boolean for this breakpoint type to see if it now + // indicates that + // this breakpoint type is unsupported. If they are still supported then we + // should return + // with the error code. If they are now unsupported, then we would like to + // fall through + // and try another form of breakpoint. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat( + "error: %d sending the breakpoint request", errno); + else + error.SetErrorString("error sending the breakpoint request"); + return error; + } + + // We reach here when software breakpoints have been found to be + // unsupported. For future + // calls to set a breakpoint, we will not attempt to set a breakpoint with a + // type that is + // known not to be supported. + if (log) + log->Printf("Software breakpoints are unsupported"); + + // So we will fall through and try a hardware breakpoint + } + + // The process of setting a hardware breakpoint is much the same as above. We + // check the + // supported boolean for this breakpoint type, and if it is thought to be + // supported then we + // will try to set this breakpoint with a hardware breakpoint. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { + // Try to send off a hardware breakpoint packet ($Z1) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( + eBreakpointHardware, true, addr, bp_op_size); + if (error_no == 0) { + // The breakpoint was placed successfully + bp_site->SetEnabled(true); + bp_site->SetType(BreakpointSite::eHardware); + return error; + } + + // Check if the error was something other then an unsupported breakpoint + // type + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { + // Unable to set this hardware breakpoint + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat( + "error: %d sending the hardware breakpoint request " + "(hardware breakpoint resources might be exhausted or unavailable)", + error_no); + else + error.SetErrorString("error sending the hardware breakpoint request " + "(hardware breakpoint resources " + "might be exhausted or unavailable)"); + return error; + } + + // We will reach here when the stub gives an unsupported response to a + // hardware breakpoint + if (log) + log->Printf("Hardware breakpoints are unsupported"); - // Finally we will falling through to a #trap style breakpoint - } + // Finally we will falling through to a #trap style breakpoint + } - // Don't fall through when hardware breakpoints were specifically requested - if (bp_site->HardwareRequired()) - { - error.SetErrorString("hardware breakpoints are not supported"); - return error; - } + // Don't fall through when hardware breakpoints were specifically requested + if (bp_site->HardwareRequired()) { + error.SetErrorString("hardware breakpoints are not supported"); + return error; + } - // As a last resort we want to place a manual breakpoint. An instruction - // is placed into the process memory using memory write packets. - return EnableSoftwareBreakpoint(bp_site); + // As a last resort we want to place a manual breakpoint. An instruction + // is placed into the process memory using memory write packets. + return EnableSoftwareBreakpoint(bp_site); } -Error -ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site) -{ - Error error; - assert (bp_site != NULL); - addr_t addr = bp_site->GetLoadAddress(); - user_id_t site_id = bp_site->GetID(); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); - if (log) - log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr); - - if (bp_site->IsEnabled()) - { - const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site); +Error ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { + Error error; + assert(bp_site != NULL); + addr_t addr = bp_site->GetLoadAddress(); + user_id_t site_id = bp_site->GetID(); + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); + if (log) + log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + site_id, (uint64_t)addr); + + if (bp_site->IsEnabled()) { + const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); - BreakpointSite::Type bp_type = bp_site->GetType(); - switch (bp_type) - { - case BreakpointSite::eSoftware: - error = DisableSoftwareBreakpoint (bp_site); - break; + BreakpointSite::Type bp_type = bp_site->GetType(); + switch (bp_type) { + case BreakpointSite::eSoftware: + error = DisableSoftwareBreakpoint(bp_site); + break; - case BreakpointSite::eHardware: - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size)) - error.SetErrorToGenericError(); - break; + case BreakpointSite::eHardware: + if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, + addr, bp_op_size)) + error.SetErrorToGenericError(); + break; - case BreakpointSite::eExternal: - { - GDBStoppointType stoppoint_type; - if (bp_site->IsHardware()) - stoppoint_type = eBreakpointHardware; - else - stoppoint_type = eBreakpointSoftware; + case BreakpointSite::eExternal: { + GDBStoppointType stoppoint_type; + if (bp_site->IsHardware()) + stoppoint_type = eBreakpointHardware; + else + stoppoint_type = eBreakpointSoftware; - if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size)) - error.SetErrorToGenericError(); - } - break; - } - if (error.Success()) - bp_site->SetEnabled(false); - } - else - { - if (log) - log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr); - return error; + if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, + bp_op_size)) + error.SetErrorToGenericError(); + } break; } - if (error.Success()) - error.SetErrorToGenericError(); + bp_site->SetEnabled(false); + } else { + if (log) + log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + site_id, (uint64_t)addr); return error; + } + + if (error.Success()) + error.SetErrorToGenericError(); + return error; } // Pre-requisite: wp != NULL. -static GDBStoppointType -GetGDBStoppointType (Watchpoint *wp) -{ - assert(wp); - bool watch_read = wp->WatchpointRead(); - bool watch_write = wp->WatchpointWrite(); - - // watch_read and watch_write cannot both be false. - assert(watch_read || watch_write); - if (watch_read && watch_write) - return eWatchpointReadWrite; - else if (watch_read) - return eWatchpointRead; - else // Must be watch_write, then. - return eWatchpointWrite; +static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) { + assert(wp); + bool watch_read = wp->WatchpointRead(); + bool watch_write = wp->WatchpointWrite(); + + // watch_read and watch_write cannot both be false. + assert(watch_read || watch_write); + if (watch_read && watch_write) + return eWatchpointReadWrite; + else if (watch_read) + return eWatchpointRead; + else // Must be watch_write, then. + return eWatchpointWrite; } -Error -ProcessGDBRemote::EnableWatchpoint (Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); - if (log) - log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID); - if (wp->IsEnabled()) - { - if (log) - log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr); - return error; - } - - GDBStoppointType type = GetGDBStoppointType(wp); - // Pass down an appropriate z/Z packet... - if (m_gdb_comm.SupportsGDBStoppointPacket (type)) - { - if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0) - { - wp->SetEnabled(true, notify); - return error; - } - else - error.SetErrorString("sending gdb watchpoint packet failed"); - } - else - error.SetErrorString("watchpoints not supported"); - } - else - { - error.SetErrorString("Watchpoint argument was NULL."); - } - if (error.Success()) - error.SetErrorToGenericError(); - return error; +Error ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + if (wp) { + user_id_t watchID = wp->GetID(); + addr_t addr = wp->GetLoadAddress(); + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); + if (log) + log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (wp->IsEnabled()) { + if (log) + log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); + return error; + } + + GDBStoppointType type = GetGDBStoppointType(wp); + // Pass down an appropriate z/Z packet... + if (m_gdb_comm.SupportsGDBStoppointPacket(type)) { + if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, + wp->GetByteSize()) == 0) { + wp->SetEnabled(true, notify); + return error; + } else + error.SetErrorString("sending gdb watchpoint packet failed"); + } else + error.SetErrorString("watchpoints not supported"); + } else { + error.SetErrorString("Watchpoint argument was NULL."); + } + if (error.Success()) + error.SetErrorToGenericError(); + return error; } -Error -ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); +Error ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { + Error error; + if (wp) { + user_id_t watchID = wp->GetID(); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); - addr_t addr = wp->GetLoadAddress(); + addr_t addr = wp->GetLoadAddress(); - if (log) - log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr); - - if (!wp->IsEnabled()) - { - if (log) - log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr); - // See also 'class WatchpointSentry' within StopInfo.cpp. - // This disabling attempt might come from the user-supplied actions, we'll route it in order for - // the watchpoint object to intelligently process this action. - wp->SetEnabled(false, notify); - return error; - } - - if (wp->IsHardware()) - { - GDBStoppointType type = GetGDBStoppointType(wp); - // Pass down an appropriate z/Z packet... - if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0) - { - wp->SetEnabled(false, notify); - return error; - } - else - error.SetErrorString("sending gdb watchpoint packet failed"); - } - // TODO: clear software watchpoints if we implement them - } - else - { - error.SetErrorString("Watchpoint argument was NULL."); - } - if (error.Success()) - error.SetErrorToGenericError(); - return error; + if (log) + log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + watchID, (uint64_t)addr); + + if (!wp->IsEnabled()) { + if (log) + log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + watchID, (uint64_t)addr); + // See also 'class WatchpointSentry' within StopInfo.cpp. + // This disabling attempt might come from the user-supplied actions, we'll + // route it in order for + // the watchpoint object to intelligently process this action. + wp->SetEnabled(false, notify); + return error; + } + + if (wp->IsHardware()) { + GDBStoppointType type = GetGDBStoppointType(wp); + // Pass down an appropriate z/Z packet... + if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, + wp->GetByteSize()) == 0) { + wp->SetEnabled(false, notify); + return error; + } else + error.SetErrorString("sending gdb watchpoint packet failed"); + } + // TODO: clear software watchpoints if we implement them + } else { + error.SetErrorString("Watchpoint argument was NULL."); + } + if (error.Success()) + error.SetErrorToGenericError(); + return error; } -void -ProcessGDBRemote::Clear() -{ - m_flags = 0; - m_thread_list_real.Clear(); - m_thread_list.Clear(); +void ProcessGDBRemote::Clear() { + m_flags = 0; + m_thread_list_real.Clear(); + m_thread_list.Clear(); } -Error -ProcessGDBRemote::DoSignal (int signo) -{ - Error error; - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo); +Error ProcessGDBRemote::DoSignal(int signo) { + Error error; + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo); - if (!m_gdb_comm.SendAsyncSignal (signo)) - error.SetErrorStringWithFormat("failed to send signal %i", signo); - return error; + if (!m_gdb_comm.SendAsyncSignal(signo)) + error.SetErrorStringWithFormat("failed to send signal %i", signo); + return error; } -Error -ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info) -{ - // Make sure we aren't already connected? - if (m_gdb_comm.IsConnected()) - return Error(); - - PlatformSP platform_sp (GetTarget ().GetPlatform ()); - if (platform_sp && !platform_sp->IsHost ()) - return Error("Lost debug server connection"); +Error ProcessGDBRemote::EstablishConnectionIfNeeded( + const ProcessInfo &process_info) { + // Make sure we aren't already connected? + if (m_gdb_comm.IsConnected()) + return Error(); - auto error = LaunchAndConnectToDebugserver (process_info); - if (error.Fail()) - { - const char *error_string = error.AsCString(); - if (error_string == nullptr) - error_string = "unable to launch " DEBUGSERVER_BASENAME; - } - return error; + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (platform_sp && !platform_sp->IsHost()) + return Error("Lost debug server connection"); + + auto error = LaunchAndConnectToDebugserver(process_info); + if (error.Fail()) { + const char *error_string = error.AsCString(); + if (error_string == nullptr) + error_string = "unable to launch " DEBUGSERVER_BASENAME; + } + return error; } -#if defined (__APPLE__) +#if defined(__APPLE__) #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 #endif #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION -static bool SetCloexecFlag(int fd) -{ -#if defined(FD_CLOEXEC) - int flags = ::fcntl(fd, F_GETFD); - if (flags == -1) - return false; - return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); -#else +static bool SetCloexecFlag(int fd) { +#if defined(FD_CLOEXEC) + int flags = ::fcntl(fd, F_GETFD); + if (flags == -1) return false; + return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); +#else + return false; #endif } #endif -Error -ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info) -{ - using namespace std::placeholders; // For _1, _2, etc. +Error ProcessGDBRemote::LaunchAndConnectToDebugserver( + const ProcessInfo &process_info) { + using namespace std::placeholders; // For _1, _2, etc. - Error error; - if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) - { - // If we locate debugserver, keep that located version around - static FileSpec g_debugserver_file_spec; - - ProcessLaunchInfo debugserver_launch_info; - // Make debugserver run in its own session so signals generated by - // special terminal key sequences (^C) don't affect debugserver. - debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); + Error error; + if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { + // If we locate debugserver, keep that located version around + static FileSpec g_debugserver_file_spec; - const std::weak_ptr<ProcessGDBRemote> this_wp = std::static_pointer_cast<ProcessGDBRemote>(shared_from_this()); - debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), - false); - debugserver_launch_info.SetUserID(process_info.GetUserID()); + ProcessLaunchInfo debugserver_launch_info; + // Make debugserver run in its own session so signals generated by + // special terminal key sequences (^C) don't affect debugserver. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); + const std::weak_ptr<ProcessGDBRemote> this_wp = + std::static_pointer_cast<ProcessGDBRemote>(shared_from_this()); + debugserver_launch_info.SetMonitorProcessCallback( + std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false); + debugserver_launch_info.SetUserID(process_info.GetUserID()); - int communication_fd = -1; + int communication_fd = -1; #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION - // Auto close the sockets we might open up unless everything goes OK. This - // helps us not leak file descriptors when things go wrong. - lldb_utility::CleanUp <int, int> our_socket(-1, -1, close); - lldb_utility::CleanUp <int, int> gdb_socket(-1, -1, close); + // Auto close the sockets we might open up unless everything goes OK. This + // helps us not leak file descriptors when things go wrong. + lldb_utility::CleanUp<int, int> our_socket(-1, -1, close); + lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close); - // Use a socketpair on Apple for now until other platforms can verify it - // works and is fast enough - { - int sockets[2]; /* the pair of socket descriptors */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) - { - error.SetErrorToErrno(); - return error; - } + // Use a socketpair on Apple for now until other platforms can verify it + // works and is fast enough + { + int sockets[2]; /* the pair of socket descriptors */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { + error.SetErrorToErrno(); + return error; + } - our_socket.set(sockets[0]); - gdb_socket.set(sockets[1]); - } + our_socket.set(sockets[0]); + gdb_socket.set(sockets[1]); + } - // Don't let any child processes inherit our communication socket - SetCloexecFlag(our_socket.get()); - communication_fd = gdb_socket.get(); + // Don't let any child processes inherit our communication socket + SetCloexecFlag(our_socket.get()); + communication_fd = gdb_socket.get(); #endif - error = m_gdb_comm.StartDebugserverProcess(nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, nullptr, nullptr, communication_fd); + error = m_gdb_comm.StartDebugserverProcess( + nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, + nullptr, nullptr, communication_fd); - if (error.Success ()) - m_debugserver_pid = debugserver_launch_info.GetProcessID(); - else - m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + if (error.Success()) + m_debugserver_pid = debugserver_launch_info.GetProcessID(); + else + m_debugserver_pid = LLDB_INVALID_PROCESS_ID; - if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) - { + if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION - // Our process spawned correctly, we can now set our connection to use our - // end of the socket pair - m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket.release(), true)); + // Our process spawned correctly, we can now set our connection to use our + // end of the socket pair + m_gdb_comm.SetConnection( + new ConnectionFileDescriptor(our_socket.release(), true)); #endif - StartAsyncThread (); - } - - if (error.Fail()) - { - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); + StartAsyncThread(); + } - if (log) - log->Printf("failed to start debugserver process: %s", error.AsCString()); - return error; - } + if (error.Fail()) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (m_gdb_comm.IsConnected()) - { - // Finish the connection process by doing the handshake without connecting (send NULL URL) - ConnectToDebugserver(NULL); - } - else - { - error.SetErrorString("connection failed"); - } + if (log) + log->Printf("failed to start debugserver process: %s", + error.AsCString()); + return error; + } + if (m_gdb_comm.IsConnected()) { + // Finish the connection process by doing the handshake without connecting + // (send NULL URL) + ConnectToDebugserver(NULL); + } else { + error.SetErrorString("connection failed"); } - return error; + } + return error; } -bool -ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid, - bool exited, // True if the process did exit - int signo, // Zero for no signal - int exit_status // Exit value of process if signal is zero - ) -{ - // "debugserver_pid" argument passed in is the process ID for - // debugserver that we are tracking... - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - const bool handled = true; - - if (log) - log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__, - debugserver_pid, signo, signo, exit_status); - - std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); - if (log) - log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast<void *>(process_sp.get())); - if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) - return handled; - - // Sleep for a half a second to make sure our inferior process has - // time to set its exit status before we set it incorrectly when - // both the debugserver and the inferior process shut down. - usleep(500000); - // If our process hasn't yet exited, debugserver might have died. - // If the process did exit, then we are reaping it. - const StateType state = process_sp->GetState(); - - if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached) - { - char error_str[1024]; - if (signo) - { - const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); - if (signal_cstr) - ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); - else - ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); - } - else - { - ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", - exit_status); - } +bool ProcessGDBRemote::MonitorDebugserverProcess( + std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid, + bool exited, // True if the process did exit + int signo, // Zero for no signal + int exit_status // Exit value of process if signal is zero + ) { + // "debugserver_pid" argument passed in is the process ID for + // debugserver that we are tracking... + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + const bool handled = true; + + if (log) + log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 + ", signo=%i (0x%x), exit_status=%i)", + __FUNCTION__, debugserver_pid, signo, signo, exit_status); + + std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); + if (log) + log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, + static_cast<void *>(process_sp.get())); + if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) + return handled; - process_sp->SetExitStatus(-1, error_str); + // Sleep for a half a second to make sure our inferior process has + // time to set its exit status before we set it incorrectly when + // both the debugserver and the inferior process shut down. + usleep(500000); + // If our process hasn't yet exited, debugserver might have died. + // If the process did exit, then we are reaping it. + const StateType state = process_sp->GetState(); + + if (state != eStateInvalid && state != eStateUnloaded && + state != eStateExited && state != eStateDetached) { + char error_str[1024]; + if (signo) { + const char *signal_cstr = + process_sp->GetUnixSignals()->GetSignalAsCString(signo); + if (signal_cstr) + ::snprintf(error_str, sizeof(error_str), + DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); + else + ::snprintf(error_str, sizeof(error_str), + DEBUGSERVER_BASENAME " died with signal %i", signo); + } else { + ::snprintf(error_str, sizeof(error_str), + DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", + exit_status); } - // Debugserver has exited we need to let our ProcessGDBRemote - // know that it no longer has a debugserver instance - process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; - return handled; + + process_sp->SetExitStatus(-1, error_str); + } + // Debugserver has exited we need to let our ProcessGDBRemote + // know that it no longer has a debugserver instance + process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + return handled; } -void -ProcessGDBRemote::KillDebugserverProcess () -{ - m_gdb_comm.Disconnect(); - if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) - { - Host::Kill (m_debugserver_pid, SIGINT); - m_debugserver_pid = LLDB_INVALID_PROCESS_ID; - } +void ProcessGDBRemote::KillDebugserverProcess() { + m_gdb_comm.Disconnect(); + if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { + Host::Kill(m_debugserver_pid, SIGINT); + m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + } } -void -ProcessGDBRemote::Initialize() -{ - static std::once_flag g_once_flag; +void ProcessGDBRemote::Initialize() { + static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin (GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance, - DebuggerInitialize); - }); + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + DebuggerInitialize); + }); } -void -ProcessGDBRemote::DebuggerInitialize (Debugger &debugger) -{ - if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName())) - { - const bool is_global_setting = true; - PluginManager::CreateSettingForProcessPlugin (debugger, - GetGlobalPluginProperties()->GetValueProperties(), - ConstString ("Properties for the gdb-remote process plug-in."), - is_global_setting); - } +void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForProcessPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForProcessPlugin( + debugger, GetGlobalPluginProperties()->GetValueProperties(), + ConstString("Properties for the gdb-remote process plug-in."), + is_global_setting); + } } -bool -ProcessGDBRemote::StartAsyncThread () -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); +bool ProcessGDBRemote::StartAsyncThread() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); + if (log) + log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); - std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); - if (!m_async_thread.IsJoinable()) - { - // Create a thread that watches our internal state and controls which - // events make it to clients (into the DCProcess event queue). + std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); + if (!m_async_thread.IsJoinable()) { + // Create a thread that watches our internal state and controls which + // events make it to clients (into the DCProcess event queue). - m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL); - } - else if (log) - log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__); + m_async_thread = + ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", + ProcessGDBRemote::AsyncThread, this, NULL); + } else if (log) + log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " + "already running.", + __FUNCTION__); - return m_async_thread.IsJoinable(); + return m_async_thread.IsJoinable(); } -void -ProcessGDBRemote::StopAsyncThread () -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); +void ProcessGDBRemote::StopAsyncThread() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); + if (log) + log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); - std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); - if (m_async_thread.IsJoinable()) - { - m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); + std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); + if (m_async_thread.IsJoinable()) { + m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); - // This will shut down the async thread. - m_gdb_comm.Disconnect(); // Disconnect from the debug server. + // This will shut down the async thread. + m_gdb_comm.Disconnect(); // Disconnect from the debug server. - // Stop the stdio thread - m_async_thread.Join(nullptr); - m_async_thread.Reset(); - } - else if (log) - log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); + // Stop the stdio thread + m_async_thread.Join(nullptr); + m_async_thread.Reset(); + } else if (log) + log->Printf( + "ProcessGDBRemote::%s () - Called when Async thread was not running.", + __FUNCTION__); } -bool -ProcessGDBRemote::HandleNotifyPacket (StringExtractorGDBRemote &packet) -{ - // get the packet at a string - const std::string &pkt = packet.GetStringRef(); - // skip %stop: - StringExtractorGDBRemote stop_info(pkt.c_str() + 5); - - // pass as a thread stop info packet - SetLastStopPacket(stop_info); - - // check for more stop reasons - HandleStopReplySequence(); - - // if the process is stopped then we need to fake a resume - // so that we can stop properly with the new break. This - // is possible due to SetPrivateState() broadcasting the - // state change as a side effect. - if (GetPrivateState() == lldb::StateType::eStateStopped) - { - SetPrivateState(lldb::StateType::eStateRunning); - } +bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) { + // get the packet at a string + const std::string &pkt = packet.GetStringRef(); + // skip %stop: + StringExtractorGDBRemote stop_info(pkt.c_str() + 5); - // since we have some stopped packets we can halt the process - SetPrivateState(lldb::StateType::eStateStopped); + // pass as a thread stop info packet + SetLastStopPacket(stop_info); - return true; + // check for more stop reasons + HandleStopReplySequence(); + + // if the process is stopped then we need to fake a resume + // so that we can stop properly with the new break. This + // is possible due to SetPrivateState() broadcasting the + // state change as a side effect. + if (GetPrivateState() == lldb::StateType::eStateStopped) { + SetPrivateState(lldb::StateType::eStateRunning); + } + + // since we have some stopped packets we can halt the process + SetPrivateState(lldb::StateType::eStateStopped); + + return true; } -thread_result_t -ProcessGDBRemote::AsyncThread (void *arg) -{ - ProcessGDBRemote *process = (ProcessGDBRemote*) arg; +thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { + ProcessGDBRemote *process = (ProcessGDBRemote *)arg; - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID()); + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread starting...", + __FUNCTION__, arg, process->GetID()); - EventSP event_sp; - bool done = false; - while (!done) - { + EventSP event_sp; + bool done = false; + while (!done) { + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp)...", + __FUNCTION__, arg, process->GetID()); + if (process->m_async_listener_sp->WaitForEvent(std::chrono::microseconds(0), + event_sp)) { + const uint32_t event_type = event_sp->GetType(); + if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) { if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); - if (process->m_async_listener_sp->WaitForEvent(std::chrono::microseconds(0), event_sp)) - { - const uint32_t event_type = event_sp->GetType(); - if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) - { - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); - - switch (event_type) - { - case eBroadcastBitAsyncContinue: - { - const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); - - if (continue_packet) - { - const char *continue_cstr = (const char *)continue_packet->GetBytes (); - const size_t continue_cstr_len = continue_packet->GetByteSize (); - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); - - if (::strstr (continue_cstr, "vAttach") == NULL) - process->SetPrivateState(eStateRunning); - StringExtractorGDBRemote response; - - // If in Non-Stop-Mode - if (process->GetTarget().GetNonStopModeEnabled()) - { - // send the vCont packet - if (!process->GetGDBRemote().SendvContPacket( - llvm::StringRef(continue_cstr, continue_cstr_len), response)) - { - // Something went wrong - done = true; - break; - } - } - // If in All-Stop-Mode - else - { - StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse( - *process, *process->GetUnixSignals(), - llvm::StringRef(continue_cstr, continue_cstr_len), response); - - // We need to immediately clear the thread ID list so we are sure to get a valid list of threads. - // The thread ID list might be contained within the "response", or the stop reply packet that - // caused the stop. So clear it now before we give the stop reply packet to the process - // using the process->SetLastStopPacket()... - process->ClearThreadIDList (); - - switch (stop_state) - { - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - process->SetLastStopPacket (response); - process->SetPrivateState (stop_state); - break; - - case eStateExited: - { - process->SetLastStopPacket (response); - process->ClearThreadIDList(); - response.SetFilePos(1); - - int exit_status = response.GetHexU8(); - std::string desc_string; - if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') - { - llvm::StringRef desc_str; - llvm::StringRef desc_token; - while (response.GetNameColonValue(desc_token, desc_str)) - { - if (desc_token != "description") - continue; - StringExtractor extractor(desc_str); - extractor.GetHexByteString(desc_string); - } - } - process->SetExitStatus(exit_status, desc_string.c_str()); - done = true; - break; - } - case eStateInvalid: - { - // Check to see if we were trying to attach and if we got back - // the "E87" error code from debugserver -- this indicates that - // the process is not debuggable. Return a slightly more helpful - // error message about why the attach failed. - if (::strstr (continue_cstr, "vAttach") != NULL - && response.GetError() == 0x87) - { - process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection"); - } - // E01 code from vAttach means that the attach failed - if (::strstr (continue_cstr, "vAttach") != NULL - && response.GetError() == 0x1) - { - process->SetExitStatus(-1, "unable to attach"); - } - else - { - process->SetExitStatus(-1, "lost connection"); - } - break; - } - - default: - process->SetPrivateState (stop_state); - break; - } // switch(stop_state) - } // else // if in All-stop-mode - } // if (continue_packet) - } // case eBroadcastBitAysncContinue - break; - - case eBroadcastBitAsyncThreadShouldExit: - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); - done = true; - break; - - default: - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); - done = true; - break; - } + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") Got an event of type: %d...", + __FUNCTION__, arg, process->GetID(), event_type); + + switch (event_type) { + case eBroadcastBitAsyncContinue: { + const EventDataBytes *continue_packet = + EventDataBytes::GetEventDataFromEvent(event_sp.get()); + + if (continue_packet) { + const char *continue_cstr = + (const char *)continue_packet->GetBytes(); + const size_t continue_cstr_len = continue_packet->GetByteSize(); + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncContinue: %s", + __FUNCTION__, arg, process->GetID(), continue_cstr); + + if (::strstr(continue_cstr, "vAttach") == NULL) + process->SetPrivateState(eStateRunning); + StringExtractorGDBRemote response; + + // If in Non-Stop-Mode + if (process->GetTarget().GetNonStopModeEnabled()) { + // send the vCont packet + if (!process->GetGDBRemote().SendvContPacket( + llvm::StringRef(continue_cstr, continue_cstr_len), + response)) { + // Something went wrong + done = true; + break; + } } - else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) - { - switch (event_type) - { - case Communication::eBroadcastBitReadThreadDidExit: - process->SetExitStatus (-1, "lost connection"); - done = true; - break; - - case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: - { - lldb_private::Event *event = event_sp.get(); - const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); - StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes()); - // Hand this over to the process to handle - process->HandleNotifyPacket(notify); - break; - } - - default: - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); - done = true; - break; + // If in All-Stop-Mode + else { + StateType stop_state = + process->GetGDBRemote().SendContinuePacketAndWaitForResponse( + *process, *process->GetUnixSignals(), + llvm::StringRef(continue_cstr, continue_cstr_len), + response); + + // We need to immediately clear the thread ID list so we are sure + // to get a valid list of threads. + // The thread ID list might be contained within the "response", or + // the stop reply packet that + // caused the stop. So clear it now before we give the stop reply + // packet to the process + // using the process->SetLastStopPacket()... + process->ClearThreadIDList(); + + switch (stop_state) { + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + process->SetLastStopPacket(response); + process->SetPrivateState(stop_state); + break; + + case eStateExited: { + process->SetLastStopPacket(response); + process->ClearThreadIDList(); + response.SetFilePos(1); + + int exit_status = response.GetHexU8(); + std::string desc_string; + if (response.GetBytesLeft() > 0 && + response.GetChar('-') == ';') { + llvm::StringRef desc_str; + llvm::StringRef desc_token; + while (response.GetNameColonValue(desc_token, desc_str)) { + if (desc_token != "description") + continue; + StringExtractor extractor(desc_str); + extractor.GetHexByteString(desc_string); + } } - } + process->SetExitStatus(exit_status, desc_string.c_str()); + done = true; + break; + } + case eStateInvalid: { + // Check to see if we were trying to attach and if we got back + // the "E87" error code from debugserver -- this indicates that + // the process is not debuggable. Return a slightly more + // helpful + // error message about why the attach failed. + if (::strstr(continue_cstr, "vAttach") != NULL && + response.GetError() == 0x87) { + process->SetExitStatus(-1, "cannot attach to process due to " + "System Integrity Protection"); + } + // E01 code from vAttach means that the attach failed + if (::strstr(continue_cstr, "vAttach") != NULL && + response.GetError() == 0x1) { + process->SetExitStatus(-1, "unable to attach"); + } else { + process->SetExitStatus(-1, "lost connection"); + } + break; + } + + default: + process->SetPrivateState(stop_state); + break; + } // switch(stop_state) + } // else // if in All-stop-mode + } // if (continue_packet) + } // case eBroadcastBitAysncContinue + break; + + case eBroadcastBitAsyncThreadShouldExit: + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncThreadShouldExit...", + __FUNCTION__, arg, process->GetID()); + done = true; + break; + + default: + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); + done = true; + break; } - else - { - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); - done = true; + } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) { + switch (event_type) { + case Communication::eBroadcastBitReadThreadDidExit: + process->SetExitStatus(-1, "lost connection"); + done = true; + break; + + case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: { + lldb_private::Event *event = event_sp.get(); + const EventDataBytes *continue_packet = + EventDataBytes::GetEventDataFromEvent(event); + StringExtractorGDBRemote notify( + (const char *)continue_packet->GetBytes()); + // Hand this over to the process to handle + process->HandleNotifyPacket(notify); + break; + } + + default: + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); + done = true; + break; } + } + } else { + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp) => false", + __FUNCTION__, arg, process->GetID()); + done = true; } + } - if (log) - log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID()); + if (log) + log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread exiting...", + __FUNCTION__, arg, process->GetID()); - return NULL; + return NULL; } -//uint32_t -//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids) +// uint32_t +// ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList +// &matches, std::vector<lldb::pid_t> &pids) //{ -// // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver -// // process and ask it for the list of processes. But if we are local, we can let the Host do it. +// // If we are planning to launch the debugserver remotely, then we need to +// fire up a debugserver +// // process and ask it for the list of processes. But if we are local, we +// can let the Host do it. // if (m_local_debugserver) // { // return Host::ListProcessesMatchingName (name, matches, pids); @@ -4059,270 +3727,239 @@ ProcessGDBRemote::AsyncThread (void *arg) // //} // -bool -ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) -{ - // I don't think I have to do anything here, just make sure I notice the new thread when it starts to - // run so I can stop it if that's what I want to do. - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Hit New Thread Notification breakpoint."); - return false; +bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( + void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { + // I don't think I have to do anything here, just make sure I notice the new + // thread when it starts to + // run so I can stop it if that's what I want to do. + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + log->Printf("Hit New Thread Notification breakpoint."); + return false; } - -bool -ProcessGDBRemote::StartNoticingNewThreads() -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (m_thread_create_bp_sp) - { +bool ProcessGDBRemote::StartNoticingNewThreads() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (m_thread_create_bp_sp) { + if (log && log->GetVerbose()) + log->Printf("Enabled noticing new thread breakpoint."); + m_thread_create_bp_sp->SetEnabled(true); + } else { + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (platform_sp) { + m_thread_create_bp_sp = + platform_sp->SetThreadCreationBreakpoint(GetTarget()); + if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) - log->Printf("Enabled noticing new thread breakpoint."); - m_thread_create_bp_sp->SetEnabled(true); - } - else - { - PlatformSP platform_sp (GetTarget().GetPlatform()); - if (platform_sp) - { - m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget()); - if (m_thread_create_bp_sp) - { - if (log && log->GetVerbose()) - log->Printf("Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID()); - m_thread_create_bp_sp->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); - } - else - { - if (log) - log->Printf("Failed to create new thread notification breakpoint."); - } - } + log->Printf( + "Successfully created new thread notification breakpoint %i", + m_thread_create_bp_sp->GetID()); + m_thread_create_bp_sp->SetCallback( + ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); + } else { + if (log) + log->Printf("Failed to create new thread notification breakpoint."); + } } - return m_thread_create_bp_sp.get() != NULL; + } + return m_thread_create_bp_sp.get() != NULL; } -bool -ProcessGDBRemote::StopNoticingNewThreads() -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log && log->GetVerbose()) - log->Printf ("Disabling new thread notification breakpoint."); +bool ProcessGDBRemote::StopNoticingNewThreads() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log && log->GetVerbose()) + log->Printf("Disabling new thread notification breakpoint."); - if (m_thread_create_bp_sp) - m_thread_create_bp_sp->SetEnabled(false); + if (m_thread_create_bp_sp) + m_thread_create_bp_sp->SetEnabled(false); - return true; + return true; } -DynamicLoader * -ProcessGDBRemote::GetDynamicLoader () -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL)); - return m_dyld_ap.get(); +DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL)); + return m_dyld_ap.get(); } -Error -ProcessGDBRemote::SendEventData(const char *data) -{ - int return_value; - bool was_supported; +Error ProcessGDBRemote::SendEventData(const char *data) { + int return_value; + bool was_supported; - Error error; + Error error; - return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported); - if (return_value != 0) - { - if (!was_supported) - error.SetErrorString("Sending events is not supported for this process."); - else - error.SetErrorStringWithFormat("Error sending event data: %d.", return_value); - } - return error; + return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported); + if (return_value != 0) { + if (!was_supported) + error.SetErrorString("Sending events is not supported for this process."); + else + error.SetErrorStringWithFormat("Error sending event data: %d.", + return_value); + } + return error; } -const DataBufferSP -ProcessGDBRemote::GetAuxvData() -{ - DataBufferSP buf; - if (m_gdb_comm.GetQXferAuxvReadSupported()) - { - std::string response_string; - if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success) - buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length())); - } - return buf; +const DataBufferSP ProcessGDBRemote::GetAuxvData() { + DataBufferSP buf; + if (m_gdb_comm.GetQXferAuxvReadSupported()) { + std::string response_string; + if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", + response_string) == + GDBRemoteCommunication::PacketResult::Success) + buf.reset(new DataBufferHeap(response_string.c_str(), + response_string.length())); + } + return buf; } StructuredData::ObjectSP -ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid) -{ - StructuredData::ObjectSP object_sp; +ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { + StructuredData::ObjectSP object_sp; - if (m_gdb_comm.GetThreadExtendedInfoSupported()) - { - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - SystemRuntime *runtime = GetSystemRuntime(); - if (runtime) - { - runtime->AddThreadExtendedInfoPacketHints (args_dict); - } - args_dict->GetAsDictionary()->AddIntegerItem ("thread", tid); + if (m_gdb_comm.GetThreadExtendedInfoSupported()) { + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + SystemRuntime *runtime = GetSystemRuntime(); + if (runtime) { + runtime->AddThreadExtendedInfoPacketHints(args_dict); + } + args_dict->GetAsDictionary()->AddIntegerItem("thread", tid); - StreamString packet; - packet << "jThreadExtendedInfo:"; - args_dict->Dump (packet, false); + StreamString packet; + packet << "jThreadExtendedInfo:"; + args_dict->Dump(packet, false); - // FIXME the final character of a JSON dictionary, '}', is the escape - // character in gdb-remote binary mode. lldb currently doesn't escape - // these characters in its packet output -- so we add the quoted version - // of the } character here manually in case we talk to a debugserver which - // un-escapes the characters at packet read time. - packet << (char) (0x7d ^ 0x20); + // FIXME the final character of a JSON dictionary, '}', is the escape + // character in gdb-remote binary mode. lldb currently doesn't escape + // these characters in its packet output -- so we add the quoted version + // of the } character here manually in case we talk to a debugserver which + // un-escapes the characters at packet read time. + packet << (char)(0x7d ^ 0x20); - StringExtractorGDBRemote response; - response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) - { - StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); - if (response_type == StringExtractorGDBRemote::eResponse) - { - if (!response.Empty()) - { - object_sp = StructuredData::ParseJSON (response.GetStringRef()); - } - } + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (m_gdb_comm.SendPacketAndWaitForResponse( + packet.GetData(), packet.GetSize(), response, false) == + GDBRemoteCommunication::PacketResult::Success) { + StringExtractorGDBRemote::ResponseType response_type = + response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + if (!response.Empty()) { + object_sp = StructuredData::ParseJSON(response.GetStringRef()); } + } } - return object_sp; + } + return object_sp; } -StructuredData::ObjectSP -ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) -{ +StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( + lldb::addr_t image_list_address, lldb::addr_t image_count) { - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address); - args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count); + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + args_dict->GetAsDictionary()->AddIntegerItem("image_list_address", + image_list_address); + args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count); - return GetLoadedDynamicLibrariesInfos_sender (args_dict); + return GetLoadedDynamicLibrariesInfos_sender(args_dict); } -StructuredData::ObjectSP -ProcessGDBRemote::GetLoadedDynamicLibrariesInfos () -{ - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); +StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() { + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - args_dict->GetAsDictionary()->AddBooleanItem ("fetch_all_solibs", true); + args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true); - return GetLoadedDynamicLibrariesInfos_sender (args_dict); + return GetLoadedDynamicLibrariesInfos_sender(args_dict); } -StructuredData::ObjectSP -ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses) -{ - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - StructuredData::ArraySP addresses(new StructuredData::Array); +StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( + const std::vector<lldb::addr_t> &load_addresses) { + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + StructuredData::ArraySP addresses(new StructuredData::Array); - for (auto addr : load_addresses) - { - StructuredData::ObjectSP addr_sp (new StructuredData::Integer (addr)); - addresses->AddItem (addr_sp); - } + for (auto addr : load_addresses) { + StructuredData::ObjectSP addr_sp(new StructuredData::Integer(addr)); + addresses->AddItem(addr_sp); + } - args_dict->GetAsDictionary()->AddItem ("solib_addresses", addresses); + args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses); - return GetLoadedDynamicLibrariesInfos_sender (args_dict); + return GetLoadedDynamicLibrariesInfos_sender(args_dict); } StructuredData::ObjectSP -ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args_dict) -{ - StructuredData::ObjectSP object_sp; +ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( + StructuredData::ObjectSP args_dict) { + StructuredData::ObjectSP object_sp; - if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) - { - // Scope for the scoped timeout object - GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10); + if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) { + // Scope for the scoped timeout object + GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10); - StreamString packet; - packet << "jGetLoadedDynamicLibrariesInfos:"; - args_dict->Dump (packet, false); + StreamString packet; + packet << "jGetLoadedDynamicLibrariesInfos:"; + args_dict->Dump(packet, false); - // FIXME the final character of a JSON dictionary, '}', is the escape - // character in gdb-remote binary mode. lldb currently doesn't escape - // these characters in its packet output -- so we add the quoted version - // of the } character here manually in case we talk to a debugserver which - // un-escapes the characters at packet read time. - packet << (char) (0x7d ^ 0x20); + // FIXME the final character of a JSON dictionary, '}', is the escape + // character in gdb-remote binary mode. lldb currently doesn't escape + // these characters in its packet output -- so we add the quoted version + // of the } character here manually in case we talk to a debugserver which + // un-escapes the characters at packet read time. + packet << (char)(0x7d ^ 0x20); - StringExtractorGDBRemote response; - response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) - { - StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); - if (response_type == StringExtractorGDBRemote::eResponse) - { - if (!response.Empty()) - { - object_sp = StructuredData::ParseJSON (response.GetStringRef()); - } - } + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (m_gdb_comm.SendPacketAndWaitForResponse( + packet.GetData(), packet.GetSize(), response, false) == + GDBRemoteCommunication::PacketResult::Success) { + StringExtractorGDBRemote::ResponseType response_type = + response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + if (!response.Empty()) { + object_sp = StructuredData::ParseJSON(response.GetStringRef()); } + } } - return object_sp; + } + return object_sp; } +StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { + StructuredData::ObjectSP object_sp; + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + if (m_gdb_comm.GetSharedCacheInfoSupported()) { + StreamString packet; + packet << "jGetSharedCacheInfo:"; + args_dict->Dump(packet, false); + // FIXME the final character of a JSON dictionary, '}', is the escape + // character in gdb-remote binary mode. lldb currently doesn't escape + // these characters in its packet output -- so we add the quoted version + // of the } character here manually in case we talk to a debugserver which + // un-escapes the characters at packet read time. + packet << (char)(0x7d ^ 0x20); -StructuredData::ObjectSP -ProcessGDBRemote::GetSharedCacheInfo () -{ - StructuredData::ObjectSP object_sp; - StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - - if (m_gdb_comm.GetSharedCacheInfoSupported()) - { - StreamString packet; - packet << "jGetSharedCacheInfo:"; - args_dict->Dump (packet, false); - - // FIXME the final character of a JSON dictionary, '}', is the escape - // character in gdb-remote binary mode. lldb currently doesn't escape - // these characters in its packet output -- so we add the quoted version - // of the } character here manually in case we talk to a debugserver which - // un-escapes the characters at packet read time. - packet << (char) (0x7d ^ 0x20); - - StringExtractorGDBRemote response; - response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) - { - StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); - if (response_type == StringExtractorGDBRemote::eResponse) - { - if (!response.Empty()) - { - object_sp = StructuredData::ParseJSON (response.GetStringRef()); - } - } + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (m_gdb_comm.SendPacketAndWaitForResponse( + packet.GetData(), packet.GetSize(), response, false) == + GDBRemoteCommunication::PacketResult::Success) { + StringExtractorGDBRemote::ResponseType response_type = + response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + if (!response.Empty()) { + object_sp = StructuredData::ParseJSON(response.GetStringRef()); } + } } - return object_sp; + } + return object_sp; } -Error -ProcessGDBRemote::ConfigureStructuredData(const ConstString &type_name, - const StructuredData::ObjectSP - &config_sp) -{ - return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); +Error ProcessGDBRemote::ConfigureStructuredData( + const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { + return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); } // Establish the largest memory read/write payloads we should use. @@ -4334,100 +3971,82 @@ ProcessGDBRemote::ConfigureStructuredData(const ConstString &type_name, // If the remote stub doesn't advertise a max packet size, use a // conservative default. -void -ProcessGDBRemote::GetMaxMemorySize() -{ - const uint64_t reasonable_largeish_default = 128 * 1024; - const uint64_t conservative_default = 512; +void ProcessGDBRemote::GetMaxMemorySize() { + const uint64_t reasonable_largeish_default = 128 * 1024; + const uint64_t conservative_default = 512; - if (m_max_memory_size == 0) - { - uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize(); - if (stub_max_size != UINT64_MAX && stub_max_size != 0) - { - // Save the stub's claimed maximum packet size - m_remote_stub_max_memory_size = stub_max_size; + if (m_max_memory_size == 0) { + uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize(); + if (stub_max_size != UINT64_MAX && stub_max_size != 0) { + // Save the stub's claimed maximum packet size + m_remote_stub_max_memory_size = stub_max_size; - // Even if the stub says it can support ginormous packets, - // don't exceed our reasonable largeish default packet size. - if (stub_max_size > reasonable_largeish_default) - { - stub_max_size = reasonable_largeish_default; - } + // Even if the stub says it can support ginormous packets, + // don't exceed our reasonable largeish default packet size. + if (stub_max_size > reasonable_largeish_default) { + stub_max_size = reasonable_largeish_default; + } - m_max_memory_size = stub_max_size; - } - else - { - m_max_memory_size = conservative_default; - } + m_max_memory_size = stub_max_size; + } else { + m_max_memory_size = conservative_default; } + } } -void -ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max) -{ - if (user_specified_max != 0) - { - GetMaxMemorySize (); - - if (m_remote_stub_max_memory_size != 0) - { - if (m_remote_stub_max_memory_size < user_specified_max) - { - m_max_memory_size = m_remote_stub_max_memory_size; // user specified a packet size too big, go as big - // as the remote stub says we can go. - } - else - { - m_max_memory_size = user_specified_max; // user's packet size is good - } - } - else - { - m_max_memory_size = user_specified_max; // user's packet size is probably fine - } +void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize( + uint64_t user_specified_max) { + if (user_specified_max != 0) { + GetMaxMemorySize(); + + if (m_remote_stub_max_memory_size != 0) { + if (m_remote_stub_max_memory_size < user_specified_max) { + m_max_memory_size = m_remote_stub_max_memory_size; // user specified a + // packet size too + // big, go as big + // as the remote stub says we can go. + } else { + m_max_memory_size = user_specified_max; // user's packet size is good + } + } else { + m_max_memory_size = + user_specified_max; // user's packet size is probably fine } + } } -bool -ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec, - const ArchSpec& arch, - ModuleSpec &module_spec) -{ - Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); - - if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec)) - { - if (log) - log->Printf ("ProcessGDBRemote::%s - failed to get module info for %s:%s", - __FUNCTION__, module_file_spec.GetPath ().c_str (), - arch.GetTriple ().getTriple ().c_str ()); - return false; - } +bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, + const ArchSpec &arch, + ModuleSpec &module_spec) { + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); + if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { if (log) - { - StreamString stream; - module_spec.Dump (stream); - log->Printf ("ProcessGDBRemote::%s - got module info for (%s:%s) : %s", - __FUNCTION__, module_file_spec.GetPath ().c_str (), - arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ()); - } - - return true; + log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str()); + return false; + } + + if (log) { + StreamString stream; + module_spec.Dump(stream); + log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str(), + stream.GetString().c_str()); + } + + return true; } -bool -ProcessGDBRemote::GetHostOSVersion(uint32_t &major, - uint32_t &minor, - uint32_t &update) -{ - if (m_gdb_comm.GetOSVersion(major, minor, update)) - return true; - // We failed to get the host OS version, defer to the base - // implementation to correctly invalidate the arguments. - return Process::GetHostOSVersion(major, minor, update); +bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) { + if (m_gdb_comm.GetOSVersion(major, minor, update)) + return true; + // We failed to get the host OS version, defer to the base + // implementation to correctly invalidate the arguments. + return Process::GetHostOSVersion(major, minor, update); } namespace { @@ -4435,29 +4054,29 @@ namespace { typedef std::vector<std::string> stringVec; typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec; -struct RegisterSetInfo -{ - ConstString name; +struct RegisterSetInfo { + ConstString name; }; typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap; -struct GdbServerTargetInfo -{ - std::string arch; - std::string osabi; - stringVec includes; - RegisterSetMap reg_set_map; - XMLNode feature_node; +struct GdbServerTargetInfo { + std::string arch; + std::string osabi; + stringVec includes; + RegisterSetMap reg_set_map; + XMLNode feature_node; }; -bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t ®_offset) -{ - if (!feature_node) - return false; +bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, + GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, + uint32_t &cur_reg_num, uint32_t ®_offset) { + if (!feature_node) + return false; - feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool { + feature_node.ForEachChildElementWithName( + "reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, + &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; ConstString reg_name; @@ -4468,1076 +4087,1001 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot std::vector<uint8_t> dwarf_opcode_bytes; bool encoding_set = false; bool format_set = false; - RegisterInfo reg_info = { NULL, // Name - NULL, // Alt name - 0, // byte size - reg_offset, // offset - eEncodingUint, // encoding - eFormatHex, // format + RegisterInfo reg_info = { + NULL, // Name + NULL, // Alt name + 0, // byte size + reg_offset, // offset + eEncodingUint, // encoding + eFormatHex, // format { LLDB_INVALID_REGNUM, // eh_frame reg num LLDB_INVALID_REGNUM, // DWARF reg num LLDB_INVALID_REGNUM, // generic reg num - cur_reg_num, // process plugin reg num - cur_reg_num // native register number + cur_reg_num, // process plugin reg num + cur_reg_num // native register number }, NULL, NULL, - NULL, // Dwarf Expression opcode bytes pointer - 0 // Dwarf Expression opcode bytes length + NULL, // Dwarf Expression opcode bytes pointer + 0 // Dwarf Expression opcode bytes length }; - reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset, &dwarf_opcode_bytes](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { - if (name == "name") - { - reg_name.SetString(value); + reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, + ®_name, &alt_name, &set_name, &value_regs, + &invalidate_regs, &encoding_set, &format_set, + ®_info, &cur_reg_num, ®_offset, + &dwarf_opcode_bytes]( + const llvm::StringRef &name, + const llvm::StringRef &value) -> bool { + if (name == "name") { + reg_name.SetString(value); + } else if (name == "bitsize") { + reg_info.byte_size = + StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT; + } else if (name == "type") { + gdb_type = value.str(); + } else if (name == "group") { + gdb_group = value.str(); + } else if (name == "regnum") { + const uint32_t regnum = + StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); + if (regnum != LLDB_INVALID_REGNUM) { + reg_info.kinds[eRegisterKindProcessPlugin] = regnum; } - else if (name == "bitsize") - { - reg_info.byte_size = StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT; - } - else if (name == "type") - { - gdb_type = value.str(); - } - else if (name == "group") - { - gdb_group = value.str(); - } - else if (name == "regnum") - { - const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); - if (regnum != LLDB_INVALID_REGNUM) - { - reg_info.kinds[eRegisterKindProcessPlugin] = regnum; - } - } - else if (name == "offset") - { - reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); - } - else if (name == "altname") - { - alt_name.SetString(value); - } - else if (name == "encoding") - { - encoding_set = true; - reg_info.encoding = Args::StringToEncoding (value.data(), eEncodingUint); - } - else if (name == "format") - { - format_set = true; - Format format = eFormatInvalid; - if (Args::StringToFormat (value.data(), format, NULL).Success()) - reg_info.format = format; - else if (value == "vector-sint8") - reg_info.format = eFormatVectorOfSInt8; - else if (value == "vector-uint8") - reg_info.format = eFormatVectorOfUInt8; - else if (value == "vector-sint16") - reg_info.format = eFormatVectorOfSInt16; - else if (value == "vector-uint16") - reg_info.format = eFormatVectorOfUInt16; - else if (value == "vector-sint32") - reg_info.format = eFormatVectorOfSInt32; - else if (value == "vector-uint32") - reg_info.format = eFormatVectorOfUInt32; - else if (value == "vector-float32") - reg_info.format = eFormatVectorOfFloat32; - else if (value == "vector-uint128") - reg_info.format = eFormatVectorOfUInt128; - } - else if (name == "group_id") - { - const uint32_t set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); - RegisterSetMap::const_iterator pos = target_info.reg_set_map.find(set_id); - if (pos != target_info.reg_set_map.end()) - set_name = pos->second.name; - } - else if (name == "gcc_regnum" || name == "ehframe_regnum") - { - reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); - } - else if (name == "dwarf_regnum") - { - reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); - } - else if (name == "generic") - { - reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value.data()); - } - else if (name == "value_regnums") - { - SplitCommaSeparatedRegisterNumberString(value, value_regs, 0); - } - else if (name == "invalidate_regnums") - { - SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); - } - else if (name == "dynamic_size_dwarf_expr_bytes") - { - StringExtractor opcode_extractor; - std::string opcode_string = value.str (); - size_t dwarf_opcode_len = opcode_string.length () / 2; - assert (dwarf_opcode_len > 0); - - dwarf_opcode_bytes.resize (dwarf_opcode_len); - reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; - opcode_extractor.GetStringRef ().swap (opcode_string); - uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes); - assert (dwarf_opcode_len == ret_val); - - reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data (); - } - else - { - printf("unhandled attribute %s = %s\n", name.data(), value.data()); - } - return true; // Keep iterating through all attributes + } else if (name == "offset") { + reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); + } else if (name == "altname") { + alt_name.SetString(value); + } else if (name == "encoding") { + encoding_set = true; + reg_info.encoding = + Args::StringToEncoding(value.data(), eEncodingUint); + } else if (name == "format") { + format_set = true; + Format format = eFormatInvalid; + if (Args::StringToFormat(value.data(), format, NULL).Success()) + reg_info.format = format; + else if (value == "vector-sint8") + reg_info.format = eFormatVectorOfSInt8; + else if (value == "vector-uint8") + reg_info.format = eFormatVectorOfUInt8; + else if (value == "vector-sint16") + reg_info.format = eFormatVectorOfSInt16; + else if (value == "vector-uint16") + reg_info.format = eFormatVectorOfUInt16; + else if (value == "vector-sint32") + reg_info.format = eFormatVectorOfSInt32; + else if (value == "vector-uint32") + reg_info.format = eFormatVectorOfUInt32; + else if (value == "vector-float32") + reg_info.format = eFormatVectorOfFloat32; + else if (value == "vector-uint128") + reg_info.format = eFormatVectorOfUInt128; + } else if (name == "group_id") { + const uint32_t set_id = + StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); + RegisterSetMap::const_iterator pos = + target_info.reg_set_map.find(set_id); + if (pos != target_info.reg_set_map.end()) + set_name = pos->second.name; + } else if (name == "gcc_regnum" || name == "ehframe_regnum") { + reg_info.kinds[eRegisterKindEHFrame] = + StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); + } else if (name == "dwarf_regnum") { + reg_info.kinds[eRegisterKindDWARF] = + StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); + } else if (name == "generic") { + reg_info.kinds[eRegisterKindGeneric] = + Args::StringToGenericRegister(value.data()); + } else if (name == "value_regnums") { + SplitCommaSeparatedRegisterNumberString(value, value_regs, 0); + } else if (name == "invalidate_regnums") { + SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); + } else if (name == "dynamic_size_dwarf_expr_bytes") { + StringExtractor opcode_extractor; + std::string opcode_string = value.str(); + size_t dwarf_opcode_len = opcode_string.length() / 2; + assert(dwarf_opcode_len > 0); + + dwarf_opcode_bytes.resize(dwarf_opcode_len); + reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; + opcode_extractor.GetStringRef().swap(opcode_string); + uint32_t ret_val = + opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); + assert(dwarf_opcode_len == ret_val); + + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); + } else { + printf("unhandled attribute %s = %s\n", name.data(), value.data()); + } + return true; // Keep iterating through all attributes }); - if (!gdb_type.empty() && !(encoding_set || format_set)) - { - if (gdb_type.find("int") == 0) - { - reg_info.format = eFormatHex; - reg_info.encoding = eEncodingUint; - } - else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") - { - reg_info.format = eFormatAddressInfo; - reg_info.encoding = eEncodingUint; - } - else if (gdb_type == "i387_ext" || gdb_type == "float") - { - reg_info.format = eFormatFloat; - reg_info.encoding = eEncodingIEEE754; - } + if (!gdb_type.empty() && !(encoding_set || format_set)) { + if (gdb_type.find("int") == 0) { + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { + reg_info.format = eFormatAddressInfo; + reg_info.encoding = eEncodingUint; + } else if (gdb_type == "i387_ext" || gdb_type == "float") { + reg_info.format = eFormatFloat; + reg_info.encoding = eEncodingIEEE754; + } } - // Only update the register set name if we didn't get a "reg_set" attribute. + // Only update the register set name if we didn't get a "reg_set" + // attribute. // "set_name" will be empty if we didn't have a "reg_set" attribute. if (!set_name && !gdb_group.empty()) - set_name.SetCString(gdb_group.c_str()); + set_name.SetCString(gdb_group.c_str()); reg_info.byte_offset = reg_offset; - assert (reg_info.byte_size != 0); + assert(reg_info.byte_size != 0); reg_offset += reg_info.byte_size; - if (!value_regs.empty()) - { - value_regs.push_back(LLDB_INVALID_REGNUM); - reg_info.value_regs = value_regs.data(); + if (!value_regs.empty()) { + value_regs.push_back(LLDB_INVALID_REGNUM); + reg_info.value_regs = value_regs.data(); } - if (!invalidate_regs.empty()) - { - invalidate_regs.push_back(LLDB_INVALID_REGNUM); - reg_info.invalidate_regs = invalidate_regs.data(); + if (!invalidate_regs.empty()) { + invalidate_regs.push_back(LLDB_INVALID_REGNUM); + reg_info.invalidate_regs = invalidate_regs.data(); } ++cur_reg_num; - AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp); + AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp); dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name); return true; // Keep iterating through all "reg" elements - }); - return true; + }); + return true; } } // namespace {} - // query the target of gdb-remote for extended target information // return: 'true' on success // 'false' on failure -bool -ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use) -{ - // Make sure LLDB has an XML parser it can use first - if (!XMLDocument::XMLEnabled()) - return false; - - // redirect libxml2's error handler since the default prints to stdout - - GDBRemoteCommunicationClient & comm = m_gdb_comm; - - // check that we have extended feature read support - if ( !comm.GetQXferFeaturesReadSupported( ) ) - return false; - - // request the target xml file - std::string raw; - lldb_private::Error lldberr; - if (!comm.ReadExtFeature(ConstString("features"), - ConstString("target.xml"), - raw, - lldberr)) - { - return false; - } +bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { + // Make sure LLDB has an XML parser it can use first + if (!XMLDocument::XMLEnabled()) + return false; + // redirect libxml2's error handler since the default prints to stdout - XMLDocument xml_document; + GDBRemoteCommunicationClient &comm = m_gdb_comm; - if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) - { - GdbServerTargetInfo target_info; + // check that we have extended feature read support + if (!comm.GetQXferFeaturesReadSupported()) + return false; - XMLNode target_node = xml_document.GetRootElement("target"); - if (target_node) - { - XMLNode feature_node; - target_node.ForEachChildElement([&target_info, this, &feature_node](const XMLNode &node) -> bool - { - llvm::StringRef name = node.GetName(); - if (name == "architecture") - { - node.GetElementText(target_info.arch); - } - else if (name == "osabi") - { - node.GetElementText(target_info.osabi); - } - else if (name == "xi:include" || name == "include") - { - llvm::StringRef href = node.GetAttributeValue("href"); - if (!href.empty()) - target_info.includes.push_back(href.str()); - } - else if (name == "feature") - { - feature_node = node; - } - else if (name == "groups") - { - node.ForEachChildElementWithName("group", [&target_info](const XMLNode &node) -> bool { - uint32_t set_id = UINT32_MAX; - RegisterSetInfo set_info; - - node.ForEachAttribute([&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { - if (name == "id") - set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); - if (name == "name") - set_info.name = ConstString(value); - return true; // Keep iterating through all attributes - }); - - if (set_id != UINT32_MAX) - target_info.reg_set_map[set_id] = set_info; - return true; // Keep iterating through all "group" elements + // request the target xml file + std::string raw; + lldb_private::Error lldberr; + if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"), + raw, lldberr)) { + return false; + } + + XMLDocument xml_document; + + if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) { + GdbServerTargetInfo target_info; + + XMLNode target_node = xml_document.GetRootElement("target"); + if (target_node) { + XMLNode feature_node; + target_node.ForEachChildElement([&target_info, this, &feature_node]( + const XMLNode &node) -> bool { + llvm::StringRef name = node.GetName(); + if (name == "architecture") { + node.GetElementText(target_info.arch); + } else if (name == "osabi") { + node.GetElementText(target_info.osabi); + } else if (name == "xi:include" || name == "include") { + llvm::StringRef href = node.GetAttributeValue("href"); + if (!href.empty()) + target_info.includes.push_back(href.str()); + } else if (name == "feature") { + feature_node = node; + } else if (name == "groups") { + node.ForEachChildElementWithName( + "group", [&target_info](const XMLNode &node) -> bool { + uint32_t set_id = UINT32_MAX; + RegisterSetInfo set_info; + + node.ForEachAttribute( + [&set_id, &set_info](const llvm::StringRef &name, + const llvm::StringRef &value) -> bool { + if (name == "id") + set_id = StringConvert::ToUInt32(value.data(), + UINT32_MAX, 0); + if (name == "name") + set_info.name = ConstString(value); + return true; // Keep iterating through all attributes }); - } - return true; // Keep iterating through all children of the target_node - }); - - // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature - uint32_t cur_reg_num = 0; - uint32_t reg_offset = 0; - - // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't - // set the Target's architecture yet, so the ABI is also potentially incorrect. - ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use); - if (feature_node) - { - ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); - } - for (const auto &include : target_info.includes) - { - // request register file - std::string xml_data; - if (!comm.ReadExtFeature(ConstString("features"), - ConstString(include), - xml_data, - lldberr)) - continue; - - XMLDocument include_xml_document; - include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), include.c_str()); - XMLNode include_feature_node = include_xml_document.GetRootElement("feature"); - if (include_feature_node) - { - ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); - } - } - this->m_register_info.Finalize(arch_to_use); + if (set_id != UINT32_MAX) + target_info.reg_set_map[set_id] = set_info; + return true; // Keep iterating through all "group" elements + }); + } + return true; // Keep iterating through all children of the target_node + }); + + // Initialize these outside of ParseRegisters, since they should not be + // reset inside each include feature + uint32_t cur_reg_num = 0; + uint32_t reg_offset = 0; + + // Don't use Process::GetABI, this code gets called from DidAttach, and in + // that context we haven't + // set the Target's architecture yet, so the ABI is also potentially + // incorrect. + ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use); + if (feature_node) { + ParseRegisters(feature_node, target_info, this->m_register_info, + abi_to_use_sp, cur_reg_num, reg_offset); + } + + for (const auto &include : target_info.includes) { + // request register file + std::string xml_data; + if (!comm.ReadExtFeature(ConstString("features"), ConstString(include), + xml_data, lldberr)) + continue; + + XMLDocument include_xml_document; + include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), + include.c_str()); + XMLNode include_feature_node = + include_xml_document.GetRootElement("feature"); + if (include_feature_node) { + ParseRegisters(include_feature_node, target_info, + this->m_register_info, abi_to_use_sp, cur_reg_num, + reg_offset); } + } + this->m_register_info.Finalize(arch_to_use); } + } - return m_register_info.GetNumRegisters() > 0; + return m_register_info.GetNumRegisters() > 0; } -Error -ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list) -{ - // Make sure LLDB has an XML parser it can use first - if (!XMLDocument::XMLEnabled()) - return Error (0, ErrorType::eErrorTypeGeneric); +Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { + // Make sure LLDB has an XML parser it can use first + if (!XMLDocument::XMLEnabled()) + return Error(0, ErrorType::eErrorTypeGeneric); - Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS); - if (log) - log->Printf ("ProcessGDBRemote::%s", __FUNCTION__); + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS); + if (log) + log->Printf("ProcessGDBRemote::%s", __FUNCTION__); - GDBRemoteCommunicationClient & comm = m_gdb_comm; + GDBRemoteCommunicationClient &comm = m_gdb_comm; - // check that we have extended feature read support - if (comm.GetQXferLibrariesSVR4ReadSupported ()) { - list.clear (); + // check that we have extended feature read support + if (comm.GetQXferLibrariesSVR4ReadSupported()) { + list.clear(); - // request the loaded library list - std::string raw; - lldb_private::Error lldberr; + // request the loaded library list + std::string raw; + lldb_private::Error lldberr; - if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr)) - return Error (0, ErrorType::eErrorTypeGeneric); + if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""), + raw, lldberr)) + return Error(0, ErrorType::eErrorTypeGeneric); - // parse the xml file in memory - if (log) - log->Printf ("parsing: %s", raw.c_str()); - XMLDocument doc; + // parse the xml file in memory + if (log) + log->Printf("parsing: %s", raw.c_str()); + XMLDocument doc; - if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Error (0, ErrorType::eErrorTypeGeneric); + if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) + return Error(0, ErrorType::eErrorTypeGeneric); - XMLNode root_element = doc.GetRootElement("library-list-svr4"); - if (!root_element) - return Error(); + XMLNode root_element = doc.GetRootElement("library-list-svr4"); + if (!root_element) + return Error(); - // main link map structure - llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); - if (!main_lm.empty()) - { - list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0); - } + // main link map structure + llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); + if (!main_lm.empty()) { + list.m_link_map = + StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0); + } - root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool { + root_element.ForEachChildElementWithName( + "library", [log, &list](const XMLNode &library) -> bool { - LoadedModuleInfoList::LoadedModuleInfo module; + LoadedModuleInfoList::LoadedModuleInfo module; - library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { + library.ForEachAttribute( + [log, &module](const llvm::StringRef &name, + const llvm::StringRef &value) -> bool { if (name == "name") - module.set_name (value.str()); - else if (name == "lm") - { - // the address of the link_map struct. - module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0)); - } - else if (name == "l_addr") - { - // the displacement as read from the field 'l_addr' of the link_map struct. - module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0)); - // base address is always a displacement, not an absolute value. - module.set_base_is_offset(true); - } - else if (name == "l_ld") - { - // the memory address of the libraries PT_DYAMIC section. - module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0)); + module.set_name(value.str()); + else if (name == "lm") { + // the address of the link_map struct. + module.set_link_map(StringConvert::ToUInt64( + value.data(), LLDB_INVALID_ADDRESS, 0)); + } else if (name == "l_addr") { + // the displacement as read from the field 'l_addr' of the + // link_map struct. + module.set_base(StringConvert::ToUInt64( + value.data(), LLDB_INVALID_ADDRESS, 0)); + // base address is always a displacement, not an absolute + // value. + module.set_base_is_offset(true); + } else if (name == "l_ld") { + // the memory address of the libraries PT_DYAMIC section. + module.set_dynamic(StringConvert::ToUInt64( + value.data(), LLDB_INVALID_ADDRESS, 0)); } return true; // Keep iterating over all properties of "library" - }); - - if (log) - { - std::string name; - lldb::addr_t lm=0, base=0, ld=0; - bool base_is_offset; - - module.get_name (name); - module.get_link_map (lm); - module.get_base (base); - module.get_base_is_offset (base_is_offset); - module.get_dynamic (ld); - - log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str()); - } - - list.add (module); - return true; // Keep iterating over all "library" elements in the root node + }); + + if (log) { + std::string name; + lldb::addr_t lm = 0, base = 0, ld = 0; + bool base_is_offset; + + module.get_name(name); + module.get_link_map(lm); + module.get_base(base); + module.get_base_is_offset(base_is_offset); + module.get_dynamic(ld); + + log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 + "[%s], ld:0x%08" PRIx64 ", name:'%s')", + lm, base, (base_is_offset ? "offset" : "absolute"), ld, + name.c_str()); + } + + list.add(module); + return true; // Keep iterating over all "library" elements in the root + // node }); - if (log) - log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size()); - } else if (comm.GetQXferLibrariesReadSupported ()) { - list.clear (); - - // request the loaded library list - std::string raw; - lldb_private::Error lldberr; - - if (!comm.ReadExtFeature (ConstString ("libraries"), ConstString (""), raw, lldberr)) - return Error (0, ErrorType::eErrorTypeGeneric); - - if (log) - log->Printf ("parsing: %s", raw.c_str()); - XMLDocument doc; - - if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Error (0, ErrorType::eErrorTypeGeneric); - - XMLNode root_element = doc.GetRootElement("library-list"); - if (!root_element) - return Error(); - - root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool { - LoadedModuleInfoList::LoadedModuleInfo module; - - llvm::StringRef name = library.GetAttributeValue("name"); - module.set_name(name.str()); + if (log) + log->Printf("found %" PRId32 " modules in total", + (int)list.m_list.size()); + } else if (comm.GetQXferLibrariesReadSupported()) { + list.clear(); - // The base address of a given library will be the address of its - // first section. Most remotes send only one section for Windows - // targets for example. - const XMLNode §ion = library.FindFirstChildElementWithName("section"); - llvm::StringRef address = section.GetAttributeValue("address"); - module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0)); - // These addresses are absolute values. - module.set_base_is_offset(false); + // request the loaded library list + std::string raw; + lldb_private::Error lldberr; - if (log) - { - std::string name; - lldb::addr_t base = 0; - bool base_is_offset; - module.get_name (name); - module.get_base (base); - module.get_base_is_offset (base_is_offset); - - log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str()); - } + if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw, + lldberr)) + return Error(0, ErrorType::eErrorTypeGeneric); - list.add (module); - return true; // Keep iterating over all "library" elements in the root node + if (log) + log->Printf("parsing: %s", raw.c_str()); + XMLDocument doc; + + if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) + return Error(0, ErrorType::eErrorTypeGeneric); + + XMLNode root_element = doc.GetRootElement("library-list"); + if (!root_element) + return Error(); + + root_element.ForEachChildElementWithName( + "library", [log, &list](const XMLNode &library) -> bool { + LoadedModuleInfoList::LoadedModuleInfo module; + + llvm::StringRef name = library.GetAttributeValue("name"); + module.set_name(name.str()); + + // The base address of a given library will be the address of its + // first section. Most remotes send only one section for Windows + // targets for example. + const XMLNode §ion = + library.FindFirstChildElementWithName("section"); + llvm::StringRef address = section.GetAttributeValue("address"); + module.set_base( + StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0)); + // These addresses are absolute values. + module.set_base_is_offset(false); + + if (log) { + std::string name; + lldb::addr_t base = 0; + bool base_is_offset; + module.get_name(name); + module.get_base(base); + module.get_base_is_offset(base_is_offset); + + log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, + (base_is_offset ? "offset" : "absolute"), name.c_str()); + } + + list.add(module); + return true; // Keep iterating over all "library" elements in the root + // node }); - if (log) - log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size()); - } else { - return Error (0, ErrorType::eErrorTypeGeneric); - } + if (log) + log->Printf("found %" PRId32 " modules in total", + (int)list.m_list.size()); + } else { + return Error(0, ErrorType::eErrorTypeGeneric); + } - return Error(); + return Error(); } -lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, - lldb::addr_t base_addr, bool value_is_offset) -{ - DynamicLoader *loader = GetDynamicLoader(); - if (!loader) - return nullptr; +lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, + lldb::addr_t link_map, + lldb::addr_t base_addr, + bool value_is_offset) { + DynamicLoader *loader = GetDynamicLoader(); + if (!loader) + return nullptr; - return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset); + return loader->LoadModuleAtAddress(file, link_map, base_addr, + value_is_offset); } -size_t -ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) -{ - using lldb_private::process_gdb_remote::ProcessGDBRemote; - - // request a list of loaded libraries from GDBServer - if (GetLoadedModuleList (module_list).Fail()) - return 0; - - // get a list of all the modules - ModuleList new_modules; - - for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list) - { - std::string mod_name; - lldb::addr_t mod_base; - lldb::addr_t link_map; - bool mod_base_is_offset; - - bool valid = true; - valid &= modInfo.get_name (mod_name); - valid &= modInfo.get_base (mod_base); - valid &= modInfo.get_base_is_offset (mod_base_is_offset); - if (!valid) - continue; - - if (!modInfo.get_link_map (link_map)) - link_map = LLDB_INVALID_ADDRESS; - - FileSpec file (mod_name.c_str(), true); - lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base, - mod_base_is_offset); - - if (module_sp.get()) - new_modules.Append (module_sp); - } - - if (new_modules.GetSize() > 0) - { - ModuleList removed_modules; - Target &target = GetTarget(); - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); - - for (size_t i = 0; i < loaded_modules.GetSize(); ++i) - { - const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); +size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { + using lldb_private::process_gdb_remote::ProcessGDBRemote; - bool found = false; - for (size_t j = 0; j < new_modules.GetSize(); ++j) - { - if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) - found = true; - } - - // The main executable will never be included in libraries-svr4, don't remove it - if (!found && loaded_module.get() != target.GetExecutableModulePointer()) - { - removed_modules.Append (loaded_module); - } - } - - loaded_modules.Remove (removed_modules); - m_process->GetTarget().ModulesDidUnload (removed_modules, false); + // request a list of loaded libraries from GDBServer + if (GetLoadedModuleList(module_list).Fail()) + return 0; - new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool - { - lldb_private::ObjectFile * obj = module_sp->GetObjectFile (); - if (!obj) - return true; + // get a list of all the modules + ModuleList new_modules; + + for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) { + std::string mod_name; + lldb::addr_t mod_base; + lldb::addr_t link_map; + bool mod_base_is_offset; + + bool valid = true; + valid &= modInfo.get_name(mod_name); + valid &= modInfo.get_base(mod_base); + valid &= modInfo.get_base_is_offset(mod_base_is_offset); + if (!valid) + continue; + + if (!modInfo.get_link_map(link_map)) + link_map = LLDB_INVALID_ADDRESS; + + FileSpec file(mod_name.c_str(), true); + lldb::ModuleSP module_sp = + LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset); + + if (module_sp.get()) + new_modules.Append(module_sp); + } + + if (new_modules.GetSize() > 0) { + ModuleList removed_modules; + Target &target = GetTarget(); + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + for (size_t i = 0; i < loaded_modules.GetSize(); ++i) { + const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); + + bool found = false; + for (size_t j = 0; j < new_modules.GetSize(); ++j) { + if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) + found = true; + } + + // The main executable will never be included in libraries-svr4, don't + // remove it + if (!found && + loaded_module.get() != target.GetExecutableModulePointer()) { + removed_modules.Append(loaded_module); + } + } + + loaded_modules.Remove(removed_modules); + m_process->GetTarget().ModulesDidUnload(removed_modules, false); + + new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool { + lldb_private::ObjectFile *obj = module_sp->GetObjectFile(); + if (!obj) + return true; - if (obj->GetType () != ObjectFile::Type::eTypeExecutable) - return true; + if (obj->GetType() != ObjectFile::Type::eTypeExecutable) + return true; - lldb::ModuleSP module_copy_sp = module_sp; - target.SetExecutableModule (module_copy_sp, false); - return false; - }); + lldb::ModuleSP module_copy_sp = module_sp; + target.SetExecutableModule(module_copy_sp, false); + return false; + }); - loaded_modules.AppendIfNeeded (new_modules); - m_process->GetTarget().ModulesDidLoad (new_modules); - } + loaded_modules.AppendIfNeeded(new_modules); + m_process->GetTarget().ModulesDidLoad(new_modules); + } - return new_modules.GetSize(); + return new_modules.GetSize(); } -size_t -ProcessGDBRemote::LoadModules () -{ - LoadedModuleInfoList module_list; - return LoadModules (module_list); +size_t ProcessGDBRemote::LoadModules() { + LoadedModuleInfoList module_list; + return LoadModules(module_list); } -Error -ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) -{ - is_loaded = false; - load_addr = LLDB_INVALID_ADDRESS; - - std::string file_path = file.GetPath(false); - if (file_path.empty ()) - return Error("Empty file name specified"); - - StreamString packet; - packet.PutCString("qFileLoadAddress:"); - packet.PutCStringAsRawHex8(file_path.c_str()); - - StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success) - return Error("Sending qFileLoadAddress packet failed"); - - if (response.IsErrorResponse()) - { - if (response.GetError() == 1) - { - // The file is not loaded into the inferior - is_loaded = false; - load_addr = LLDB_INVALID_ADDRESS; - return Error(); - } - - return Error("Fetching file load address from remote server returned an error"); - } - - if (response.IsNormalResponse()) - { - is_loaded = true; - load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - return Error(); - } +Error ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, + bool &is_loaded, + lldb::addr_t &load_addr) { + is_loaded = false; + load_addr = LLDB_INVALID_ADDRESS; + + std::string file_path = file.GetPath(false); + if (file_path.empty()) + return Error("Empty file name specified"); + + StreamString packet; + packet.PutCString("qFileLoadAddress:"); + packet.PutCStringAsRawHex8(file_path.c_str()); + + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), + response, false) != + GDBRemoteCommunication::PacketResult::Success) + return Error("Sending qFileLoadAddress packet failed"); + + if (response.IsErrorResponse()) { + if (response.GetError() == 1) { + // The file is not loaded into the inferior + is_loaded = false; + load_addr = LLDB_INVALID_ADDRESS; + return Error(); + } + + return Error( + "Fetching file load address from remote server returned an error"); + } + + if (response.IsNormalResponse()) { + is_loaded = true; + load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); + return Error(); + } - return Error("Unknown error happened during sending the load address packet"); + return Error("Unknown error happened during sending the load address packet"); } +void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) { + // We must call the lldb_private::Process::ModulesDidLoad () first before we + // do anything + Process::ModulesDidLoad(module_list); -void -ProcessGDBRemote::ModulesDidLoad (ModuleList &module_list) -{ - // We must call the lldb_private::Process::ModulesDidLoad () first before we do anything - Process::ModulesDidLoad (module_list); - - // After loading shared libraries, we can ask our remote GDB server if - // it needs any symbols. - m_gdb_comm.ServeSymbolLookups(this); + // After loading shared libraries, we can ask our remote GDB server if + // it needs any symbols. + m_gdb_comm.ServeSymbolLookups(this); } -void -ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) -{ - AppendSTDOUT(out.data(), out.size()); +void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) { + AppendSTDOUT(out.data(), out.size()); } static const char *end_delimiter = "--end--;"; static const int end_delimiter_len = 8; -void -ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) -{ - std::string input = data.str(); // '1' to move beyond 'A' - if (m_partial_profile_data.length() > 0) - { - m_partial_profile_data.append(input); - input = m_partial_profile_data; - m_partial_profile_data.clear(); - } - - size_t found, pos = 0, len = input.length(); - while ((found = input.find(end_delimiter, pos)) != std::string::npos) - { - StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str()); - std::string profile_data = HarmonizeThreadIdsForProfileData(profileDataExtractor); - BroadcastAsyncProfileData(profile_data); - - pos = found + end_delimiter_len; - } - - if (pos < len) - { - // Last incomplete chunk. - m_partial_profile_data = input.substr(pos); - } +void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) { + std::string input = data.str(); // '1' to move beyond 'A' + if (m_partial_profile_data.length() > 0) { + m_partial_profile_data.append(input); + input = m_partial_profile_data; + m_partial_profile_data.clear(); + } + + size_t found, pos = 0, len = input.length(); + while ((found = input.find(end_delimiter, pos)) != std::string::npos) { + StringExtractorGDBRemote profileDataExtractor( + input.substr(pos, found).c_str()); + std::string profile_data = + HarmonizeThreadIdsForProfileData(profileDataExtractor); + BroadcastAsyncProfileData(profile_data); + + pos = found + end_delimiter_len; + } + + if (pos < len) { + // Last incomplete chunk. + m_partial_profile_data = input.substr(pos); + } } -std::string -ProcessGDBRemote::HarmonizeThreadIdsForProfileData(StringExtractorGDBRemote &profileDataExtractor) -{ - std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map; - std::string output; - llvm::raw_string_ostream output_stream(output); - llvm::StringRef name, value; - - // Going to assuming thread_used_usec comes first, else bail out. - while (profileDataExtractor.GetNameColonValue(name, value)) - { - if (name.compare("thread_used_id") == 0) - { - StringExtractor threadIDHexExtractor(value); - uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0); - - bool has_used_usec = false; - uint32_t curr_used_usec = 0; - llvm::StringRef usec_name, usec_value; - uint32_t input_file_pos = profileDataExtractor.GetFilePos(); - if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) - { - if (usec_name.equals("thread_used_usec")) - { - has_used_usec = true; - usec_value.getAsInteger(0, curr_used_usec); - } - else - { - // We didn't find what we want, it is probably - // an older version. Bail out. - profileDataExtractor.SetFilePos(input_file_pos); - } - } - - if (has_used_usec) - { - uint32_t prev_used_usec = 0; - std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id); - if (iterator != m_thread_id_to_used_usec_map.end()) - { - prev_used_usec = m_thread_id_to_used_usec_map[thread_id]; - } - - uint32_t real_used_usec = curr_used_usec - prev_used_usec; - // A good first time record is one that runs for at least 0.25 sec - bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000); - bool good_subsequent_time = - (prev_used_usec > 0) && ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id))); - - if (good_first_time || good_subsequent_time) - { - // We try to avoid doing too many index id reservation, - // resulting in fast increase of index ids. - - output_stream << name << ":"; - int32_t index_id = AssignIndexIDToThread(thread_id); - output_stream << index_id << ";"; - - output_stream << usec_name << ":" << usec_value << ";"; - } - else - { - // Skip past 'thread_used_name'. - llvm::StringRef local_name, local_value; - profileDataExtractor.GetNameColonValue(local_name, local_value); - } - - // Store current time as previous time so that they can be compared later. - new_thread_id_to_used_usec_map[thread_id] = curr_used_usec; - } - else - { - // Bail out and use old string. - output_stream << name << ":" << value << ";"; - } +std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData( + StringExtractorGDBRemote &profileDataExtractor) { + std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map; + std::string output; + llvm::raw_string_ostream output_stream(output); + llvm::StringRef name, value; + + // Going to assuming thread_used_usec comes first, else bail out. + while (profileDataExtractor.GetNameColonValue(name, value)) { + if (name.compare("thread_used_id") == 0) { + StringExtractor threadIDHexExtractor(value); + uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0); + + bool has_used_usec = false; + uint32_t curr_used_usec = 0; + llvm::StringRef usec_name, usec_value; + uint32_t input_file_pos = profileDataExtractor.GetFilePos(); + if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) { + if (usec_name.equals("thread_used_usec")) { + has_used_usec = true; + usec_value.getAsInteger(0, curr_used_usec); + } else { + // We didn't find what we want, it is probably + // an older version. Bail out. + profileDataExtractor.SetFilePos(input_file_pos); } - else - { - output_stream << name << ":" << value << ";"; + } + + if (has_used_usec) { + uint32_t prev_used_usec = 0; + std::map<uint64_t, uint32_t>::iterator iterator = + m_thread_id_to_used_usec_map.find(thread_id); + if (iterator != m_thread_id_to_used_usec_map.end()) { + prev_used_usec = m_thread_id_to_used_usec_map[thread_id]; } + + uint32_t real_used_usec = curr_used_usec - prev_used_usec; + // A good first time record is one that runs for at least 0.25 sec + bool good_first_time = + (prev_used_usec == 0) && (real_used_usec > 250000); + bool good_subsequent_time = + (prev_used_usec > 0) && + ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id))); + + if (good_first_time || good_subsequent_time) { + // We try to avoid doing too many index id reservation, + // resulting in fast increase of index ids. + + output_stream << name << ":"; + int32_t index_id = AssignIndexIDToThread(thread_id); + output_stream << index_id << ";"; + + output_stream << usec_name << ":" << usec_value << ";"; + } else { + // Skip past 'thread_used_name'. + llvm::StringRef local_name, local_value; + profileDataExtractor.GetNameColonValue(local_name, local_value); + } + + // Store current time as previous time so that they can be compared + // later. + new_thread_id_to_used_usec_map[thread_id] = curr_used_usec; + } else { + // Bail out and use old string. + output_stream << name << ":" << value << ";"; + } + } else { + output_stream << name << ":" << value << ";"; } - output_stream << end_delimiter; - m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map; + } + output_stream << end_delimiter; + m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map; - return output_stream.str(); + return output_stream.str(); } -void -ProcessGDBRemote::HandleStopReply() -{ - if (GetStopID() != 0) - return; +void ProcessGDBRemote::HandleStopReply() { + if (GetStopID() != 0) + return; - if (GetID() == LLDB_INVALID_PROCESS_ID) - { - lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) - SetID(pid); - } - BuildDynamicRegisterInfo(true); + if (GetID() == LLDB_INVALID_PROCESS_ID) { + lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) + SetID(pid); + } + BuildDynamicRegisterInfo(true); } -bool -ProcessGDBRemote::HandleAsyncStructuredData(const StructuredData::ObjectSP - &object_sp) -{ - return RouteAsyncStructuredData(object_sp); +bool ProcessGDBRemote::HandleAsyncStructuredData( + const StructuredData::ObjectSP &object_sp) { + return RouteAsyncStructuredData(object_sp); } -class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed -{ +class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed { public: - CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process plugin packet speed-test", - "Tests packet speeds of various sizes to determine the performance characteristics of the GDB remote connection. ", - NULL), - m_option_group (), - m_num_packets (LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size (default is 1000).", 1000), - m_max_send (LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024), - m_max_recv (LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024), - m_json (LLDB_OPT_SET_1, false, "json", 'j', "Print the output as JSON data for easy parsing.", false, true) - { - m_option_group.Append (&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectProcessGDBRemoteSpeedTest () - { - } - - - Options * - GetOptions () override - { - return &m_option_group; - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - StreamSP output_stream_sp (m_interpreter.GetDebugger().GetAsyncOutputStream()); - result.SetImmediateOutputStream (output_stream_sp); - - const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); - const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); - const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); - const bool json = m_json.GetOptionValue().GetCurrentValue(); - if (output_stream_sp) - process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, *output_stream_sp); - else - { - process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, result.GetOutputStream()); - } - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - } - else - { - result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str()); + CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process plugin packet speed-test", + "Tests packet speeds of various sizes to determine " + "the performance characteristics of the GDB remote " + "connection. ", + NULL), + m_option_group(), + m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, + "The number of packets to send of each varying size " + "(default is 1000).", + 1000), + m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, + "The maximum number of bytes to send in a packet. Sizes " + "increase in powers of 2 while the size is less than or " + "equal to this option value. (default 1024).", + 1024), + m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, + "The maximum number of bytes to receive in a packet. Sizes " + "increase in powers of 2 while the size is less than or " + "equal to this option value. (default 1024).", + 1024), + m_json(LLDB_OPT_SET_1, false, "json", 'j', + "Print the output as JSON data for easy parsing.", false, true) { + m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectProcessGDBRemoteSpeedTest() {} + + Options *GetOptions() override { return &m_option_group; } + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + ProcessGDBRemote *process = + (ProcessGDBRemote *)m_interpreter.GetExecutionContext() + .GetProcessPtr(); + if (process) { + StreamSP output_stream_sp( + m_interpreter.GetDebugger().GetAsyncOutputStream()); + result.SetImmediateOutputStream(output_stream_sp); + + const uint32_t num_packets = + (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); + const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); + const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); + const bool json = m_json.GetOptionValue().GetCurrentValue(); + if (output_stream_sp) + process->GetGDBRemote().TestPacketSpeed( + num_packets, max_send, max_recv, json, *output_stream_sp); + else { + process->GetGDBRemote().TestPacketSpeed( + num_packets, max_send, max_recv, json, result.GetOutputStream()); } - result.SetStatus (eReturnStatusFailed); - return false; + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } else { + result.AppendErrorWithFormat("'%s' takes no arguments", + m_cmd_name.c_str()); } -protected: - OptionGroupOptions m_option_group; - OptionGroupUInt64 m_num_packets; - OptionGroupUInt64 m_max_send; - OptionGroupUInt64 m_max_recv; - OptionGroupBoolean m_json; + result.SetStatus(eReturnStatusFailed); + return false; + } +protected: + OptionGroupOptions m_option_group; + OptionGroupUInt64 m_num_packets; + OptionGroupUInt64 m_max_send; + OptionGroupUInt64 m_max_recv; + OptionGroupBoolean m_json; }; -class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed -{ +class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { private: - public: - CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process plugin packet history", - "Dumps the packet history buffer. ", - NULL) - { - } - - ~CommandObjectProcessGDBRemotePacketHistory () - { - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - process->GetGDBRemote().DumpHistory(result.GetOutputStream()); - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - } - else - { - result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str()); - } - result.SetStatus (eReturnStatusFailed); - return false; + CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process plugin packet history", + "Dumps the packet history buffer. ", NULL) {} + + ~CommandObjectProcessGDBRemotePacketHistory() {} + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + ProcessGDBRemote *process = + (ProcessGDBRemote *)m_interpreter.GetExecutionContext() + .GetProcessPtr(); + if (process) { + process->GetGDBRemote().DumpHistory(result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } else { + result.AppendErrorWithFormat("'%s' takes no arguments", + m_cmd_name.c_str()); } + result.SetStatus(eReturnStatusFailed); + return false; + } }; -class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed -{ +class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { private: - public: - CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process plugin packet xfer-size", - "Maximum size that lldb will try to read/write one one chunk.", - NULL) - { - } - - ~CommandObjectProcessGDBRemotePacketXferSize () - { - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - result.AppendErrorWithFormat ("'%s' takes an argument to specify the max amount to be transferred when reading/writing", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - const char *packet_size = command.GetArgumentAtIndex(0); - errno = 0; - uint64_t user_specified_max = strtoul (packet_size, NULL, 10); - if (errno == 0 && user_specified_max != 0) - { - process->SetUserSpecifiedMaxMemoryTransferSize (user_specified_max); - result.SetStatus (eReturnStatusSuccessFinishResult); - return true; - } - } - result.SetStatus (eReturnStatusFailed); - return false; + CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process plugin packet xfer-size", + "Maximum size that lldb will try to read/write one one chunk.", + NULL) {} + + ~CommandObjectProcessGDBRemotePacketXferSize() {} + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + result.AppendErrorWithFormat("'%s' takes an argument to specify the max " + "amount to be transferred when " + "reading/writing", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ProcessGDBRemote *process = + (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) { + const char *packet_size = command.GetArgumentAtIndex(0); + errno = 0; + uint64_t user_specified_max = strtoul(packet_size, NULL, 10); + if (errno == 0 && user_specified_max != 0) { + process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } } + result.SetStatus(eReturnStatusFailed); + return false; + } }; - -class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed -{ +class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { private: - public: - CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "process plugin packet send", - "Send a custom packet through the GDB remote protocol and print the answer. " - "The packet header and footer will automatically be added to the packet prior to sending and stripped from the result.", - NULL) - { - } - - ~CommandObjectProcessGDBRemotePacketSend () - { - } - - bool - DoExecute (Args& command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - result.AppendErrorWithFormat ("'%s' takes a one or more packet content arguments", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; + CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "process plugin packet send", + "Send a custom packet through the GDB remote " + "protocol and print the answer. " + "The packet header and footer will automatically " + "be added to the packet prior to sending and " + "stripped from the result.", + NULL) {} + + ~CommandObjectProcessGDBRemotePacketSend() {} + + bool DoExecute(Args &command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) { + result.AppendErrorWithFormat( + "'%s' takes a one or more packet content arguments", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ProcessGDBRemote *process = + (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) { + for (size_t i = 0; i < argc; ++i) { + const char *packet_cstr = command.GetArgumentAtIndex(0); + bool send_async = true; + StringExtractorGDBRemote response; + process->GetGDBRemote().SendPacketAndWaitForResponse( + packet_cstr, response, send_async); + result.SetStatus(eReturnStatusSuccessFinishResult); + Stream &output_strm = result.GetOutputStream(); + output_strm.Printf(" packet: %s\n", packet_cstr); + std::string &response_str = response.GetStringRef(); + + if (strstr(packet_cstr, "qGetProfileData") != NULL) { + response_str = process->HarmonizeThreadIdsForProfileData(response); } - ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - for (size_t i=0; i<argc; ++ i) - { - const char *packet_cstr = command.GetArgumentAtIndex(0); - bool send_async = true; - StringExtractorGDBRemote response; - process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async); - result.SetStatus (eReturnStatusSuccessFinishResult); - Stream &output_strm = result.GetOutputStream(); - output_strm.Printf (" packet: %s\n", packet_cstr); - std::string &response_str = response.GetStringRef(); - - if (strstr(packet_cstr, "qGetProfileData") != NULL) - { - response_str = process->HarmonizeThreadIdsForProfileData(response); - } - - if (response_str.empty()) - output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n"); - else - output_strm.Printf ("response: %s\n", response.GetStringRef().c_str()); - } - } - return true; + if (response_str.empty()) + output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); + else + output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); + } } + return true; + } }; -class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw -{ +class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw { private: - public: - CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) : - CommandObjectRaw (interpreter, - "process plugin packet monitor", - "Send a qRcmd packet through the GDB remote protocol and print the response." - "The argument passed to this command will be hex encoded into a valid 'qRcmd' packet, sent and the response will be printed.", - NULL) - { - } - - ~CommandObjectProcessGDBRemotePacketMonitor () - { - } - - bool - DoExecute (const char *command, CommandReturnObject &result) override - { - if (command == NULL || command[0] == '\0') - { - result.AppendErrorWithFormat ("'%s' takes a command string argument", m_cmd_name.c_str()); - result.SetStatus (eReturnStatusFailed); - return false; - } - - ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) - { - StreamString packet; - packet.PutCString("qRcmd,"); - packet.PutBytesAsRawHex8(command, strlen(command)); - const char *packet_cstr = packet.GetString().c_str(); - - bool send_async = true; - StringExtractorGDBRemote response; - process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async); - result.SetStatus (eReturnStatusSuccessFinishResult); - Stream &output_strm = result.GetOutputStream(); - output_strm.Printf (" packet: %s\n", packet_cstr); - const std::string &response_str = response.GetStringRef(); - - if (response_str.empty()) - output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n"); - else - output_strm.Printf ("response: %s\n", response.GetStringRef().c_str()); - } - return true; + CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "process plugin packet monitor", + "Send a qRcmd packet through the GDB remote protocol " + "and print the response." + "The argument passed to this command will be hex " + "encoded into a valid 'qRcmd' packet, sent and the " + "response will be printed.", + NULL) {} + + ~CommandObjectProcessGDBRemotePacketMonitor() {} + + bool DoExecute(const char *command, CommandReturnObject &result) override { + if (command == NULL || command[0] == '\0') { + result.AppendErrorWithFormat("'%s' takes a command string argument", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ProcessGDBRemote *process = + (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) { + StreamString packet; + packet.PutCString("qRcmd,"); + packet.PutBytesAsRawHex8(command, strlen(command)); + const char *packet_cstr = packet.GetString().c_str(); + + bool send_async = true; + StringExtractorGDBRemote response; + process->GetGDBRemote().SendPacketAndWaitForResponse( + packet_cstr, response, send_async); + result.SetStatus(eReturnStatusSuccessFinishResult); + Stream &output_strm = result.GetOutputStream(); + output_strm.Printf(" packet: %s\n", packet_cstr); + const std::string &response_str = response.GetStringRef(); + + if (response_str.empty()) + output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); + else + output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); } + return true; + } }; -class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword -{ +class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword { private: - public: - CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "process plugin packet", - "Commands that deal with GDB remote packets.", - NULL) - { - LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter))); - LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter))); - LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter))); - LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter))); - LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter))); - } - - ~CommandObjectProcessGDBRemotePacket () - { - } + CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "process plugin packet", + "Commands that deal with GDB remote packets.", + NULL) { + LoadSubCommand( + "history", + CommandObjectSP( + new CommandObjectProcessGDBRemotePacketHistory(interpreter))); + LoadSubCommand( + "send", CommandObjectSP( + new CommandObjectProcessGDBRemotePacketSend(interpreter))); + LoadSubCommand( + "monitor", + CommandObjectSP( + new CommandObjectProcessGDBRemotePacketMonitor(interpreter))); + LoadSubCommand( + "xfer-size", + CommandObjectSP( + new CommandObjectProcessGDBRemotePacketXferSize(interpreter))); + LoadSubCommand("speed-test", + CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest( + interpreter))); + } + + ~CommandObjectProcessGDBRemotePacket() {} }; -class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword -{ +class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { public: - CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.", - "process plugin <subcommand> [<subcommand-options>]") - { - LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket (interpreter))); - } - - ~CommandObjectMultiwordProcessGDBRemote () - { - } + CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "process plugin", + "Commands for operating on a ProcessGDBRemote process.", + "process plugin <subcommand> [<subcommand-options>]") { + LoadSubCommand( + "packet", + CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); + } + + ~CommandObjectMultiwordProcessGDBRemote() {} }; -CommandObject * -ProcessGDBRemote::GetPluginCommandObject() -{ - if (!m_command_sp) - m_command_sp.reset (new CommandObjectMultiwordProcessGDBRemote (GetTarget().GetDebugger().GetCommandInterpreter())); - return m_command_sp.get(); +CommandObject *ProcessGDBRemote::GetPluginCommandObject() { + if (!m_command_sp) + m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote( + GetTarget().GetDebugger().GetCommandInterpreter())); + return m_command_sp.get(); } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 3a0dd2f7235..f2a58dbccaa 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -24,16 +24,16 @@ #include "lldb/Core/Broadcaster.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" +#include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/StringList.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/ThreadSafeValue.h" -#include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Host/HostThread.h" -#include "lldb/lldb-private-forward.h" -#include "lldb/Utility/StringExtractor.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/StringExtractor.h" +#include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationClient.h" #include "GDBRemoteRegisterContext.h" @@ -43,478 +43,376 @@ namespace process_gdb_remote { class ThreadGDBRemote; -class ProcessGDBRemote : public Process, private GDBRemoteClientBase::ContinueDelegate -{ +class ProcessGDBRemote : public Process, + private GDBRemoteClientBase::ContinueDelegate { public: - ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + + ~ProcessGDBRemote() override; + + static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *crash_file_path); + + static void Initialize(); + + static void DebuggerInitialize(Debugger &debugger); + + static void Terminate(); + + static ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Check if a given Process + //------------------------------------------------------------------ + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + + CommandObject *GetPluginCommandObject() override; + + //------------------------------------------------------------------ + // Creating a new process, or attaching to an existing one + //------------------------------------------------------------------ + Error WillLaunch(Module *module) override; + + Error DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; + + void DidLaunch() override; + + Error WillAttachToProcessWithID(lldb::pid_t pid) override; + + Error WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) override; + + Error DoConnectRemote(Stream *strm, const char *remote_url) override; + + Error WillLaunchOrAttach(); + + Error DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) override; + + Error + DoAttachToProcessWithName(const char *process_name, + const ProcessAttachInfo &attach_info) override; + + void DidAttach(ArchSpec &process_arch) override; + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + + //------------------------------------------------------------------ + // Process Control + //------------------------------------------------------------------ + Error WillResume() override; + + Error DoResume() override; + + Error DoHalt(bool &caused_stop) override; + + Error DoDetach(bool keep_stopped) override; + + bool DetachRequiresHalt() override { return true; } + + Error DoSignal(int signal) override; + + Error DoDestroy() override; + + void RefreshStateAfterStop() override; + + void SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); + + //------------------------------------------------------------------ + // Process Queries + //------------------------------------------------------------------ + bool IsAlive() override; + + lldb::addr_t GetImageInfoAddress() override; + + void WillPublicStop() override; + + //------------------------------------------------------------------ + // Process Memory + //------------------------------------------------------------------ + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Error &error) override; - ~ProcessGDBRemote() override; + size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, + Error &error) override; - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path); + lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) override; - static void - Initialize(); + Error GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion_info) override; - static void - DebuggerInitialize (Debugger &debugger); + Error DoDeallocateMemory(lldb::addr_t ptr) override; - static void - Terminate(); + //------------------------------------------------------------------ + // Process STDIO + //------------------------------------------------------------------ + size_t PutSTDIN(const char *buf, size_t buf_size, Error &error) override; - static ConstString - GetPluginNameStatic(); + //---------------------------------------------------------------------- + // Process Breakpoints + //---------------------------------------------------------------------- + Error EnableBreakpointSite(BreakpointSite *bp_site) override; - static const char * - GetPluginDescriptionStatic(); + Error DisableBreakpointSite(BreakpointSite *bp_site) override; - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - bool - CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + //---------------------------------------------------------------------- + // Process Watchpoints + //---------------------------------------------------------------------- + Error EnableWatchpoint(Watchpoint *wp, bool notify = true) override; - CommandObject * - GetPluginCommandObject() override; + Error DisableWatchpoint(Watchpoint *wp, bool notify = true) override; - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - Error - WillLaunch (Module* module) override; + Error GetWatchpointSupportInfo(uint32_t &num) override; - Error - DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) override; + Error GetWatchpointSupportInfo(uint32_t &num, bool &after) override; - void - DidLaunch () override; - - Error - WillAttachToProcessWithID (lldb::pid_t pid) override; - - Error - WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override; + bool StartNoticingNewThreads() override; - Error - DoConnectRemote (Stream *strm, const char *remote_url) override; - - Error - WillLaunchOrAttach (); - - Error - DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) override; - - Error - DoAttachToProcessWithName (const char *process_name, - const ProcessAttachInfo &attach_info) override; - - void - DidAttach (ArchSpec &process_arch) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - ConstString - GetPluginName() override; - - uint32_t - GetPluginVersion() override; - - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - Error - WillResume () override; - - Error - DoResume () override; - - Error - DoHalt (bool &caused_stop) override; - - Error - DoDetach (bool keep_stopped) override; - - bool - DetachRequiresHalt() override { return true; } - - Error - DoSignal (int signal) override; - - Error - DoDestroy () override; - - void - RefreshStateAfterStop() override; - - void - SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); - - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - bool - IsAlive () override; - - lldb::addr_t - GetImageInfoAddress() override; - - void - WillPublicStop () override; - - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) override; - - size_t - DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, Error &error) override; - - lldb::addr_t - DoAllocateMemory (size_t size, uint32_t permissions, Error &error) override; - - Error - GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) override; - - Error - DoDeallocateMemory (lldb::addr_t ptr) override; - - //------------------------------------------------------------------ - // Process STDIO - //------------------------------------------------------------------ - size_t - PutSTDIN (const char *buf, size_t buf_size, Error &error) override; - - //---------------------------------------------------------------------- - // Process Breakpoints - //---------------------------------------------------------------------- - Error - EnableBreakpointSite (BreakpointSite *bp_site) override; - - Error - DisableBreakpointSite (BreakpointSite *bp_site) override; - - //---------------------------------------------------------------------- - // Process Watchpoints - //---------------------------------------------------------------------- - Error - EnableWatchpoint (Watchpoint *wp, bool notify = true) override; - - Error - DisableWatchpoint (Watchpoint *wp, bool notify = true) override; - - Error - GetWatchpointSupportInfo (uint32_t &num) override; - - Error - GetWatchpointSupportInfo (uint32_t &num, bool& after) override; - - bool - StartNoticingNewThreads() override; - - bool - StopNoticingNewThreads() override; + bool StopNoticingNewThreads() override; - GDBRemoteCommunicationClient & - GetGDBRemote() - { - return m_gdb_comm; - } - - Error - SendEventData(const char *data) override; + GDBRemoteCommunicationClient &GetGDBRemote() { return m_gdb_comm; } - //---------------------------------------------------------------------- - // Override DidExit so we can disconnect from the remote GDB server - //---------------------------------------------------------------------- - void - DidExit () override; - - void - SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max); - - bool - GetModuleSpec(const FileSpec& module_file_spec, - const ArchSpec& arch, - ModuleSpec &module_spec) override; - - bool - GetHostOSVersion(uint32_t &major, - uint32_t &minor, - uint32_t &update) override; + Error SendEventData(const char *data) override; - size_t - LoadModules(LoadedModuleInfoList &module_list) override; - - size_t - LoadModules() override; - - Error - GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) override; - - void - ModulesDidLoad (ModuleList &module_list) override; + //---------------------------------------------------------------------- + // Override DidExit so we can disconnect from the remote GDB server + //---------------------------------------------------------------------- + void DidExit() override; - StructuredData::ObjectSP - GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override; - - Error - ConfigureStructuredData(const ConstString &type_name, - const StructuredData::ObjectSP &config_sp) override; - - StructuredData::ObjectSP - GetLoadedDynamicLibrariesInfos () override; - - StructuredData::ObjectSP - GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses) override; - - StructuredData::ObjectSP - GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args); - - StructuredData::ObjectSP - GetSharedCacheInfo () override; - - std::string - HarmonizeThreadIdsForProfileData(StringExtractorGDBRemote &inputStringExtractor); + void SetUserSpecifiedMaxMemoryTransferSize(uint64_t user_specified_max); + + bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch, + ModuleSpec &module_spec) override; + + bool GetHostOSVersion(uint32_t &major, uint32_t &minor, + uint32_t &update) override; + + size_t LoadModules(LoadedModuleInfoList &module_list) override; + + size_t LoadModules() override; + + Error GetFileLoadAddress(const FileSpec &file, bool &is_loaded, + lldb::addr_t &load_addr) override; + + void ModulesDidLoad(ModuleList &module_list) override; + + StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos(lldb::addr_t image_list_address, + lldb::addr_t image_count) override; + + Error + ConfigureStructuredData(const ConstString &type_name, + const StructuredData::ObjectSP &config_sp) override; + + StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos() override; + + StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos( + const std::vector<lldb::addr_t> &load_addresses) override; + + StructuredData::ObjectSP + GetLoadedDynamicLibrariesInfos_sender(StructuredData::ObjectSP args); + + StructuredData::ObjectSP GetSharedCacheInfo() override; + + std::string HarmonizeThreadIdsForProfileData( + StringExtractorGDBRemote &inputStringExtractor); protected: - friend class ThreadGDBRemote; - friend class GDBRemoteCommunicationClient; - friend class GDBRemoteRegisterContext; - - //------------------------------------------------------------------ - /// Broadcaster event bits definitions. - //------------------------------------------------------------------ - enum - { - eBroadcastBitAsyncContinue = (1 << 0), - eBroadcastBitAsyncThreadShouldExit = (1 << 1), - eBroadcastBitAsyncThreadDidExit = (1 << 2) - }; - - Flags m_flags; // Process specific flags (see eFlags enums) - GDBRemoteCommunicationClient m_gdb_comm; - std::atomic<lldb::pid_t> m_debugserver_pid; - std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable - std::recursive_mutex m_last_stop_packet_mutex; - GDBRemoteDynamicRegisterInfo m_register_info; - Broadcaster m_async_broadcaster; - lldb::ListenerSP m_async_listener_sp; - HostThread m_async_thread; - std::recursive_mutex m_async_thread_state_mutex; - typedef std::vector<lldb::tid_t> tid_collection; - typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection; - typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; - typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; - tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping - std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads. - StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos - StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported - tid_collection m_continue_c_tids; // 'c' for continue - tid_sig_collection m_continue_C_tids; // 'C' for continue with signal - tid_collection m_continue_s_tids; // 's' for step - tid_sig_collection m_continue_S_tids; // 'S' for step with signal - uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory - uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle - MMapMap m_addr_to_mmap_size; - lldb::BreakpointSP m_thread_create_bp_sp; - bool m_waiting_for_attach; - bool m_destroy_tried_resuming; - lldb::CommandObjectSP m_command_sp; - int64_t m_breakpoint_pc_offset; - lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - bool - IsRunning ( lldb::StateType state ) - { - return state == lldb::eStateRunning || IsStepping(state); - } - - bool - IsStepping ( lldb::StateType state) - { - return state == lldb::eStateStepping; - } - - bool - CanResume ( lldb::StateType state) - { - return state == lldb::eStateStopped; - } - - bool - HasExited (lldb::StateType state) - { - return state == lldb::eStateExited; - } - - bool - ProcessIDIsValid ( ) const; - - void - Clear ( ); - - Flags & - GetFlags () - { - return m_flags; - } - - const Flags & - GetFlags () const - { - return m_flags; - } - - bool - UpdateThreadList (ThreadList &old_thread_list, - ThreadList &new_thread_list) override; - - Error - EstablishConnectionIfNeeded (const ProcessInfo &process_info); - - Error - LaunchAndConnectToDebugserver (const ProcessInfo &process_info); - - void - KillDebugserverProcess (); - - void - BuildDynamicRegisterInfo (bool force); - - void - SetLastStopPacket (const StringExtractorGDBRemote &response); - - bool - ParsePythonTargetDefinition(const FileSpec &target_definition_fspec); - - const lldb::DataBufferSP - GetAuxvData() override; - - StructuredData::ObjectSP - GetExtendedInfoForThread (lldb::tid_t tid); - - void - GetMaxMemorySize(); - - bool - CalculateThreadStopInfo (ThreadGDBRemote *thread); - - size_t - UpdateThreadPCsFromStopReplyThreadsValue (std::string &value); - - size_t - UpdateThreadIDsFromStopReplyThreadsValue (std::string &value); - - bool - HandleNotifyPacket(StringExtractorGDBRemote &packet); - - bool - StartAsyncThread (); - - void - StopAsyncThread (); - - static lldb::thread_result_t - AsyncThread (void *arg); + friend class ThreadGDBRemote; + friend class GDBRemoteCommunicationClient; + friend class GDBRemoteRegisterContext; + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum { + eBroadcastBitAsyncContinue = (1 << 0), + eBroadcastBitAsyncThreadShouldExit = (1 << 1), + eBroadcastBitAsyncThreadDidExit = (1 << 2) + }; + + Flags m_flags; // Process specific flags (see eFlags enums) + GDBRemoteCommunicationClient m_gdb_comm; + std::atomic<lldb::pid_t> m_debugserver_pid; + std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet + // stack replaces + // the last stop + // packet variable + std::recursive_mutex m_last_stop_packet_mutex; + GDBRemoteDynamicRegisterInfo m_register_info; + Broadcaster m_async_broadcaster; + lldb::ListenerSP m_async_listener_sp; + HostThread m_async_thread; + std::recursive_mutex m_async_thread_state_mutex; + typedef std::vector<lldb::tid_t> tid_collection; + typedef std::vector<std::pair<lldb::tid_t, int>> tid_sig_collection; + typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; + typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; + tid_collection m_thread_ids; // Thread IDs for all threads. This list gets + // updated after stopping + std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads. + StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads + // that have valid stop infos + StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited + // registers and memory for all + // threads if "jThreadsInfo" + // packet is supported + tid_collection m_continue_c_tids; // 'c' for continue + tid_sig_collection m_continue_C_tids; // 'C' for continue with signal + tid_collection m_continue_s_tids; // 's' for step + tid_sig_collection m_continue_S_tids; // 'S' for step with signal + uint64_t m_max_memory_size; // The maximum number of bytes to read/write when + // reading and writing memory + uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote + // gdb stub can handle + MMapMap m_addr_to_mmap_size; + lldb::BreakpointSP m_thread_create_bp_sp; + bool m_waiting_for_attach; + bool m_destroy_tried_resuming; + lldb::CommandObjectSP m_command_sp; + int64_t m_breakpoint_pc_offset; + lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + bool IsRunning(lldb::StateType state) { + return state == lldb::eStateRunning || IsStepping(state); + } + + bool IsStepping(lldb::StateType state) { + return state == lldb::eStateStepping; + } + + bool CanResume(lldb::StateType state) { return state == lldb::eStateStopped; } + + bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; } + + bool ProcessIDIsValid() const; + + void Clear(); + + Flags &GetFlags() { return m_flags; } + + const Flags &GetFlags() const { return m_flags; } + + bool UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) override; + + Error EstablishConnectionIfNeeded(const ProcessInfo &process_info); + + Error LaunchAndConnectToDebugserver(const ProcessInfo &process_info); + + void KillDebugserverProcess(); + + void BuildDynamicRegisterInfo(bool force); + + void SetLastStopPacket(const StringExtractorGDBRemote &response); + + bool ParsePythonTargetDefinition(const FileSpec &target_definition_fspec); + + const lldb::DataBufferSP GetAuxvData() override; + + StructuredData::ObjectSP GetExtendedInfoForThread(lldb::tid_t tid); + + void GetMaxMemorySize(); + + bool CalculateThreadStopInfo(ThreadGDBRemote *thread); + + size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value); + + size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value); + + bool HandleNotifyPacket(StringExtractorGDBRemote &packet); + + bool StartAsyncThread(); + + void StopAsyncThread(); + + static lldb::thread_result_t AsyncThread(void *arg); - static bool - MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t pid, bool exited, int signo, - int exit_status); + static bool + MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, + lldb::pid_t pid, bool exited, int signo, + int exit_status); - lldb::StateType - SetThreadStopInfo (StringExtractor& stop_packet); + lldb::StateType SetThreadStopInfo(StringExtractor &stop_packet); - bool - GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp); + bool + GetThreadStopInfoFromJSON(ThreadGDBRemote *thread, + const StructuredData::ObjectSP &thread_infos_sp); - lldb::ThreadSP - SetThreadStopInfo (StructuredData::Dictionary *thread_dict); + lldb::ThreadSP SetThreadStopInfo(StructuredData::Dictionary *thread_dict); - lldb::ThreadSP - SetThreadStopInfo (lldb::tid_t tid, - ExpeditedRegisterMap &expedited_register_map, - uint8_t signo, - const std::string &thread_name, - const std::string &reason, - const std::string &description, - uint32_t exc_type, - const std::vector<lldb::addr_t> &exc_data, - lldb::addr_t thread_dispatch_qaddr, - bool queue_vars_valid, - lldb_private::LazyBool associated_with_libdispatch_queue, - lldb::addr_t dispatch_queue_t, - std::string &queue_name, - lldb::QueueKind queue_kind, - uint64_t queue_serial); + lldb::ThreadSP + SetThreadStopInfo(lldb::tid_t tid, + ExpeditedRegisterMap &expedited_register_map, uint8_t signo, + const std::string &thread_name, const std::string &reason, + const std::string &description, uint32_t exc_type, + const std::vector<lldb::addr_t> &exc_data, + lldb::addr_t thread_dispatch_qaddr, bool queue_vars_valid, + lldb_private::LazyBool associated_with_libdispatch_queue, + lldb::addr_t dispatch_queue_t, std::string &queue_name, + lldb::QueueKind queue_kind, uint64_t queue_serial); - void - HandleStopReplySequence (); + void HandleStopReplySequence(); - void - ClearThreadIDList (); + void ClearThreadIDList(); - bool - UpdateThreadIDList (); + bool UpdateThreadIDList(); - void - DidLaunchOrAttach (ArchSpec& process_arch); + void DidLaunchOrAttach(ArchSpec &process_arch); - Error - ConnectToDebugserver (const char *host_port); + Error ConnectToDebugserver(const char *host_port); - const char * - GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr, - std::string &dispatch_queue_name); + const char *GetDispatchQueueNameForThread(lldb::addr_t thread_dispatch_qaddr, + std::string &dispatch_queue_name); - DynamicLoader * - GetDynamicLoader () override; + DynamicLoader *GetDynamicLoader() override; - // Query remote GDBServer for register information - bool - GetGDBServerRegisterInfo (ArchSpec &arch); + // Query remote GDBServer for register information + bool GetGDBServerRegisterInfo(ArchSpec &arch); - // Query remote GDBServer for a detailed loaded library list - Error - GetLoadedModuleList (LoadedModuleInfoList &); + // Query remote GDBServer for a detailed loaded library list + Error GetLoadedModuleList(LoadedModuleInfoList &); - lldb::ModuleSP - LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, - bool value_is_offset); + lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file, + lldb::addr_t link_map, + lldb::addr_t base_addr, + bool value_is_offset); private: - //------------------------------------------------------------------ - // For ProcessGDBRemote only - //------------------------------------------------------------------ - std::string m_partial_profile_data; - std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map; - - static bool - NewThreadNotifyBreakpointHit (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - //------------------------------------------------------------------ - // ContinueDelegate interface - //------------------------------------------------------------------ - void - HandleAsyncStdout(llvm::StringRef out) override; - void - HandleAsyncMisc(llvm::StringRef data) override; - void - HandleStopReply() override; - bool - HandleAsyncStructuredData(const StructuredData::ObjectSP - &object_sp) override; - - DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote); + //------------------------------------------------------------------ + // For ProcessGDBRemote only + //------------------------------------------------------------------ + std::string m_partial_profile_data; + std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map; + + static bool NewThreadNotifyBreakpointHit(void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + //------------------------------------------------------------------ + // ContinueDelegate interface + //------------------------------------------------------------------ + void HandleAsyncStdout(llvm::StringRef out) override; + void HandleAsyncMisc(llvm::StringRef data) override; + void HandleStopReply() override; + bool + HandleAsyncStructuredData(const StructuredData::ObjectSP &object_sp) override; + + DISALLOW_COPY_AND_ASSIGN(ProcessGDBRemote); }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index d4726adc890..80139cedc7a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -11,8 +11,8 @@ #include <mutex> -#include "lldb/Interpreter/Args.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" #include "ProcessGDBRemote.h" @@ -20,196 +20,198 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; - // We want to avoid global constructors where code needs to be run so here we // control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_lob_sp the first time this function is +// that will construct the static g_lob_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = NULL; -static Log * -GetLog () -{ - if (!g_log_enabled) - return NULL; - return g_log; +static Log *g_log = NULL; +static Log *GetLog() { + if (!g_log_enabled) + return NULL; + return g_log; } -void -ProcessGDBRemoteLog::Initialize() -{ - static ConstString g_name("gdb-remote"); - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, [](){ - Log::Callbacks log_callbacks = { - DisableLog, - EnableLog, - ListLogCategories - }; - - Log::RegisterLogChannel (g_name, log_callbacks); - }); -} +void ProcessGDBRemoteLog::Initialize() { + static ConstString g_name("gdb-remote"); + static std::once_flag g_once_flag; -Log * -ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; + std::call_once(g_once_flag, []() { + Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; + + Log::RegisterLogChannel(g_name, log_callbacks); + }); } -Log * -ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log && log->GetMask().Get() & mask) - return log; - return NULL; +Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) { + Log *log(GetLog()); + if (log && mask) { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return NULL; + } + return log; } -void -ProcessGDBRemoteLog::DisableLog (const char **categories, Stream *feedback_strm) -{ - Log *log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - if (categories[0] != NULL) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; categories[i] != NULL; ++i) - { - const char *arg = categories[i]; - - - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~GDBR_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~GDBR_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~GDBR_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~GDBR_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~GDBR_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~GDBR_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~GDBR_LOG_PROCESS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~GDBR_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~GDBR_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~GDBR_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~GDBR_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - - } - } - - if (flag_bits == 0) - g_log_enabled = false; - else - log->GetMask().Reset (flag_bits); - } - - return; +Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) { + Log *log(GetLog()); + if (log && log->GetMask().Get() & mask) + return log; + return NULL; } -Log * -ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. +void ProcessGDBRemoteLog::DisableLog(const char **categories, + Stream *feedback_strm) { + Log *log(GetLog()); + if (log) { uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); + + if (categories[0] != NULL) { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits &= ~GDBR_LOG_ALL; + else if (::strcasecmp(arg, "async") == 0) + flag_bits &= ~GDBR_LOG_ASYNC; + else if (::strncasecmp(arg, "break", 5) == 0) + flag_bits &= ~GDBR_LOG_BREAKPOINTS; + else if (::strncasecmp(arg, "comm", 4) == 0) + flag_bits &= ~GDBR_LOG_COMM; + else if (::strcasecmp(arg, "default") == 0) + flag_bits &= ~GDBR_LOG_DEFAULT; + else if (::strcasecmp(arg, "packets") == 0) + flag_bits &= ~GDBR_LOG_PACKETS; + else if (::strcasecmp(arg, "memory") == 0) + flag_bits &= ~GDBR_LOG_MEMORY; + else if (::strcasecmp(arg, "data-short") == 0) + flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp(arg, "data-long") == 0) + flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp(arg, "process") == 0) + flag_bits &= ~GDBR_LOG_PROCESS; + else if (::strcasecmp(arg, "step") == 0) + flag_bits &= ~GDBR_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + flag_bits &= ~GDBR_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + flag_bits &= ~GDBR_LOG_VERBOSE; + else if (::strncasecmp(arg, "watch", 5) == 0) + flag_bits &= ~GDBR_LOG_WATCHPOINTS; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); + } + } } + if (flag_bits == 0) + g_log_enabled = false; + else + log->GetMask().Reset(flag_bits); + } + + return; +} + +Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp, + uint32_t log_options, + const char **categories, + Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits = 0; + if (g_log) + flag_bits = g_log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log) - { - bool got_unknown_category = false; - for (size_t i=0; categories[i] != NULL; ++i) - { - const char *arg = categories[i]; - - if (::strcasecmp (arg, "all") == 0 ) flag_bits |= GDBR_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= GDBR_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= GDBR_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= GDBR_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= GDBR_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= GDBR_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= GDBR_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= GDBR_LOG_PROCESS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= GDBR_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= GDBR_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= GDBR_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= GDBR_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } + + if (g_log) { + bool got_unknown_category = false; + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits |= GDBR_LOG_ALL; + else if (::strcasecmp(arg, "async") == 0) + flag_bits |= GDBR_LOG_ASYNC; + else if (::strncasecmp(arg, "break", 5) == 0) + flag_bits |= GDBR_LOG_BREAKPOINTS; + else if (::strncasecmp(arg, "comm", 4) == 0) + flag_bits |= GDBR_LOG_COMM; + else if (::strcasecmp(arg, "default") == 0) + flag_bits |= GDBR_LOG_DEFAULT; + else if (::strcasecmp(arg, "packets") == 0) + flag_bits |= GDBR_LOG_PACKETS; + else if (::strcasecmp(arg, "memory") == 0) + flag_bits |= GDBR_LOG_MEMORY; + else if (::strcasecmp(arg, "data-short") == 0) + flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp(arg, "data-long") == 0) + flag_bits |= GDBR_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp(arg, "process") == 0) + flag_bits |= GDBR_LOG_PROCESS; + else if (::strcasecmp(arg, "step") == 0) + flag_bits |= GDBR_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0) + flag_bits |= GDBR_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0) + flag_bits |= GDBR_LOG_VERBOSE; + else if (::strncasecmp(arg, "watch", 5) == 0) + flag_bits |= GDBR_LOG_WATCHPOINTS; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListLogCategories(feedback_strm); } - if (flag_bits == 0) - flag_bits = GDBR_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); + } } - g_log_enabled = true; - return g_log; + if (flag_bits == 0) + flag_bits = GDBR_LOG_DEFAULT; + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + } + g_log_enabled = true; + return g_log; } -void -ProcessGDBRemoteLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic().GetCString()); +void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) { + strm->Printf( + "Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " async - log asynchronous activity\n" + " break - log breakpoints\n" + " communication - log communication activity\n" + " default - enable the default set of logging categories for liblldb\n" + " packets - log gdb remote packets\n" + " memory - log memory reads and writes\n" + " data-short - log memory bytes for memory reads and writes for short " + "transactions only\n" + " data-long - log memory bytes for memory reads and writes for all " + "transactions\n" + " process - log process events and activities\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n", + ProcessGDBRemote::GetPluginNameStatic().GetCString()); } - -void -ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...) -{ - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } +void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask)); + if (log) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index 3cd974d7d82..f5e92b45061 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -17,50 +17,44 @@ // Project includes #include "lldb/Core/Log.h" -#define GDBR_LOG_VERBOSE (1u << 0) -#define GDBR_LOG_PROCESS (1u << 1) -#define GDBR_LOG_THREAD (1u << 2) -#define GDBR_LOG_PACKETS (1u << 3) -#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define GDBR_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define GDBR_LOG_BREAKPOINTS (1u << 7) -#define GDBR_LOG_WATCHPOINTS (1u << 8) -#define GDBR_LOG_STEP (1u << 9) -#define GDBR_LOG_COMM (1u << 10) -#define GDBR_LOG_ASYNC (1u << 11) -#define GDBR_LOG_ALL (UINT32_MAX) -#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS +#define GDBR_LOG_VERBOSE (1u << 0) +#define GDBR_LOG_PROCESS (1u << 1) +#define GDBR_LOG_THREAD (1u << 2) +#define GDBR_LOG_PACKETS (1u << 3) +#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define GDBR_LOG_MEMORY_DATA_SHORT \ + (1u << 5) // Log short memory reads/writes bytes +#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes +#define GDBR_LOG_BREAKPOINTS (1u << 7) +#define GDBR_LOG_WATCHPOINTS (1u << 8) +#define GDBR_LOG_STEP (1u << 9) +#define GDBR_LOG_COMM (1u << 10) +#define GDBR_LOG_ASYNC (1u << 11) +#define GDBR_LOG_ALL (UINT32_MAX) +#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS namespace lldb_private { namespace process_gdb_remote { -class ProcessGDBRemoteLog -{ +class ProcessGDBRemoteLog { public: - static void - Initialize(); + static void Initialize(); - static Log * - GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static Log * - GetLogIfAnyCategoryIsSet (uint32_t mask); + static Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); - static void - DisableLog (const char **categories, Stream *feedback_strm); + static Log *GetLogIfAnyCategoryIsSet(uint32_t mask); - static Log * - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm); + static void DisableLog(const char **categories, Stream *feedback_strm); - static void - ListLogCategories (Stream *strm); + static Log *EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options, + const char **categories, Stream *feedback_strm); - static void - LogIf (uint32_t mask, const char *format, ...); + static void ListLogCategories(Stream *strm); + + static void LogIf(uint32_t mask, const char *format, ...); }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_ProcessGDBRemoteLog_h_ +#endif // liblldb_ProcessGDBRemoteLog_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 02a617badeb..ab552145a18 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "ThreadGDBRemote.h" #include "lldb/Breakpoint/Watchpoint.h" @@ -36,372 +35,318 @@ using namespace lldb_private::process_gdb_remote; // Thread Registers //---------------------------------------------------------------------- -ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) : - Thread(process, tid), - m_thread_name (), - m_dispatch_queue_name (), - m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS), - m_dispatch_queue_t (LLDB_INVALID_ADDRESS), - m_queue_kind (eQueueKindUnknown), - m_queue_serial_number (LLDB_INVALID_QUEUE_ID), - m_associated_with_libdispatch_queue (eLazyBoolCalculate) -{ - ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", - this, - process.GetID(), - GetID()); +ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) + : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), + m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), + m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown), + m_queue_serial_number(LLDB_INVALID_QUEUE_ID), + m_associated_with_libdispatch_queue(eLazyBoolCalculate) { + ProcessGDBRemoteLog::LogIf( + GDBR_LOG_THREAD, + "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, + process.GetID(), GetID()); } -ThreadGDBRemote::~ThreadGDBRemote () -{ - ProcessSP process_sp(GetProcess()); - ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", - this, - process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, - GetID()); - DestroyThread(); +ThreadGDBRemote::~ThreadGDBRemote() { + ProcessSP process_sp(GetProcess()); + ProcessGDBRemoteLog::LogIf( + GDBR_LOG_THREAD, + "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, + process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); + DestroyThread(); } -const char * -ThreadGDBRemote::GetName () -{ - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); +const char *ThreadGDBRemote::GetName() { + if (m_thread_name.empty()) + return NULL; + return m_thread_name.c_str(); } -void -ThreadGDBRemote::ClearQueueInfo () -{ - m_dispatch_queue_name.clear(); - m_queue_kind = eQueueKindUnknown; - m_queue_serial_number = 0; - m_dispatch_queue_t = LLDB_INVALID_ADDRESS; - m_associated_with_libdispatch_queue = eLazyBoolCalculate; +void ThreadGDBRemote::ClearQueueInfo() { + m_dispatch_queue_name.clear(); + m_queue_kind = eQueueKindUnknown; + m_queue_serial_number = 0; + m_dispatch_queue_t = LLDB_INVALID_ADDRESS; + m_associated_with_libdispatch_queue = eLazyBoolCalculate; } -void -ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial, addr_t dispatch_queue_t, LazyBool associated_with_libdispatch_queue) -{ - m_dispatch_queue_name = queue_name; - m_queue_kind = queue_kind; - m_queue_serial_number = queue_serial; - m_dispatch_queue_t = dispatch_queue_t; - m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; +void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name, + QueueKind queue_kind, uint64_t queue_serial, + addr_t dispatch_queue_t, + LazyBool associated_with_libdispatch_queue) { + m_dispatch_queue_name = queue_name; + m_queue_kind = queue_kind; + m_queue_serial_number = queue_serial; + m_dispatch_queue_t = dispatch_queue_t; + m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; } +const char *ThreadGDBRemote::GetQueueName() { + // If our cached queue info is valid, then someone called + // ThreadGDBRemote::SetQueueInfo(...) + // with valid information that was gleaned from the stop reply packet. In this + // case we trust + // that the info is valid in m_dispatch_queue_name without refetching it + if (CachedQueueInfoIsValid()) { + if (m_dispatch_queue_name.empty()) + return nullptr; + else + return m_dispatch_queue_name.c_str(); + } + // Always re-fetch the dispatch queue name since it can change -const char * -ThreadGDBRemote::GetQueueName () -{ - // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...) - // with valid information that was gleaned from the stop reply packet. In this case we trust - // that the info is valid in m_dispatch_queue_name without refetching it - if (CachedQueueInfoIsValid()) - { - if (m_dispatch_queue_name.empty()) - return nullptr; - else - return m_dispatch_queue_name.c_str(); - } - // Always re-fetch the dispatch queue name since it can change - - if (m_associated_with_libdispatch_queue == eLazyBoolNo) - return nullptr; - - if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SystemRuntime *runtime = process_sp->GetSystemRuntime (); - if (runtime) - m_dispatch_queue_name = runtime->GetQueueNameFromThreadQAddress (m_thread_dispatch_qaddr); - else - m_dispatch_queue_name.clear(); - - if (!m_dispatch_queue_name.empty()) - return m_dispatch_queue_name.c_str(); - } + if (m_associated_with_libdispatch_queue == eLazyBoolNo) + return nullptr; + + if (m_thread_dispatch_qaddr != 0 && + m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + if (runtime) + m_dispatch_queue_name = + runtime->GetQueueNameFromThreadQAddress(m_thread_dispatch_qaddr); + else + m_dispatch_queue_name.clear(); + + if (!m_dispatch_queue_name.empty()) + return m_dispatch_queue_name.c_str(); } - return NULL; + } + return NULL; } -QueueKind -ThreadGDBRemote::GetQueueKind () -{ - // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...) - // with valid information that was gleaned from the stop reply packet. In this case we trust - // that the info is valid in m_dispatch_queue_name without refetching it - if (CachedQueueInfoIsValid()) - { - return m_queue_kind; - } +QueueKind ThreadGDBRemote::GetQueueKind() { + // If our cached queue info is valid, then someone called + // ThreadGDBRemote::SetQueueInfo(...) + // with valid information that was gleaned from the stop reply packet. In this + // case we trust + // that the info is valid in m_dispatch_queue_name without refetching it + if (CachedQueueInfoIsValid()) { + return m_queue_kind; + } + + if (m_associated_with_libdispatch_queue == eLazyBoolNo) + return eQueueKindUnknown; - if (m_associated_with_libdispatch_queue == eLazyBoolNo) - return eQueueKindUnknown; - - if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SystemRuntime *runtime = process_sp->GetSystemRuntime (); - if (runtime) - m_queue_kind = runtime->GetQueueKind (m_thread_dispatch_qaddr); - return m_queue_kind; - } + if (m_thread_dispatch_qaddr != 0 && + m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + if (runtime) + m_queue_kind = runtime->GetQueueKind(m_thread_dispatch_qaddr); + return m_queue_kind; } - return eQueueKindUnknown; + } + return eQueueKindUnknown; } +queue_id_t ThreadGDBRemote::GetQueueID() { + // If our cached queue info is valid, then someone called + // ThreadGDBRemote::SetQueueInfo(...) + // with valid information that was gleaned from the stop reply packet. In this + // case we trust + // that the info is valid in m_dispatch_queue_name without refetching it + if (CachedQueueInfoIsValid()) + return m_queue_serial_number; -queue_id_t -ThreadGDBRemote::GetQueueID () -{ - // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...) - // with valid information that was gleaned from the stop reply packet. In this case we trust - // that the info is valid in m_dispatch_queue_name without refetching it - if (CachedQueueInfoIsValid()) - return m_queue_serial_number; - - if (m_associated_with_libdispatch_queue == eLazyBoolNo) - return LLDB_INVALID_QUEUE_ID; - - if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SystemRuntime *runtime = process_sp->GetSystemRuntime (); - if (runtime) - { - return runtime->GetQueueIDFromThreadQAddress (m_thread_dispatch_qaddr); - } - } - } + if (m_associated_with_libdispatch_queue == eLazyBoolNo) return LLDB_INVALID_QUEUE_ID; + + if (m_thread_dispatch_qaddr != 0 && + m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + if (runtime) { + return runtime->GetQueueIDFromThreadQAddress(m_thread_dispatch_qaddr); + } + } + } + return LLDB_INVALID_QUEUE_ID; } -QueueSP -ThreadGDBRemote::GetQueue () -{ - queue_id_t queue_id = GetQueueID(); - QueueSP queue; - if (queue_id != LLDB_INVALID_QUEUE_ID) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - queue = process_sp->GetQueueList().FindQueueByID (queue_id); - } +QueueSP ThreadGDBRemote::GetQueue() { + queue_id_t queue_id = GetQueueID(); + QueueSP queue; + if (queue_id != LLDB_INVALID_QUEUE_ID) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + queue = process_sp->GetQueueList().FindQueueByID(queue_id); } - return queue; + } + return queue; } -addr_t -ThreadGDBRemote::GetQueueLibdispatchQueueAddress () -{ - if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS) - { - if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SystemRuntime *runtime = process_sp->GetSystemRuntime (); - if (runtime) - { - m_dispatch_queue_t = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr); - } - } +addr_t ThreadGDBRemote::GetQueueLibdispatchQueueAddress() { + if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS) { + if (m_thread_dispatch_qaddr != 0 && + m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + if (runtime) { + m_dispatch_queue_t = + runtime->GetLibdispatchQueueAddressFromThreadQAddress( + m_thread_dispatch_qaddr); } + } } - return m_dispatch_queue_t; + } + return m_dispatch_queue_t; } -void -ThreadGDBRemote::SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) -{ - m_dispatch_queue_t = dispatch_queue_t; +void ThreadGDBRemote::SetQueueLibdispatchQueueAddress( + lldb::addr_t dispatch_queue_t) { + m_dispatch_queue_t = dispatch_queue_t; } -bool -ThreadGDBRemote::ThreadHasQueueInformation () const -{ - if (m_thread_dispatch_qaddr != 0 - && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS - && m_dispatch_queue_t != LLDB_INVALID_ADDRESS - && m_queue_kind != eQueueKindUnknown - && m_queue_serial_number != 0) - { - return true; - } - return false; +bool ThreadGDBRemote::ThreadHasQueueInformation() const { + if (m_thread_dispatch_qaddr != 0 && + m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS && + m_dispatch_queue_t != LLDB_INVALID_ADDRESS && + m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0) { + return true; + } + return false; } -LazyBool -ThreadGDBRemote::GetAssociatedWithLibdispatchQueue () -{ - return m_associated_with_libdispatch_queue; +LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() { + return m_associated_with_libdispatch_queue; } -void -ThreadGDBRemote::SetAssociatedWithLibdispatchQueue (LazyBool associated_with_libdispatch_queue) -{ - m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; +void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue( + LazyBool associated_with_libdispatch_queue) { + m_associated_with_libdispatch_queue = associated_with_libdispatch_queue; } -StructuredData::ObjectSP -ThreadGDBRemote::FetchThreadExtendedInfo () -{ - StructuredData::ObjectSP object_sp; - const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD)); - if (log) - log->Printf ("Fetching extended information for thread %4.4" PRIx64, tid); - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - object_sp = gdb_process->GetExtendedInfoForThread (tid); - } - return object_sp; +StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { + StructuredData::ObjectSP object_sp; + const lldb::user_id_t tid = GetProtocolID(); + Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + if (log) + log->Printf("Fetching extended information for thread %4.4" PRIx64, tid); + ProcessSP process_sp(GetProcess()); + if (process_sp) { + ProcessGDBRemote *gdb_process = + static_cast<ProcessGDBRemote *>(process_sp.get()); + object_sp = gdb_process->GetExtendedInfoForThread(tid); + } + return object_sp; } -void -ThreadGDBRemote::WillResume (StateType resume_state) -{ - int signo = GetResumeSignal(); - const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD)); - if (log) - log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state)); - - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - switch (resume_state) - { - case eStateSuspended: - case eStateStopped: - // Don't append anything for threads that should stay stopped. - break; - - case eStateRunning: - if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) - gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo)); - else - gdb_process->m_continue_c_tids.push_back(tid); - break; - - case eStateStepping: - if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) - gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo)); - else - gdb_process->m_continue_s_tids.push_back(tid); - break; - - default: - break; - } +void ThreadGDBRemote::WillResume(StateType resume_state) { + int signo = GetResumeSignal(); + const lldb::user_id_t tid = GetProtocolID(); + Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + if (log) + log->Printf("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, + StateAsCString(resume_state)); + + ProcessSP process_sp(GetProcess()); + if (process_sp) { + ProcessGDBRemote *gdb_process = + static_cast<ProcessGDBRemote *>(process_sp.get()); + switch (resume_state) { + case eStateSuspended: + case eStateStopped: + // Don't append anything for threads that should stay stopped. + break; + + case eStateRunning: + if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) + gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo)); + else + gdb_process->m_continue_c_tids.push_back(tid); + break; + + case eStateStepping: + if (gdb_process->GetUnixSignals()->SignalIsValid(signo)) + gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo)); + else + gdb_process->m_continue_s_tids.push_back(tid); + break; + + default: + break; } + } } -void -ThreadGDBRemote::RefreshStateAfterStop() -{ - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The GDBRemoteRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do - // the right thing. - const bool force = false; - GetRegisterContext()->InvalidateIfNeeded (force); -} - -bool -ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread) -{ - return thread != 0; +void ThreadGDBRemote::RefreshStateAfterStop() { + // Invalidate all registers in our register context. We don't set "force" to + // true because the stop reply packet might have had some register values + // that were expedited and these will already be copied into the register + // context by the time this function gets called. The GDBRemoteRegisterContext + // class has been made smart enough to detect when it needs to invalidate + // which registers are valid by putting hooks in the register read and + // register supply functions where they check the process stop ID and do + // the right thing. + const bool force = false; + GetRegisterContext()->InvalidateIfNeeded(force); } -void -ThreadGDBRemote::Dump(Log *log, uint32_t index) -{ +bool ThreadGDBRemote::ThreadIDIsValid(lldb::tid_t thread) { + return thread != 0; } +void ThreadGDBRemote::Dump(Log *log, uint32_t index) {} -bool -ThreadGDBRemote::ShouldStop (bool &step_more) -{ - return true; -} -lldb::RegisterContextSP -ThreadGDBRemote::GetRegisterContext () -{ - if (m_reg_context_sp.get() == NULL) - m_reg_context_sp = CreateRegisterContextForFrame (NULL); - return m_reg_context_sp; +bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; } +lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() { + if (m_reg_context_sp.get() == NULL) + m_reg_context_sp = CreateRegisterContextForFrame(NULL); + return m_reg_context_sp; } lldb::RegisterContextSP -ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex (); - - - if (concrete_frame_idx == 0) - { - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get()); - // read_all_registers_at_once will be true if 'p' packet is not supported. - bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID()); - reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once)); - } - } - else - { - Unwind *unwinder = GetUnwinder (); - if (unwinder) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame); +ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + ProcessGDBRemote *gdb_process = + static_cast<ProcessGDBRemote *>(process_sp.get()); + // read_all_registers_at_once will be true if 'p' packet is not supported. + bool read_all_registers_at_once = + !gdb_process->GetGDBRemote().GetpPacketSupported(GetID()); + reg_ctx_sp.reset(new GDBRemoteRegisterContext( + *this, concrete_frame_idx, gdb_process->m_register_info, + read_all_registers_at_once)); } - return reg_ctx_sp; + } else { + Unwind *unwinder = GetUnwinder(); + if (unwinder) + reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; } -bool -ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data) -{ - GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get()); - assert (gdb_reg_ctx); - return gdb_reg_ctx->PrivateSetRegisterValue(reg, data); +bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, + llvm::ArrayRef<uint8_t> data) { + GDBRemoteRegisterContext *gdb_reg_ctx = + static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get()); + assert(gdb_reg_ctx); + return gdb_reg_ctx->PrivateSetRegisterValue(reg, data); } -bool -ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval) -{ - GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get()); - assert (gdb_reg_ctx); - return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval); +bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, uint64_t regval) { + GDBRemoteRegisterContext *gdb_reg_ctx = + static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get()); + assert(gdb_reg_ctx); + return gdb_reg_ctx->PrivateSetRegisterValue(reg, regval); } -bool -ThreadGDBRemote::CalculateStopInfo () -{ - ProcessSP process_sp (GetProcess()); - if (process_sp) - return static_cast<ProcessGDBRemote *>(process_sp.get())->CalculateThreadStopInfo(this); - return false; +bool ThreadGDBRemote::CalculateStopInfo() { + ProcessSP process_sp(GetProcess()); + if (process_sp) + return static_cast<ProcessGDBRemote *>(process_sp.get()) + ->CalculateThreadStopInfo(this); + return false; } - - diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index d4520427269..27caf42fc4a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -27,125 +27,94 @@ namespace process_gdb_remote { class ProcessGDBRemote; -class ThreadGDBRemote : public Thread -{ +class ThreadGDBRemote : public Thread { public: - ThreadGDBRemote (Process &process, lldb::tid_t tid); + ThreadGDBRemote(Process &process, lldb::tid_t tid); - ~ThreadGDBRemote() override; + ~ThreadGDBRemote() override; - void - WillResume (lldb::StateType resume_state) override; + void WillResume(lldb::StateType resume_state) override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - const char * - GetName () override; + const char *GetName() override; - const char * - GetQueueName () override; + const char *GetQueueName() override; - lldb::QueueKind - GetQueueKind () override; + lldb::QueueKind GetQueueKind() override; - lldb::queue_id_t - GetQueueID () override; + lldb::queue_id_t GetQueueID() override; - lldb::QueueSP - GetQueue () override; + lldb::QueueSP GetQueue() override; - lldb::addr_t - GetQueueLibdispatchQueueAddress () override; + lldb::addr_t GetQueueLibdispatchQueueAddress() override; - void - SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) override; + void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override; - bool - ThreadHasQueueInformation () const override; + bool ThreadHasQueueInformation() const override; - lldb::RegisterContextSP - GetRegisterContext () override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame (StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; - void - Dump (Log *log, uint32_t index); + void Dump(Log *log, uint32_t index); - static bool - ThreadIDIsValid (lldb::tid_t thread); + static bool ThreadIDIsValid(lldb::tid_t thread); - bool - ShouldStop (bool &step_more); + bool ShouldStop(bool &step_more); - const char * - GetBasicInfoAsString (); + const char *GetBasicInfoAsString(); - void - SetName (const char *name) override - { - if (name && name[0]) - m_thread_name.assign (name); - else - m_thread_name.clear(); - } + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } - lldb::addr_t - GetThreadDispatchQAddr () - { - return m_thread_dispatch_qaddr; - } + lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; } - void - SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr) - { - m_thread_dispatch_qaddr = thread_dispatch_qaddr; - } + void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) { + m_thread_dispatch_qaddr = thread_dispatch_qaddr; + } - void - ClearQueueInfo (); - - void - SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial, lldb::addr_t dispatch_queue_t, lldb_private::LazyBool associated_with_libdispatch_queue); + void ClearQueueInfo(); - lldb_private::LazyBool - GetAssociatedWithLibdispatchQueue () override; + void SetQueueInfo(std::string &&queue_name, lldb::QueueKind queue_kind, + uint64_t queue_serial, lldb::addr_t dispatch_queue_t, + lldb_private::LazyBool associated_with_libdispatch_queue); - void - SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) override; + lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override; - StructuredData::ObjectSP - FetchThreadExtendedInfo () override; + void SetAssociatedWithLibdispatchQueue( + lldb_private::LazyBool associated_with_libdispatch_queue) override; + + StructuredData::ObjectSP FetchThreadExtendedInfo() override; protected: - friend class ProcessGDBRemote; - - std::string m_thread_name; - std::string m_dispatch_queue_name; - lldb::addr_t m_thread_dispatch_qaddr; - lldb::addr_t m_dispatch_queue_t; - lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread - uint64_t m_queue_serial_number; // Queue info from stop reply/stop info for thread - lldb_private::LazyBool m_associated_with_libdispatch_queue; - - bool - PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data); - - bool - PrivateSetRegisterValue (uint32_t reg, - uint64_t regval); - - bool - CachedQueueInfoIsValid() const - { - return m_queue_kind != lldb::eQueueKindUnknown; - } - void - SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id); - - bool - CalculateStopInfo () override; + friend class ProcessGDBRemote; + + std::string m_thread_name; + std::string m_dispatch_queue_name; + lldb::addr_t m_thread_dispatch_qaddr; + lldb::addr_t m_dispatch_queue_t; + lldb::QueueKind + m_queue_kind; // Queue info from stop reply/stop info for thread + uint64_t + m_queue_serial_number; // Queue info from stop reply/stop info for thread + lldb_private::LazyBool m_associated_with_libdispatch_queue; + + bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data); + + bool PrivateSetRegisterValue(uint32_t reg, uint64_t regval); + + bool CachedQueueInfoIsValid() const { + return m_queue_kind != lldb::eQueueKindUnknown; + } + void SetStopInfoFromPacket(StringExtractor &stop_packet, uint32_t stop_id); + + bool CalculateStopInfo() override; }; } // namespace process_gdb_remote diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index d2f50ba6c54..f83499cdb23 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -1,4 +1,5 @@ -//===-- ProcessMachCore.cpp ------------------------------------------*- C++ -*-===// +//===-- ProcessMachCore.cpp ------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -32,639 +33,576 @@ // Project includes #include "ProcessMachCore.h" -#include "ThreadMachCore.h" #include "StopInfoMachException.h" +#include "ThreadMachCore.h" // Needed for the plug-in names for the dynamic loaders. #include "lldb/Utility/SafeMachO.h" -#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" +#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" using namespace lldb; using namespace lldb_private; -ConstString -ProcessMachCore::GetPluginNameStatic() -{ - static ConstString g_name("mach-o-core"); - return g_name; +ConstString ProcessMachCore::GetPluginNameStatic() { + static ConstString g_name("mach-o-core"); + return g_name; } -const char * -ProcessMachCore::GetPluginDescriptionStatic() -{ - return "Mach-O core file debugging plug-in."; +const char *ProcessMachCore::GetPluginDescriptionStatic() { + return "Mach-O core file debugging plug-in."; } -void -ProcessMachCore::Terminate() -{ - PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance); +void ProcessMachCore::Terminate() { + PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance); } - -lldb::ProcessSP -ProcessMachCore::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file) -{ - lldb::ProcessSP process_sp; - if (crash_file) - { - const size_t header_size = sizeof(llvm::MachO::mach_header); - lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size)); - if (data_sp && data_sp->GetByteSize() == header_size) - { - DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); - - lldb::offset_t data_offset = 0; - llvm::MachO::mach_header mach_header; - if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) - { - if (mach_header.filetype == llvm::MachO::MH_CORE) - process_sp.reset(new ProcessMachCore (target_sp, listener_sp, *crash_file)); - } - } - +lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec *crash_file) { + lldb::ProcessSP process_sp; + if (crash_file) { + const size_t header_size = sizeof(llvm::MachO::mach_header); + lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size)); + if (data_sp && data_sp->GetByteSize() == header_size) { + DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); + + lldb::offset_t data_offset = 0; + llvm::MachO::mach_header mach_header; + if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) { + if (mach_header.filetype == llvm::MachO::MH_CORE) + process_sp.reset( + new ProcessMachCore(target_sp, listener_sp, *crash_file)); + } } - return process_sp; + } + return process_sp; } -bool -ProcessMachCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - if (plugin_specified_by_name) - return true; +bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + if (plugin_specified_by_name) + return true; - // For now we are just making sure the file exists for a given module - if (!m_core_module_sp && m_core_file.Exists()) - { - // Don't add the Target's architecture to the ModuleSpec - we may be working - // with a core file that doesn't have the correct cpusubtype in the header - // but we should still try to use it - ModuleSpecList::FindMatchingModuleSpec - // enforces a strict arch mach. - ModuleSpec core_module_spec(m_core_file); - Error error (ModuleList::GetSharedModule (core_module_spec, - m_core_module_sp, - NULL, - NULL, - NULL)); - - if (m_core_module_sp) - { - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) - return true; - } + // For now we are just making sure the file exists for a given module + if (!m_core_module_sp && m_core_file.Exists()) { + // Don't add the Target's architecture to the ModuleSpec - we may be working + // with a core file that doesn't have the correct cpusubtype in the header + // but we should still try to use it - + // ModuleSpecList::FindMatchingModuleSpec + // enforces a strict arch mach. + ModuleSpec core_module_spec(m_core_file); + Error error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, + NULL, NULL, NULL)); + + if (m_core_module_sp) { + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) + return true; } - return false; + } + return false; } //---------------------------------------------------------------------- // ProcessMachCore constructor //---------------------------------------------------------------------- -ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec &core_file) - : Process(target_sp, listener_sp), - m_core_aranges(), - m_core_range_infos(), - m_core_module_sp(), - m_core_file(core_file), +ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec &core_file) + : Process(target_sp, listener_sp), m_core_aranges(), m_core_range_infos(), + m_core_module_sp(), m_core_file(core_file), m_dyld_addr(LLDB_INVALID_ADDRESS), - m_mach_kernel_addr(LLDB_INVALID_ADDRESS), - m_dyld_plugin_name() -{ -} + m_mach_kernel_addr(LLDB_INVALID_ADDRESS), m_dyld_plugin_name() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ProcessMachCore::~ProcessMachCore() -{ - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); +ProcessMachCore::~ProcessMachCore() { + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); } //---------------------------------------------------------------------- // PluginInterface //---------------------------------------------------------------------- -ConstString -ProcessMachCore::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessMachCore::GetPluginVersion() -{ - return 1; -} +ConstString ProcessMachCore::GetPluginName() { return GetPluginNameStatic(); } -bool -ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS)); - llvm::MachO::mach_header header; - Error error; - if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header)) - return false; - if (header.magic == llvm::MachO::MH_CIGAM || - header.magic == llvm::MachO::MH_CIGAM_64) - { - header.magic = llvm::ByteSwap_32(header.magic); - header.cputype = llvm::ByteSwap_32(header.cputype); - header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); - header.filetype = llvm::ByteSwap_32(header.filetype); - header.ncmds = llvm::ByteSwap_32(header.ncmds); - header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); - header.flags = llvm::ByteSwap_32(header.flags); - } +uint32_t ProcessMachCore::GetPluginVersion() { return 1; } - // TODO: swap header if needed... - //printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr, header.magic, header.filetype); - if (header.magic == llvm::MachO::MH_MAGIC || - header.magic == llvm::MachO::MH_MAGIC_64) - { - // Check MH_EXECUTABLE to see if we can find the mach image - // that contains the shared library list. The dynamic loader - // (dyld) is what contains the list for user applications, - // and the mach kernel contains a global that has the list - // of kexts to load - switch (header.filetype) - { - case llvm::MachO::MH_DYLINKER: - //printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr); - // Address of dyld "struct mach_header" in the core file - if (log) - log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a user process dyld binary image at 0x%" PRIx64, addr); - m_dyld_addr = addr; - return true; - - case llvm::MachO::MH_EXECUTE: - //printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr); - // Check MH_EXECUTABLE file types to see if the dynamic link object flag - // is NOT set. If it isn't, then we have a mach_kernel. - if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) - { - if (log) - log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a mach kernel binary image at 0x%" PRIx64, addr); - // Address of the mach kernel "struct mach_header" in the core file. - m_mach_kernel_addr = addr; - return true; - } - break; - } - } +bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER | + LIBLLDB_LOG_PROCESS)); + llvm::MachO::mach_header header; + Error error; + if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header)) return false; + if (header.magic == llvm::MachO::MH_CIGAM || + header.magic == llvm::MachO::MH_CIGAM_64) { + header.magic = llvm::ByteSwap_32(header.magic); + header.cputype = llvm::ByteSwap_32(header.cputype); + header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); + header.filetype = llvm::ByteSwap_32(header.filetype); + header.ncmds = llvm::ByteSwap_32(header.ncmds); + header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); + header.flags = llvm::ByteSwap_32(header.flags); + } + + // TODO: swap header if needed... + // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr, + // header.magic, header.filetype); + if (header.magic == llvm::MachO::MH_MAGIC || + header.magic == llvm::MachO::MH_MAGIC_64) { + // Check MH_EXECUTABLE to see if we can find the mach image + // that contains the shared library list. The dynamic loader + // (dyld) is what contains the list for user applications, + // and the mach kernel contains a global that has the list + // of kexts to load + switch (header.filetype) { + case llvm::MachO::MH_DYLINKER: + // printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr); + // Address of dyld "struct mach_header" in the core file + if (log) + log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a user " + "process dyld binary image at 0x%" PRIx64, + addr); + m_dyld_addr = addr; + return true; + + case llvm::MachO::MH_EXECUTE: + // printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr); + // Check MH_EXECUTABLE file types to see if the dynamic link object flag + // is NOT set. If it isn't, then we have a mach_kernel. + if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) { + if (log) + log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a mach " + "kernel binary image at 0x%" PRIx64, + addr); + // Address of the mach kernel "struct mach_header" in the core file. + m_mach_kernel_addr = addr; + return true; + } + break; + } + } + return false; } //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- -Error -ProcessMachCore::DoLoadCore () -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS)); - Error error; - if (!m_core_module_sp) - { - error.SetErrorString ("invalid core module"); - return error; - } - - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile == NULL) - { - error.SetErrorString ("invalid core object file"); - return error; - } - - if (core_objfile->GetNumThreadContexts() == 0) - { - error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb"); - return error; - } +Error ProcessMachCore::DoLoadCore() { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER | + LIBLLDB_LOG_PROCESS)); + Error error; + if (!m_core_module_sp) { + error.SetErrorString("invalid core module"); + return error; + } - SectionList *section_list = core_objfile->GetSectionList(); - if (section_list == NULL) - { - error.SetErrorString ("core file has no sections"); - return error; - } - - const uint32_t num_sections = section_list->GetNumSections(0); - if (num_sections == 0) - { - error.SetErrorString ("core file has no sections"); - return error; - } - - SetCanJIT(false); - - llvm::MachO::mach_header header; - DataExtractor data (&header, - sizeof(header), - m_core_module_sp->GetArchitecture().GetByteOrder(), - m_core_module_sp->GetArchitecture().GetAddressByteSize()); - - bool ranges_are_sorted = true; - addr_t vm_addr = 0; - for (uint32_t i=0; i<num_sections; ++i) - { - Section *section = section_list->GetSectionAtIndex (i).get(); - if (section) - { - lldb::addr_t section_vm_addr = section->GetFileAddress(); - FileRange file_range (section->GetFileOffset(), section->GetFileSize()); - VMRangeToFileOffset::Entry range_entry (section_vm_addr, - section->GetByteSize(), - file_range); - - if (vm_addr > section_vm_addr) - ranges_are_sorted = false; - vm_addr = section->GetFileAddress(); - VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); -// printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", -// i, -// range_entry.GetRangeBase(), -// range_entry.GetRangeEnd(), -// range_entry.data.GetRangeBase(), -// range_entry.data.GetRangeEnd()); - - if (last_entry && - last_entry->GetRangeEnd() == range_entry.GetRangeBase() && - last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) - { - last_entry->SetRangeEnd (range_entry.GetRangeEnd()); - last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd()); - //puts("combine"); - } - else - { - m_core_aranges.Append(range_entry); - } - // Some core files don't fill in the permissions correctly. If that is the case - // assume read + execute so clients don't think the memory is not readable, - // or executable. The memory isn't writable since this plug-in doesn't implement - // DoWriteMemory. - uint32_t permissions = section->GetPermissions(); - if (permissions == 0) - permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; - m_core_range_infos.Append( - VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), permissions)); - } - } - if (!ranges_are_sorted) - { - m_core_aranges.Sort(); - m_core_range_infos.Sort(); - } + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + if (core_objfile == NULL) { + error.SetErrorString("invalid core object file"); + return error; + } - if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS) - { - // We need to locate the main executable in the memory ranges - // we have in the core file. We need to search for both a user-process dyld binary - // and a kernel binary in memory; we must look at all the pages in the binary so - // we don't miss one or the other. Step through all memory segments searching for - // a kernel binary and for a user process dyld -- we'll decide which to prefer - // later if both are present. - - const size_t num_core_aranges = m_core_aranges.GetSize(); - for (size_t i = 0; i < num_core_aranges; ++i) - { - const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i); - lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); - lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); - for (lldb::addr_t section_vm_addr = section_vm_addr_start; - section_vm_addr < section_vm_addr_end; - section_vm_addr += 0x1000) - { - GetDynamicLoaderAddress (section_vm_addr); - } - } - } + if (core_objfile->GetNumThreadContexts() == 0) { + error.SetErrorString("core file doesn't contain any LC_THREAD load " + "commands, or the LC_THREAD architecture is not " + "supported in this lldb"); + return error; + } + SectionList *section_list = core_objfile->GetSectionList(); + if (section_list == NULL) { + error.SetErrorString("core file has no sections"); + return error; + } - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) - { - // In the case of multiple kernel images found in the core file via exhaustive - // search, we may not pick the correct one. See if the DynamicLoaderDarwinKernel's - // search heuristics might identify the correct one. - // Most of the time, I expect the address from SearchForDarwinKernel() will be the - // same as the address we found via exhaustive search. - - if (GetTarget().GetArchitecture().IsValid() == false && m_core_module_sp.get()) - { - GetTarget().SetArchitecture (m_core_module_sp->GetArchitecture()); - } - - // SearchForDarwinKernel will end up calling back into this this class in the GetImageInfoAddress - // method which will give it the m_mach_kernel_addr/m_dyld_addr it already has. Save that aside - // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so - // DynamicLoaderDarwinKernel does a real search for the kernel using its own heuristics. - - addr_t saved_mach_kernel_addr = m_mach_kernel_addr; - addr_t saved_user_dyld_addr = m_dyld_addr; - m_mach_kernel_addr = LLDB_INVALID_ADDRESS; - m_dyld_addr = LLDB_INVALID_ADDRESS; - - addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this); - - m_mach_kernel_addr = saved_mach_kernel_addr; - m_dyld_addr = saved_user_dyld_addr; - - if (better_kernel_address != LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: Using the kernel address from DynamicLoaderDarwinKernel"); - m_mach_kernel_addr = better_kernel_address; - } + const uint32_t num_sections = section_list->GetNumSections(0); + if (num_sections == 0) { + error.SetErrorString("core file has no sections"); + return error; + } + + SetCanJIT(false); + + llvm::MachO::mach_header header; + DataExtractor data(&header, sizeof(header), + m_core_module_sp->GetArchitecture().GetByteOrder(), + m_core_module_sp->GetArchitecture().GetAddressByteSize()); + + bool ranges_are_sorted = true; + addr_t vm_addr = 0; + for (uint32_t i = 0; i < num_sections; ++i) { + Section *section = section_list->GetSectionAtIndex(i).get(); + if (section) { + lldb::addr_t section_vm_addr = section->GetFileAddress(); + FileRange file_range(section->GetFileOffset(), section->GetFileSize()); + VMRangeToFileOffset::Entry range_entry( + section_vm_addr, section->GetByteSize(), file_range); + + if (vm_addr > section_vm_addr) + ranges_are_sorted = false; + vm_addr = section->GetFileAddress(); + VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); + // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - + // 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", + // i, + // range_entry.GetRangeBase(), + // range_entry.GetRangeEnd(), + // range_entry.data.GetRangeBase(), + // range_entry.data.GetRangeEnd()); + + if (last_entry && + last_entry->GetRangeEnd() == range_entry.GetRangeBase() && + last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { + last_entry->SetRangeEnd(range_entry.GetRangeEnd()); + last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); + // puts("combine"); + } else { + m_core_aranges.Append(range_entry); + } + // Some core files don't fill in the permissions correctly. If that is the + // case + // assume read + execute so clients don't think the memory is not + // readable, + // or executable. The memory isn't writable since this plug-in doesn't + // implement + // DoWriteMemory. + uint32_t permissions = section->GetPermissions(); + if (permissions == 0) + permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; + m_core_range_infos.Append(VMRangeToPermissions::Entry( + section_vm_addr, section->GetByteSize(), permissions)); } - - - // If we found both a user-process dyld and a kernel binary, we need to decide - // which to prefer. - if (GetCorefilePreference() == eKernelCorefile) - { - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); - } - else if (m_dyld_addr != LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); - m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); - } + } + if (!ranges_are_sorted) { + m_core_aranges.Sort(); + m_core_range_infos.Sort(); + } + + if (m_dyld_addr == LLDB_INVALID_ADDRESS || + m_mach_kernel_addr == LLDB_INVALID_ADDRESS) { + // We need to locate the main executable in the memory ranges + // we have in the core file. We need to search for both a user-process dyld + // binary + // and a kernel binary in memory; we must look at all the pages in the + // binary so + // we don't miss one or the other. Step through all memory segments + // searching for + // a kernel binary and for a user process dyld -- we'll decide which to + // prefer + // later if both are present. + + const size_t num_core_aranges = m_core_aranges.GetSize(); + for (size_t i = 0; i < num_core_aranges; ++i) { + const VMRangeToFileOffset::Entry *entry = + m_core_aranges.GetEntryAtIndex(i); + lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); + lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); + for (lldb::addr_t section_vm_addr = section_vm_addr_start; + section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) { + GetDynamicLoaderAddress(section_vm_addr); + } } - else - { - if (m_dyld_addr != LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); - m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); - } - else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); - } + } + + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + // In the case of multiple kernel images found in the core file via + // exhaustive + // search, we may not pick the correct one. See if the + // DynamicLoaderDarwinKernel's + // search heuristics might identify the correct one. + // Most of the time, I expect the address from SearchForDarwinKernel() will + // be the + // same as the address we found via exhaustive search. + + if (GetTarget().GetArchitecture().IsValid() == false && + m_core_module_sp.get()) { + GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture()); } - if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) - { - // For non-user process core files, the permissions on the core file segments are usually - // meaningless, they may be just "read", because we're dealing with kernel coredumps or - // early startup coredumps and the dumper is grabbing pages of memory without knowing - // what they are. If they aren't marked as "exeuctable", that can break the unwinder - // which will check a pc value to see if it is in an executable segment and stop the - // backtrace early if it is not ("executable" and "unknown" would both be fine, but - // "not executable" will break the unwinder). - size_t core_range_infos_size = m_core_range_infos.GetSize(); - for (size_t i = 0; i < core_range_infos_size; i++) - { - VMRangeToPermissions::Entry *ent = m_core_range_infos.GetMutableEntryAtIndex (i); - ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; - } + // SearchForDarwinKernel will end up calling back into this this class in + // the GetImageInfoAddress + // method which will give it the m_mach_kernel_addr/m_dyld_addr it already + // has. Save that aside + // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily + // so + // DynamicLoaderDarwinKernel does a real search for the kernel using its own + // heuristics. + + addr_t saved_mach_kernel_addr = m_mach_kernel_addr; + addr_t saved_user_dyld_addr = m_dyld_addr; + m_mach_kernel_addr = LLDB_INVALID_ADDRESS; + m_dyld_addr = LLDB_INVALID_ADDRESS; + + addr_t better_kernel_address = + DynamicLoaderDarwinKernel::SearchForDarwinKernel(this); + + m_mach_kernel_addr = saved_mach_kernel_addr; + m_dyld_addr = saved_user_dyld_addr; + + if (better_kernel_address != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address " + "from DynamicLoaderDarwinKernel"); + m_mach_kernel_addr = better_kernel_address; } - - // Even if the architecture is set in the target, we need to override - // it to match the core file which is always single arch. - ArchSpec arch (m_core_module_sp->GetArchitecture()); - if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) - { - arch.SetTriple ("i386", GetTarget().GetPlatform().get()); + } + + // If we found both a user-process dyld and a kernel binary, we need to decide + // which to prefer. + if (GetCorefilePreference() == eKernelCorefile) { + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image " + "at 0x%" PRIx64, + m_mach_kernel_addr); + m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); + } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld " + "image at 0x%" PRIx64, + m_dyld_addr); + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } - if (arch.IsValid()) - GetTarget().SetArchitecture(arch); - - return error; + } else { + if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld " + "image at 0x%" PRIx64, + m_dyld_addr); + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image " + "at 0x%" PRIx64, + m_mach_kernel_addr); + m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); + } + } + + if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) { + // For non-user process core files, the permissions on the core file + // segments are usually + // meaningless, they may be just "read", because we're dealing with kernel + // coredumps or + // early startup coredumps and the dumper is grabbing pages of memory + // without knowing + // what they are. If they aren't marked as "exeuctable", that can break the + // unwinder + // which will check a pc value to see if it is in an executable segment and + // stop the + // backtrace early if it is not ("executable" and "unknown" would both be + // fine, but + // "not executable" will break the unwinder). + size_t core_range_infos_size = m_core_range_infos.GetSize(); + for (size_t i = 0; i < core_range_infos_size; i++) { + VMRangeToPermissions::Entry *ent = + m_core_range_infos.GetMutableEntryAtIndex(i); + ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; + } + } + + // Even if the architecture is set in the target, we need to override + // it to match the core file which is always single arch. + ArchSpec arch(m_core_module_sp->GetArchitecture()); + if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { + arch.SetTriple("i386", GetTarget().GetPlatform().get()); + } + if (arch.IsValid()) + GetTarget().SetArchitecture(arch); + + return error; } -lldb_private::DynamicLoader * -ProcessMachCore::GetDynamicLoader () -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); - return m_dyld_ap.get(); +lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin( + this, + m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); + return m_dyld_ap.get(); } -bool -ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - if (old_thread_list.GetSize(false) == 0) - { - // Make up the thread the first time this is called so we can setup our one and only - // core thread state. - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - - if (core_objfile) - { - const uint32_t num_threads = core_objfile->GetNumThreadContexts (); - for (lldb::tid_t tid = 0; tid < num_threads; ++tid) - { - ThreadSP thread_sp(new ThreadMachCore (*this, tid)); - new_thread_list.AddThread (thread_sp); - } - } - } - else - { - const uint32_t num_threads = old_thread_list.GetSize(false); - for (uint32_t i=0; i<num_threads; ++i) - new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i, false)); +bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + if (old_thread_list.GetSize(false) == 0) { + // Make up the thread the first time this is called so we can setup our one + // and only + // core thread state. + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + + if (core_objfile) { + const uint32_t num_threads = core_objfile->GetNumThreadContexts(); + for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { + ThreadSP thread_sp(new ThreadMachCore(*this, tid)); + new_thread_list.AddThread(thread_sp); + } } - return new_thread_list.GetSize(false) > 0; + } else { + const uint32_t num_threads = old_thread_list.GetSize(false); + for (uint32_t i = 0; i < num_threads; ++i) + new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false)); + } + return new_thread_list.GetSize(false) > 0; } -void -ProcessMachCore::RefreshStateAfterStop () -{ - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - m_thread_list.RefreshStateAfterStop(); - //SetThreadStopInfo (m_last_stop_packet); +void ProcessMachCore::RefreshStateAfterStop() { + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + m_thread_list.RefreshStateAfterStop(); + // SetThreadStopInfo (m_last_stop_packet); } -Error -ProcessMachCore::DoDestroy () -{ - return Error(); -} +Error ProcessMachCore::DoDestroy() { return Error(); } //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ -bool -ProcessMachCore::IsAlive () -{ - return true; -} +bool ProcessMachCore::IsAlive() { return true; } -bool -ProcessMachCore::WarnBeforeDetach () const -{ - return false; -} +bool ProcessMachCore::WarnBeforeDetach() const { return false; } //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ -size_t -ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error) -{ - // Don't allow the caching that lldb_private::Process::ReadMemory does - // since in core files we have it all cached our our core file anyway. - return DoReadMemory (addr, buf, size, error); +size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size, + Error &error) { + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since in core files we have it all cached our our core file anyway. + return DoReadMemory(addr, buf, size, error); } -size_t -ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) -{ - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - size_t bytes_read = 0; - - if (core_objfile) - { - //---------------------------------------------------------------------- - // Segments are not always contiguous in mach-o core files. We have core - // files that have segments like: - // Address Size File off File size - // ---------- ---------- ---------- ---------- - // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0 0x00000000 __TEXT - // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0 0x00000000 __TEXT - // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0 0x00000000 __TEXT - // - // Any if the user executes the following command: - // - // (lldb) mem read 0xf6ff0 - // - // We would attempt to read 32 bytes from 0xf6ff0 but would only - // get 16 unless we loop through consecutive memory ranges that are - // contiguous in the address space, but not in the file data. - //---------------------------------------------------------------------- - while (bytes_read < size) - { - const addr_t curr_addr = addr + bytes_read; - const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains(curr_addr); - - if (core_memory_entry) - { - const addr_t offset = curr_addr - core_memory_entry->GetRangeBase(); - const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr; - const size_t bytes_to_read = std::min(size - bytes_read, (size_t)bytes_left); - const size_t curr_bytes_read = core_objfile->CopyData(core_memory_entry->data.GetRangeBase() + offset, - bytes_to_read, (char *)buf + bytes_read); - if (curr_bytes_read == 0) - break; - bytes_read += curr_bytes_read; - } - else - { - // Only set the error if we didn't read any bytes - if (bytes_read == 0) - error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, curr_addr); - break; - } - } +size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size, + Error &error) { + ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + size_t bytes_read = 0; + + if (core_objfile) { + //---------------------------------------------------------------------- + // Segments are not always contiguous in mach-o core files. We have core + // files that have segments like: + // Address Size File off File size + // ---------- ---------- ---------- ---------- + // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0 + // 0x00000000 __TEXT + // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0 + // 0x00000000 __TEXT + // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0 + // 0x00000000 __TEXT + // + // Any if the user executes the following command: + // + // (lldb) mem read 0xf6ff0 + // + // We would attempt to read 32 bytes from 0xf6ff0 but would only + // get 16 unless we loop through consecutive memory ranges that are + // contiguous in the address space, but not in the file data. + //---------------------------------------------------------------------- + while (bytes_read < size) { + const addr_t curr_addr = addr + bytes_read; + const VMRangeToFileOffset::Entry *core_memory_entry = + m_core_aranges.FindEntryThatContains(curr_addr); + + if (core_memory_entry) { + const addr_t offset = curr_addr - core_memory_entry->GetRangeBase(); + const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr; + const size_t bytes_to_read = + std::min(size - bytes_read, (size_t)bytes_left); + const size_t curr_bytes_read = core_objfile->CopyData( + core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, + (char *)buf + bytes_read); + if (curr_bytes_read == 0) + break; + bytes_read += curr_bytes_read; + } else { + // Only set the error if we didn't read any bytes + if (bytes_read == 0) + error.SetErrorStringWithFormat( + "core file does not contain 0x%" PRIx64, curr_addr); + break; + } } + } - return bytes_read; + return bytes_read; } -Error -ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_info) -{ - region_info.Clear(); - const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); - if (permission_entry) - { - if (permission_entry->Contains(load_addr)) - { - region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); - const Flags permissions(permission_entry->data); - region_info.SetReadable(permissions.Test(ePermissionsReadable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetWritable(permissions.Test(ePermissionsWritable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetExecutable(permissions.Test(ePermissionsExecutable) ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eYes); - } - else if (load_addr < permission_entry->GetRangeBase()) - { - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - } - return Error(); +Error ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, + MemoryRegionInfo ®ion_info) { + region_info.Clear(); + const VMRangeToPermissions::Entry *permission_entry = + m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); + if (permission_entry) { + if (permission_entry->Contains(load_addr)) { + region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); + const Flags permissions(permission_entry->data); + region_info.SetReadable(permissions.Test(ePermissionsReadable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetWritable(permissions.Test(ePermissionsWritable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetExecutable(permissions.Test(ePermissionsExecutable) + ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eYes); + } else if (load_addr < permission_entry->GetRangeBase()) { + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } - - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); return Error(); + } + + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + return Error(); } -void -ProcessMachCore::Clear() -{ - m_thread_list.Clear(); -} +void ProcessMachCore::Clear() { m_thread_list.Clear(); } -void -ProcessMachCore::Initialize() -{ - static std::once_flag g_once_flag; +void ProcessMachCore::Initialize() { + static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin (GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - }); + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); } -addr_t -ProcessMachCore::GetImageInfoAddress() -{ - // If we found both a user-process dyld and a kernel binary, we need to decide - // which to prefer. - if (GetCorefilePreference() == eKernelCorefile) - { - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) - { - return m_mach_kernel_addr; - } - return m_dyld_addr; +addr_t ProcessMachCore::GetImageInfoAddress() { + // If we found both a user-process dyld and a kernel binary, we need to decide + // which to prefer. + if (GetCorefilePreference() == eKernelCorefile) { + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + return m_mach_kernel_addr; } - else - { - if (m_dyld_addr != LLDB_INVALID_ADDRESS) - { - return m_dyld_addr; - } - return m_mach_kernel_addr; + return m_dyld_addr; + } else { + if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + return m_dyld_addr; } + return m_mach_kernel_addr; + } } - -lldb_private::ObjectFile * -ProcessMachCore::GetCoreObjectFile () -{ - return m_core_module_sp->GetObjectFile(); +lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() { + return m_core_module_sp->GetObjectFile(); } diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h index 21a0083b2d1..7094eb33110 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -23,147 +23,131 @@ class ThreadKDP; -class ProcessMachCore : public lldb_private::Process -{ +class ProcessMachCore : public lldb_private::Process { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ProcessMachCore(lldb::TargetSP target_sp, - lldb::ListenerSP listener, - const lldb_private::FileSpec &core_file); - - ~ProcessMachCore() override; - - static lldb::ProcessSP - CreateInstance (lldb::TargetSP target_sp, - lldb::ListenerSP listener, - const lldb_private::FileSpec *crash_file_path); - - static void - Initialize(); - - static void - Terminate(); - - static lldb_private::ConstString - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - bool - CanDebug (lldb::TargetSP target_sp, - bool plugin_specified_by_name) override; - - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - lldb_private::Error - DoLoadCore () override; - - lldb_private::DynamicLoader * - GetDynamicLoader () override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString - GetPluginName() override; - - uint32_t - GetPluginVersion() override; - - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - lldb_private::Error - DoDestroy () override; - - void - RefreshStateAfterStop() override; - - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - bool - IsAlive () override; - - bool - WarnBeforeDetach () const override; - - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - size_t - ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; - - size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; - - lldb_private::Error - GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override; - - lldb::addr_t - GetImageInfoAddress () override; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ProcessMachCore(lldb::TargetSP target_sp, lldb::ListenerSP listener, + const lldb_private::FileSpec &core_file); + + ~ProcessMachCore() override; + + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, + const lldb_private::FileSpec *crash_file_path); + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Check if a given Process + //------------------------------------------------------------------ + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + + //------------------------------------------------------------------ + // Creating a new process, or attaching to an existing one + //------------------------------------------------------------------ + lldb_private::Error DoLoadCore() override; + + lldb_private::DynamicLoader *GetDynamicLoader() override; + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + + //------------------------------------------------------------------ + // Process Control + //------------------------------------------------------------------ + lldb_private::Error DoDestroy() override; + + void RefreshStateAfterStop() override; + + //------------------------------------------------------------------ + // Process Queries + //------------------------------------------------------------------ + bool IsAlive() override; + + bool WarnBeforeDetach() const override; + + //------------------------------------------------------------------ + // Process Memory + //------------------------------------------------------------------ + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Error &error) override; + + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo ®ion_info) override; + + lldb::addr_t GetImageInfoAddress() override; protected: - friend class ThreadMachCore; - - void - Clear ( ); - - bool - UpdateThreadList (lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; - - lldb_private::ObjectFile * - GetCoreObjectFile (); + friend class ThreadMachCore; + + void Clear(); + + bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + + lldb_private::ObjectFile *GetCoreObjectFile(); + private: - bool - GetDynamicLoaderAddress (lldb::addr_t addr); - - typedef enum CorefilePreference { eUserProcessCorefile, eKernelCorefile } CorefilePreferences; - - //------------------------------------------------------------------ - /// If a core file can be interpreted multiple ways, this establishes - /// which style wins. - /// - /// If a core file contains both a kernel binary and a user-process - /// dynamic loader, lldb needs to pick one over the other. This could - /// be a kernel corefile that happens to have a copy of dyld in its - /// memory. Or it could be a user process coredump of lldb while doing - /// kernel debugging - so a copy of the kernel is in its heap. This - /// should become a setting so it can be over-ridden when necessary. - //------------------------------------------------------------------ - CorefilePreference - GetCorefilePreference () - { - // For now, if both user process and kernel binaries a present, - // assume this is a kernel coredump which has a copy of a user - // process dyld in one of its pages. - return eKernelCorefile; - } - - //------------------------------------------------------------------ - // For ProcessMachCore only - //------------------------------------------------------------------ - typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> VMRangeToPermissions; - - VMRangeToFileOffset m_core_aranges; - VMRangeToPermissions m_core_range_infos; - lldb::ModuleSP m_core_module_sp; - lldb_private::FileSpec m_core_file; - lldb::addr_t m_dyld_addr; - lldb::addr_t m_mach_kernel_addr; - lldb_private::ConstString m_dyld_plugin_name; - - DISALLOW_COPY_AND_ASSIGN (ProcessMachCore); + bool GetDynamicLoaderAddress(lldb::addr_t addr); + + typedef enum CorefilePreference { + eUserProcessCorefile, + eKernelCorefile + } CorefilePreferences; + + //------------------------------------------------------------------ + /// If a core file can be interpreted multiple ways, this establishes + /// which style wins. + /// + /// If a core file contains both a kernel binary and a user-process + /// dynamic loader, lldb needs to pick one over the other. This could + /// be a kernel corefile that happens to have a copy of dyld in its + /// memory. Or it could be a user process coredump of lldb while doing + /// kernel debugging - so a copy of the kernel is in its heap. This + /// should become a setting so it can be over-ridden when necessary. + //------------------------------------------------------------------ + CorefilePreference GetCorefilePreference() { + // For now, if both user process and kernel binaries a present, + // assume this is a kernel coredump which has a copy of a user + // process dyld in one of its pages. + return eKernelCorefile; + } + + //------------------------------------------------------------------ + // For ProcessMachCore only + //------------------------------------------------------------------ + typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> + VMRangeToFileOffset; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> + VMRangeToPermissions; + + VMRangeToFileOffset m_core_aranges; + VMRangeToPermissions m_core_range_infos; + lldb::ModuleSP m_core_module_sp; + lldb_private::FileSpec m_core_file; + lldb::addr_t m_dyld_addr; + lldb::addr_t m_mach_kernel_addr; + lldb_private::ConstString m_dyld_plugin_name; + + DISALLOW_COPY_AND_ASSIGN(ProcessMachCore); }; #endif // liblldb_ProcessMachCore_h_ diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp index 2720c910e4d..828b705edf5 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -7,22 +7,21 @@ // //===----------------------------------------------------------------------===// - #include "ThreadMachCore.h" #include "lldb/Utility/SafeMachO.h" +#include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataExtractor.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/State.h" +#include "lldb/Core/StreamString.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" -#include "lldb/Breakpoint/Watchpoint.h" #include "ProcessMachCore.h" //#include "RegisterContextKDP_arm.h" @@ -36,97 +35,71 @@ using namespace lldb_private; // Thread Registers //---------------------------------------------------------------------- -ThreadMachCore::ThreadMachCore (Process &process, lldb::tid_t tid) : - Thread(process, tid), - m_thread_name (), - m_dispatch_queue_name (), - m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS), - m_thread_reg_ctx_sp () -{ -} +ThreadMachCore::ThreadMachCore(Process &process, lldb::tid_t tid) + : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), + m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), m_thread_reg_ctx_sp() {} -ThreadMachCore::~ThreadMachCore () -{ - DestroyThread(); -} +ThreadMachCore::~ThreadMachCore() { DestroyThread(); } -const char * -ThreadMachCore::GetName () -{ - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); +const char *ThreadMachCore::GetName() { + if (m_thread_name.empty()) + return NULL; + return m_thread_name.c_str(); } -void -ThreadMachCore::RefreshStateAfterStop() -{ - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do - // the right thing. - const bool force = false; - GetRegisterContext()->InvalidateIfNeeded (force); +void ThreadMachCore::RefreshStateAfterStop() { + // Invalidate all registers in our register context. We don't set "force" to + // true because the stop reply packet might have had some register values + // that were expedited and these will already be copied into the register + // context by the time this function gets called. The KDPRegisterContext + // class has been made smart enough to detect when it needs to invalidate + // which registers are valid by putting hooks in the register read and + // register supply functions where they check the process stop ID and do + // the right thing. + const bool force = false; + GetRegisterContext()->InvalidateIfNeeded(force); } -bool -ThreadMachCore::ThreadIDIsValid (lldb::tid_t thread) -{ - return thread != 0; -} +bool ThreadMachCore::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } -lldb::RegisterContextSP -ThreadMachCore::GetRegisterContext () -{ - if (m_reg_context_sp.get() == NULL) - m_reg_context_sp = CreateRegisterContextForFrame (NULL); - return m_reg_context_sp; +lldb::RegisterContextSP ThreadMachCore::GetRegisterContext() { + if (m_reg_context_sp.get() == NULL) + m_reg_context_sp = CreateRegisterContextForFrame(NULL); + return m_reg_context_sp; } lldb::RegisterContextSP -ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex (); - - if (concrete_frame_idx == 0) - { - if (!m_thread_reg_ctx_sp) - { - ProcessSP process_sp (GetProcess()); - - ObjectFile *core_objfile = static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile (); - if (core_objfile) - m_thread_reg_ctx_sp = core_objfile->GetThreadContextAtIndex (GetID(), *this); - } - reg_ctx_sp = m_thread_reg_ctx_sp; - } - else - { - Unwind *unwinder = GetUnwinder (); - if (unwinder) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame); +ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + if (!m_thread_reg_ctx_sp) { + ProcessSP process_sp(GetProcess()); + + ObjectFile *core_objfile = + static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile(); + if (core_objfile) + m_thread_reg_ctx_sp = + core_objfile->GetThreadContextAtIndex(GetID(), *this); } - return reg_ctx_sp; + reg_ctx_sp = m_thread_reg_ctx_sp; + } else { + Unwind *unwinder = GetUnwinder(); + if (unwinder) + reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; } -bool -ThreadMachCore::CalculateStopInfo () -{ - ProcessSP process_sp (GetProcess()); - if (process_sp) - { - SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP)); - return true; - } - return false; +bool ThreadMachCore::CalculateStopInfo() { + ProcessSP process_sp(GetProcess()); + if (process_sp) { + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP)); + return true; + } + return false; } - - diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h index 25973540db1..a4db484e850 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h @@ -20,72 +20,55 @@ class ProcessMachCore; -class ThreadMachCore : public lldb_private::Thread -{ +class ThreadMachCore : public lldb_private::Thread { public: - ThreadMachCore (lldb_private::Process &process, - lldb::tid_t tid); + ThreadMachCore(lldb_private::Process &process, lldb::tid_t tid); - ~ThreadMachCore() override; + ~ThreadMachCore() override; - void - RefreshStateAfterStop() override; + void RefreshStateAfterStop() override; - const char * - GetName() override; + const char *GetName() override; - lldb::RegisterContextSP - GetRegisterContext() override; + lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - static bool - ThreadIDIsValid (lldb::tid_t thread); + static bool ThreadIDIsValid(lldb::tid_t thread); - bool - ShouldStop (bool &step_more); + bool ShouldStop(bool &step_more); - const char * - GetBasicInfoAsString (); + const char *GetBasicInfoAsString(); - void - SetName(const char *name) override - { - if (name && name[0]) - m_thread_name.assign (name); - else - m_thread_name.clear(); - } + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } - lldb::addr_t - GetThreadDispatchQAddr () - { - return m_thread_dispatch_qaddr; - } + lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; } - void - SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr) - { - m_thread_dispatch_qaddr = thread_dispatch_qaddr; - } + void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) { + m_thread_dispatch_qaddr = thread_dispatch_qaddr; + } protected: - friend class ProcessMachCore; - - //------------------------------------------------------------------ - // Member variables. - //------------------------------------------------------------------ - std::string m_thread_name; - std::string m_dispatch_queue_name; - lldb::addr_t m_thread_dispatch_qaddr; - lldb::RegisterContextSP m_thread_reg_ctx_sp; - - //------------------------------------------------------------------ - // Protected member functions. - //------------------------------------------------------------------ - bool - CalculateStopInfo() override; + friend class ProcessMachCore; + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + std::string m_thread_name; + std::string m_dispatch_queue_name; + lldb::addr_t m_thread_dispatch_qaddr; + lldb::RegisterContextSP m_thread_reg_ctx_sp; + + //------------------------------------------------------------------ + // Protected member functions. + //------------------------------------------------------------------ + bool CalculateStopInfo() override; }; #endif // liblldb_ThreadMachCore_h_ diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp index 18b8a3ff361..28dbd1bb5f1 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -1,4 +1,5 @@ -//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===// +//===-- MinidumpParser.cpp ---------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -18,143 +19,136 @@ using namespace lldb_private; using namespace minidump; llvm::Optional<MinidumpParser> -MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) -{ - if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) - { - return llvm::None; +MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) { + if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) { + return llvm::None; + } + + llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(), + sizeof(MinidumpHeader)); + const MinidumpHeader *header = MinidumpHeader::Parse(header_data); + + if (header == nullptr) { + return llvm::None; + } + + lldb::offset_t directory_list_offset = header->stream_directory_rva; + // check if there is enough data for the parsing of the directory list + if ((directory_list_offset + + sizeof(MinidumpDirectory) * header->streams_count) > + data_buf_sp->GetByteSize()) { + return llvm::None; + } + + const MinidumpDirectory *directory = nullptr; + Error error; + llvm::ArrayRef<uint8_t> directory_data( + data_buf_sp->GetBytes() + directory_list_offset, + sizeof(MinidumpDirectory) * header->streams_count); + llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map; + + for (uint32_t i = 0; i < header->streams_count; ++i) { + error = consumeObject(directory_data, directory); + if (error.Fail()) { + return llvm::None; } + directory_map[static_cast<const uint32_t>(directory->stream_type)] = + directory->location; + } - llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(), sizeof(MinidumpHeader)); - const MinidumpHeader *header = MinidumpHeader::Parse(header_data); - - if (header == nullptr) - { - return llvm::None; - } - - lldb::offset_t directory_list_offset = header->stream_directory_rva; - // check if there is enough data for the parsing of the directory list - if ((directory_list_offset + sizeof(MinidumpDirectory) * header->streams_count) > data_buf_sp->GetByteSize()) - { - return llvm::None; - } - - const MinidumpDirectory *directory = nullptr; - Error error; - llvm::ArrayRef<uint8_t> directory_data(data_buf_sp->GetBytes() + directory_list_offset, - sizeof(MinidumpDirectory) * header->streams_count); - llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map; - - for (uint32_t i = 0; i < header->streams_count; ++i) - { - error = consumeObject(directory_data, directory); - if (error.Fail()) - { - return llvm::None; - } - directory_map[static_cast<const uint32_t>(directory->stream_type)] = directory->location; - } - - MinidumpParser parser(data_buf_sp, header, directory_map); - return llvm::Optional<MinidumpParser>(parser); + MinidumpParser parser(data_buf_sp, header, directory_map); + return llvm::Optional<MinidumpParser>(parser); } -MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header, - const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map) - : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) -{ +MinidumpParser::MinidumpParser( + const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header, + const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map) + : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) { } -lldb::offset_t -MinidumpParser::GetByteSize() -{ - return m_data_sp->GetByteSize(); +lldb::offset_t MinidumpParser::GetByteSize() { + return m_data_sp->GetByteSize(); } llvm::Optional<llvm::ArrayRef<uint8_t>> -MinidumpParser::GetStream(MinidumpStreamType stream_type) -{ - auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type)); - if (iter == m_directory_map.end()) - return llvm::None; - - // check if there is enough data - if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize()) - return llvm::None; - - llvm::ArrayRef<uint8_t> arr_ref(m_data_sp->GetBytes() + iter->second.rva, iter->second.data_size); - return llvm::Optional<llvm::ArrayRef<uint8_t>>(arr_ref); +MinidumpParser::GetStream(MinidumpStreamType stream_type) { + auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type)); + if (iter == m_directory_map.end()) + return llvm::None; + + // check if there is enough data + if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize()) + return llvm::None; + + llvm::ArrayRef<uint8_t> arr_ref(m_data_sp->GetBytes() + iter->second.rva, + iter->second.data_size); + return llvm::Optional<llvm::ArrayRef<uint8_t>>(arr_ref); } llvm::Optional<std::vector<const MinidumpThread *>> -MinidumpParser::GetThreads() -{ - llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::ThreadList); +MinidumpParser::GetThreads() { + llvm::Optional<llvm::ArrayRef<uint8_t>> data = + GetStream(MinidumpStreamType::ThreadList); - if (!data) - return llvm::None; + if (!data) + return llvm::None; - return MinidumpThread::ParseThreadList(data.getValue()); + return MinidumpThread::ParseThreadList(data.getValue()); } -const MinidumpSystemInfo * -MinidumpParser::GetSystemInfo() -{ - llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::SystemInfo); +const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() { + llvm::Optional<llvm::ArrayRef<uint8_t>> data = + GetStream(MinidumpStreamType::SystemInfo); - if (!data) - return nullptr; + if (!data) + return nullptr; - return MinidumpSystemInfo::Parse(data.getValue()); + return MinidumpSystemInfo::Parse(data.getValue()); } -ArchSpec -MinidumpParser::GetArchitecture() -{ - ArchSpec arch_spec; - arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); - arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); - arch_spec.GetTriple().setArch(llvm::Triple::ArchType::UnknownArch); - - // TODO should we add the OS type here, or somewhere else ? - - const MinidumpSystemInfo *system_info = GetSystemInfo(); - - if (!system_info) - return arch_spec; - - // TODO what to do about big endiand flavors of arm ? - // TODO set the arm subarch stuff if the minidump has info about it - - const MinidumpCPUArchitecture arch = - static_cast<const MinidumpCPUArchitecture>(static_cast<const uint32_t>(system_info->processor_arch)); - switch (arch) - { - case MinidumpCPUArchitecture::X86: - arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86); - break; - case MinidumpCPUArchitecture::AMD64: - arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64); - break; - case MinidumpCPUArchitecture::ARM: - arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm); - break; - case MinidumpCPUArchitecture::ARM64: - arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64); - break; - } +ArchSpec MinidumpParser::GetArchitecture() { + ArchSpec arch_spec; + arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); + arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::UnknownArch); + + // TODO should we add the OS type here, or somewhere else ? + const MinidumpSystemInfo *system_info = GetSystemInfo(); + + if (!system_info) return arch_spec; + + // TODO what to do about big endiand flavors of arm ? + // TODO set the arm subarch stuff if the minidump has info about it + + const MinidumpCPUArchitecture arch = + static_cast<const MinidumpCPUArchitecture>( + static_cast<const uint32_t>(system_info->processor_arch)); + switch (arch) { + case MinidumpCPUArchitecture::X86: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86); + break; + case MinidumpCPUArchitecture::AMD64: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64); + break; + case MinidumpCPUArchitecture::ARM: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm); + break; + case MinidumpCPUArchitecture::ARM64: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64); + break; + } + + return arch_spec; } -const MinidumpMiscInfo * -MinidumpParser::GetMiscInfo() -{ - llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::MiscInfo); +const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() { + llvm::Optional<llvm::ArrayRef<uint8_t>> data = + GetStream(MinidumpStreamType::MiscInfo); - if (!data) - return nullptr; + if (!data) + return nullptr; - return MinidumpMiscInfo::Parse(data.getValue()); + return MinidumpMiscInfo::Parse(data.getValue()); } diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h index d99bd57f2f4..acee0e5869a 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h @@ -1,4 +1,5 @@ -//===-- MinidumpParser.h -----------------------------------------*- C++ -*-===// +//===-- MinidumpParser.h -----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -28,44 +29,37 @@ #include <cstring> #include <unordered_map> +namespace lldb_private { -namespace lldb_private -{ +namespace minidump { -namespace minidump -{ - -class MinidumpParser -{ +class MinidumpParser { public: - static llvm::Optional<MinidumpParser> - Create(const lldb::DataBufferSP &data_buf_sp); + static llvm::Optional<MinidumpParser> + Create(const lldb::DataBufferSP &data_buf_sp); - lldb::offset_t - GetByteSize(); + lldb::offset_t GetByteSize(); - llvm::Optional<llvm::ArrayRef<uint8_t>> - GetStream(MinidumpStreamType stream_type); + llvm::Optional<llvm::ArrayRef<uint8_t>> + GetStream(MinidumpStreamType stream_type); - llvm::Optional<std::vector<const MinidumpThread *>> - GetThreads(); + llvm::Optional<std::vector<const MinidumpThread *>> GetThreads(); - const MinidumpSystemInfo * - GetSystemInfo(); + const MinidumpSystemInfo *GetSystemInfo(); - ArchSpec - GetArchitecture(); + ArchSpec GetArchitecture(); - const MinidumpMiscInfo * - GetMiscInfo(); + const MinidumpMiscInfo *GetMiscInfo(); private: - lldb::DataBufferSP m_data_sp; - const MinidumpHeader *m_header; - llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map; - - MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header, - const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map); + lldb::DataBufferSP m_data_sp; + const MinidumpHeader *m_header; + llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map; + + MinidumpParser(const lldb::DataBufferSP &data_buf_sp, + const MinidumpHeader *header, + const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> + &directory_map); }; } // namespace minidump diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp index dbcf730aaea..4f1cb0aa43a 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -18,81 +18,75 @@ using namespace lldb_private; using namespace minidump; -const MinidumpHeader * -MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) -{ - const MinidumpHeader *header = nullptr; - Error error = consumeObject(data, header); - - const MinidumpHeaderConstants signature = - static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(header->signature)); - const MinidumpHeaderConstants version = - static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(header->version) & 0x0000ffff); - // the high 16 bits of the version field are implementation specific - - if (error.Fail() || signature != MinidumpHeaderConstants::Signature || version != MinidumpHeaderConstants::Version) - return nullptr; - - // TODO check for max number of streams ? - // TODO more sanity checks ? - - return header; +const MinidumpHeader *MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) { + const MinidumpHeader *header = nullptr; + Error error = consumeObject(data, header); + + const MinidumpHeaderConstants signature = + static_cast<const MinidumpHeaderConstants>( + static_cast<const uint32_t>(header->signature)); + const MinidumpHeaderConstants version = + static_cast<const MinidumpHeaderConstants>( + static_cast<const uint32_t>(header->version) & 0x0000ffff); + // the high 16 bits of the version field are implementation specific + + if (error.Fail() || signature != MinidumpHeaderConstants::Signature || + version != MinidumpHeaderConstants::Version) + return nullptr; + + // TODO check for max number of streams ? + // TODO more sanity checks ? + + return header; } // MinidumpThread -const MinidumpThread * -MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) -{ - const MinidumpThread *thread = nullptr; - Error error = consumeObject(data, thread); - if (error.Fail()) - return nullptr; - - return thread; +const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) { + const MinidumpThread *thread = nullptr; + Error error = consumeObject(data, thread); + if (error.Fail()) + return nullptr; + + return thread; } llvm::Optional<std::vector<const MinidumpThread *>> -MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) -{ - std::vector<const MinidumpThread *> thread_list; - - const llvm::support::ulittle32_t *thread_count; - Error error = consumeObject(data, thread_count); - if (error.Fail()) - return llvm::None; - - const MinidumpThread *thread; - for (uint32_t i = 0; i < *thread_count; ++i) - { - thread = MinidumpThread::Parse(data); - if (thread == nullptr) - return llvm::None; - thread_list.push_back(thread); - } - - return llvm::Optional<std::vector<const MinidumpThread *>>(thread_list); +MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) { + std::vector<const MinidumpThread *> thread_list; + + const llvm::support::ulittle32_t *thread_count; + Error error = consumeObject(data, thread_count); + if (error.Fail()) + return llvm::None; + + const MinidumpThread *thread; + for (uint32_t i = 0; i < *thread_count; ++i) { + thread = MinidumpThread::Parse(data); + if (thread == nullptr) + return llvm::None; + thread_list.push_back(thread); + } + + return llvm::Optional<std::vector<const MinidumpThread *>>(thread_list); } // MinidumpSystemInfo const MinidumpSystemInfo * -MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &data) -{ - const MinidumpSystemInfo *system_info; - Error error = consumeObject(data, system_info); - if (error.Fail()) - return nullptr; - - return system_info; +MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &data) { + const MinidumpSystemInfo *system_info; + Error error = consumeObject(data, system_info); + if (error.Fail()) + return nullptr; + + return system_info; } // MinidumpMiscInfo -const MinidumpMiscInfo * -MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) -{ - const MinidumpMiscInfo *misc_info; - Error error = consumeObject(data, misc_info); - if (error.Fail()) - return nullptr; - - return misc_info; +const MinidumpMiscInfo *MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) { + const MinidumpMiscInfo *misc_info; + Error error = consumeObject(data, misc_info); + if (error.Fail()) + return nullptr; + + return misc_info; } diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h index 6017db03527..95dc07ff9d5 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -27,271 +27,267 @@ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx // https://chromium.googlesource.com/breakpad/breakpad/ -namespace lldb_private -{ +namespace lldb_private { -namespace minidump -{ +namespace minidump { LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); -enum class MinidumpHeaderConstants : uint32_t -{ - Signature = 0x504d444d, // 'PMDM' - Version = 0x0000a793, // 42899 - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature) +enum class MinidumpHeaderConstants : uint32_t { + Signature = 0x504d444d, // 'PMDM' + Version = 0x0000a793, // 42899 + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature) }; -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx -enum class MinidumpStreamType : uint32_t -{ - Unused = 0, - Reserved0 = 1, - Reserved1 = 2, - ThreadList = 3, - ModuleList = 4, - MemoryList = 5, - Exception = 6, - SystemInfo = 7, - ThreadExList = 8, - Memory64List = 9, - CommentA = 10, - CommentW = 11, - HandleData = 12, - FunctionTable = 13, - UnloadedModuleList = 14, - MiscInfo = 15, - MemoryInfoList = 16, - ThreadInfoList = 17, - HandleOperationList = 18, - Token = 19, - JavascriptData = 20, - SystemMemoryInfo = 21, - ProcessVMCounters = 22, - LastReserved = 0x0000ffff, - - /* Breakpad extension types. 0x4767 = "Gg" */ - BreakpadInfo = 0x47670001, - AssertionInfo = 0x47670002, - /* These are additional minidump stream values which are specific to - * the linux breakpad implementation. */ - LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */ - LinuxProcStatus = 0x47670004, /* /proc/$x/status */ - LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */ - LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */ - LinuxEnviron = 0x47670007, /* /proc/$x/environ */ - LinuxAuxv = 0x47670008, /* /proc/$x/auxv */ - LinuxMaps = 0x47670009, /* /proc/$x/maps */ - LinuxDSODebug = 0x4767000A +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx +enum class MinidumpStreamType : uint32_t { + Unused = 0, + Reserved0 = 1, + Reserved1 = 2, + ThreadList = 3, + ModuleList = 4, + MemoryList = 5, + Exception = 6, + SystemInfo = 7, + ThreadExList = 8, + Memory64List = 9, + CommentA = 10, + CommentW = 11, + HandleData = 12, + FunctionTable = 13, + UnloadedModuleList = 14, + MiscInfo = 15, + MemoryInfoList = 16, + ThreadInfoList = 17, + HandleOperationList = 18, + Token = 19, + JavascriptData = 20, + SystemMemoryInfo = 21, + ProcessVMCounters = 22, + LastReserved = 0x0000ffff, + + /* Breakpad extension types. 0x4767 = "Gg" */ + BreakpadInfo = 0x47670001, + AssertionInfo = 0x47670002, + /* These are additional minidump stream values which are specific to + * the linux breakpad implementation. */ + LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */ + LinuxProcStatus = 0x47670004, /* /proc/$x/status */ + LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */ + LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */ + LinuxEnviron = 0x47670007, /* /proc/$x/environ */ + LinuxAuxv = 0x47670008, /* /proc/$x/auxv */ + LinuxMaps = 0x47670009, /* /proc/$x/maps */ + LinuxDSODebug = 0x4767000A }; // for MinidumpSystemInfo.processor_arch -enum class MinidumpCPUArchitecture : uint16_t -{ - X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ - MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ - Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ - PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ - SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */ - ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ - IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ - Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ - MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL - * (Microsoft Intermediate Language) */ - AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ - X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ - SPARC = 0x8001, /* Breakpad-defined value for SPARC */ - PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */ - ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */ - MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */ - Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ +enum class MinidumpCPUArchitecture : uint16_t { + X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ + MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ + Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ + PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ + SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */ + ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ + IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ + Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ + MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL + * (Microsoft Intermediate Language) */ + AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ + X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ + SPARC = 0x8001, /* Breakpad-defined value for SPARC */ + PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */ + ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */ + MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */ + Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ }; // for MinidumpSystemInfo.platform_id -enum class MinidumpOSPlatform : uint32_t -{ - Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ - Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ - Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ - Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH - * (Windows CE, Windows Mobile, "Handheld") */ - - /* The following values are Breakpad-defined. */ - Unix = 0x8000, /* Generic Unix-ish */ - MacOSX = 0x8101, /* Mac OS X/Darwin */ - IOS = 0x8102, /* iOS */ - Linux = 0x8201, /* Linux */ - Solaris = 0x8202, /* Solaris */ - Android = 0x8203, /* Android */ - PS3 = 0x8204, /* PS3 */ - NaCl = 0x8205 /* Native Client (NaCl) */ +enum class MinidumpOSPlatform : uint32_t { + Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ + Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ + Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ + Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH + * (Windows CE, Windows Mobile, "Handheld") */ + + /* The following values are Breakpad-defined. */ + Unix = 0x8000, /* Generic Unix-ish */ + MacOSX = 0x8101, /* Mac OS X/Darwin */ + IOS = 0x8102, /* iOS */ + Linux = 0x8201, /* Linux */ + Solaris = 0x8202, /* Solaris */ + Android = 0x8203, /* Android */ + PS3 = 0x8204, /* PS3 */ + NaCl = 0x8205 /* Native Client (NaCl) */ }; // For MinidumpCPUInfo.arm_cpu_info.elf_hwcaps. // This matches the Linux kernel definitions from <asm/hwcaps.h> -enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t -{ - SWP = (1 << 0), - Half = (1 << 1), - Thumb = (1 << 2), - _26BIT = (1 << 3), - FastMult = (1 << 4), - FPA = (1 << 5), - VFP = (1 << 6), - EDSP = (1 << 7), - Java = (1 << 8), - IWMMXT = (1 << 9), - Crunch = (1 << 10), - ThumbEE = (1 << 11), - Neon = (1 << 12), - VFPv3 = (1 << 13), - VFPv3D16 = (1 << 14), - TLS = (1 << 15), - VFPv4 = (1 << 16), - IDIVA = (1 << 17), - IDIVT = (1 << 18), - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT) +enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t { + SWP = (1 << 0), + Half = (1 << 1), + Thumb = (1 << 2), + _26BIT = (1 << 3), + FastMult = (1 << 4), + FPA = (1 << 5), + VFP = (1 << 6), + EDSP = (1 << 7), + Java = (1 << 8), + IWMMXT = (1 << 9), + Crunch = (1 << 10), + ThumbEE = (1 << 11), + Neon = (1 << 12), + VFPv3 = (1 << 13), + VFPv3D16 = (1 << 14), + TLS = (1 << 15), + VFPv4 = (1 << 16), + IDIVA = (1 << 17), + IDIVT = (1 << 18), + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT) }; template <typename T> -Error -consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) -{ - Error error; - if (Buffer.size() < sizeof(T)) - { - error.SetErrorString("Insufficient buffer!"); - return error; - } - - Object = reinterpret_cast<const T *>(Buffer.data()); - Buffer = Buffer.drop_front(sizeof(T)); +Error consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) { + Error error; + if (Buffer.size() < sizeof(T)) { + error.SetErrorString("Insufficient buffer!"); return error; + } + + Object = reinterpret_cast<const T *>(Buffer.data()); + Buffer = Buffer.drop_front(sizeof(T)); + return error; } -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx -struct MinidumpHeader -{ - llvm::support::ulittle32_t signature; - llvm::support::ulittle32_t version; // The high 16 bits of version field are implementation specific - llvm::support::ulittle32_t streams_count; - llvm::support::ulittle32_t stream_directory_rva; // offset of the stream directory - llvm::support::ulittle32_t checksum; - llvm::support::ulittle32_t time_date_stamp; // time_t format - llvm::support::ulittle64_t flags; - - static const MinidumpHeader * - Parse(llvm::ArrayRef<uint8_t> &data); +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx +struct MinidumpHeader { + llvm::support::ulittle32_t signature; + llvm::support::ulittle32_t + version; // The high 16 bits of version field are implementation specific + llvm::support::ulittle32_t streams_count; + llvm::support::ulittle32_t + stream_directory_rva; // offset of the stream directory + llvm::support::ulittle32_t checksum; + llvm::support::ulittle32_t time_date_stamp; // time_t format + llvm::support::ulittle64_t flags; + + static const MinidumpHeader *Parse(llvm::ArrayRef<uint8_t> &data); }; -static_assert(sizeof(MinidumpHeader) == 32, "sizeof MinidumpHeader is not correct!"); +static_assert(sizeof(MinidumpHeader) == 32, + "sizeof MinidumpHeader is not correct!"); -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx -struct MinidumpLocationDescriptor -{ - llvm::support::ulittle32_t data_size; - llvm::support::ulittle32_t rva; +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx +struct MinidumpLocationDescriptor { + llvm::support::ulittle32_t data_size; + llvm::support::ulittle32_t rva; }; -static_assert(sizeof(MinidumpLocationDescriptor) == 8, "sizeof MinidumpLocationDescriptor is not correct!"); +static_assert(sizeof(MinidumpLocationDescriptor) == 8, + "sizeof MinidumpLocationDescriptor is not correct!"); -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx -struct MinidumpMemoryDescriptor -{ - llvm::support::ulittle64_t start_of_memory_range; - MinidumpLocationDescriptor memory; +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx +struct MinidumpMemoryDescriptor { + llvm::support::ulittle64_t start_of_memory_range; + MinidumpLocationDescriptor memory; }; -static_assert(sizeof(MinidumpMemoryDescriptor) == 16, "sizeof MinidumpMemoryDescriptor is not correct!"); +static_assert(sizeof(MinidumpMemoryDescriptor) == 16, + "sizeof MinidumpMemoryDescriptor is not correct!"); -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx -struct MinidumpDirectory -{ - llvm::support::ulittle32_t stream_type; - MinidumpLocationDescriptor location; +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx +struct MinidumpDirectory { + llvm::support::ulittle32_t stream_type; + MinidumpLocationDescriptor location; }; -static_assert(sizeof(MinidumpDirectory) == 12, "sizeof MinidumpDirectory is not correct!"); - -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx -struct MinidumpThread -{ - llvm::support::ulittle32_t thread_id; - llvm::support::ulittle32_t suspend_count; - llvm::support::ulittle32_t priority_class; - llvm::support::ulittle32_t priority; - llvm::support::ulittle64_t teb; - MinidumpMemoryDescriptor stack; - MinidumpLocationDescriptor thread_context; - - static const MinidumpThread * - Parse(llvm::ArrayRef<uint8_t> &data); - - static llvm::Optional<std::vector<const MinidumpThread *>> - ParseThreadList(llvm::ArrayRef<uint8_t> &data); +static_assert(sizeof(MinidumpDirectory) == 12, + "sizeof MinidumpDirectory is not correct!"); + +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx +struct MinidumpThread { + llvm::support::ulittle32_t thread_id; + llvm::support::ulittle32_t suspend_count; + llvm::support::ulittle32_t priority_class; + llvm::support::ulittle32_t priority; + llvm::support::ulittle64_t teb; + MinidumpMemoryDescriptor stack; + MinidumpLocationDescriptor thread_context; + + static const MinidumpThread *Parse(llvm::ArrayRef<uint8_t> &data); + + static llvm::Optional<std::vector<const MinidumpThread *>> + ParseThreadList(llvm::ArrayRef<uint8_t> &data); }; -static_assert(sizeof(MinidumpThread) == 48, "sizeof MinidumpThread is not correct!"); +static_assert(sizeof(MinidumpThread) == 48, + "sizeof MinidumpThread is not correct!"); -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx union MinidumpCPUInfo { - struct - { - llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ - llvm::support::ulittle32_t version_information; /* cpuid 1: eax */ - llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */ - llvm::support::ulittle32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ - } x86_cpu_info; - struct - { - llvm::support::ulittle32_t cpuid; - llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */ - } arm_cpu_info; - struct - { - llvm::support::ulittle64_t processor_features[2]; - } other_cpu_info; + struct { + llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ + llvm::support::ulittle32_t version_information; /* cpuid 1: eax */ + llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */ + llvm::support::ulittle32_t + amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ + } x86_cpu_info; + struct { + llvm::support::ulittle32_t cpuid; + llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */ + } arm_cpu_info; + struct { + llvm::support::ulittle64_t processor_features[2]; + } other_cpu_info; }; -static_assert(sizeof(MinidumpCPUInfo) == 24, "sizeof MinidumpCPUInfo is not correct!"); +static_assert(sizeof(MinidumpCPUInfo) == 24, + "sizeof MinidumpCPUInfo is not correct!"); -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx -struct MinidumpSystemInfo -{ - llvm::support::ulittle16_t processor_arch; - llvm::support::ulittle16_t processor_level; - llvm::support::ulittle16_t processor_revision; +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx +struct MinidumpSystemInfo { + llvm::support::ulittle16_t processor_arch; + llvm::support::ulittle16_t processor_level; + llvm::support::ulittle16_t processor_revision; - uint8_t number_of_processors; - uint8_t product_type; + uint8_t number_of_processors; + uint8_t product_type; - llvm::support::ulittle32_t major_version; - llvm::support::ulittle32_t minor_version; - llvm::support::ulittle32_t build_number; - llvm::support::ulittle32_t platform_id; - llvm::support::ulittle32_t csd_version_rva; + llvm::support::ulittle32_t major_version; + llvm::support::ulittle32_t minor_version; + llvm::support::ulittle32_t build_number; + llvm::support::ulittle32_t platform_id; + llvm::support::ulittle32_t csd_version_rva; - llvm::support::ulittle16_t suit_mask; - llvm::support::ulittle16_t reserved2; + llvm::support::ulittle16_t suit_mask; + llvm::support::ulittle16_t reserved2; - MinidumpCPUInfo cpu; + MinidumpCPUInfo cpu; - static const MinidumpSystemInfo * - Parse(llvm::ArrayRef<uint8_t> &data); + static const MinidumpSystemInfo *Parse(llvm::ArrayRef<uint8_t> &data); }; -static_assert(sizeof(MinidumpSystemInfo) == 56, "sizeof MinidumpSystemInfo is not correct!"); +static_assert(sizeof(MinidumpSystemInfo) == 56, + "sizeof MinidumpSystemInfo is not correct!"); // TODO check flags to see what's valid // TODO misc2, misc3 ? -// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx -struct MinidumpMiscInfo -{ - llvm::support::ulittle32_t size; - llvm::support::ulittle32_t flags1; - llvm::support::ulittle32_t process_id; - llvm::support::ulittle32_t process_create_time; - llvm::support::ulittle32_t process_user_time; - llvm::support::ulittle32_t process_kernel_time; - - static const MinidumpMiscInfo * - Parse(llvm::ArrayRef<uint8_t> &data); +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx +struct MinidumpMiscInfo { + llvm::support::ulittle32_t size; + llvm::support::ulittle32_t flags1; + llvm::support::ulittle32_t process_id; + llvm::support::ulittle32_t process_create_time; + llvm::support::ulittle32_t process_user_time; + llvm::support::ulittle32_t process_kernel_time; + + static const MinidumpMiscInfo *Parse(llvm::ArrayRef<uint8_t> &data); }; -static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!"); +static_assert(sizeof(MinidumpMiscInfo) == 24, + "sizeof MinidumpMiscInfo is not correct!"); } // namespace minidump } // namespace lldb_private |