diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /lldb/source/Plugins/Process | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'lldb/source/Plugins/Process')
229 files changed, 2071 insertions, 9999 deletions
diff --git a/lldb/source/Plugins/Process/Darwin/CFBundle.cpp b/lldb/source/Plugins/Process/Darwin/CFBundle.cpp deleted file mode 100644 index 3cdd2fa575e7..000000000000 --- a/lldb/source/Plugins/Process/Darwin/CFBundle.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===-- CFBundle.cpp --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#include "CFBundle.h" -#include "CFString.h" - -// CFBundle constructor -CFBundle::CFBundle(const char *path) - : CFReleaser<CFBundleRef>(), m_bundle_url() { - if (path && path[0]) - SetPath(path); -} - -// CFBundle copy constructor -CFBundle::CFBundle(const CFBundle &rhs) - : CFReleaser<CFBundleRef>(rhs), m_bundle_url(rhs.m_bundle_url) {} - -// CFBundle copy constructor -CFBundle &CFBundle::operator=(const CFBundle &rhs) { - *this = rhs; - return *this; -} - -// Destructor -CFBundle::~CFBundle() {} - -// Set the path for a bundle by supplying a -bool CFBundle::SetPath(const char *path) { - CFAllocatorRef alloc = kCFAllocatorDefault; - // Release our old bundle and ULR - reset(); // This class is a CFReleaser<CFBundleRef> - m_bundle_url.reset(); - // Make a CFStringRef from the supplied path - CFString cf_path; - cf_path.SetFileSystemRepresentation(path); - if (cf_path.get()) { - // Make our Bundle URL - m_bundle_url.reset(::CFURLCreateWithFileSystemPath( - alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); - if (m_bundle_url.get()) { - reset(::CFBundleCreate(alloc, m_bundle_url.get())); - } - } - return get() != NULL; -} - -CFStringRef CFBundle::GetIdentifier() const { - CFBundleRef bundle = get(); - if (bundle != NULL) - return ::CFBundleGetIdentifier(bundle); - return NULL; -} - -CFURLRef CFBundle::CopyExecutableURL() const { - CFBundleRef bundle = get(); - if (bundle != NULL) - return CFBundleCopyExecutableURL(bundle); - return NULL; -} diff --git a/lldb/source/Plugins/Process/Darwin/CFBundle.h b/lldb/source/Plugins/Process/Darwin/CFBundle.h deleted file mode 100644 index f49dc30f1f8f..000000000000 --- a/lldb/source/Plugins/Process/Darwin/CFBundle.h +++ /dev/null @@ -1,35 +0,0 @@ -//===-- CFBundle.h ----------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFBundle_h__ -#define __CFBundle_h__ - -#include "CFUtils.h" - -class CFBundle : public CFReleaser<CFBundleRef> { -public: - // Constructors and Destructors - CFBundle(const char *path = NULL); - CFBundle(const CFBundle &rhs); - CFBundle &operator=(const CFBundle &rhs); - virtual ~CFBundle(); - bool SetPath(const char *path); - - CFStringRef GetIdentifier() const; - - CFURLRef CopyExecutableURL() const; - -protected: - CFReleaser<CFURLRef> m_bundle_url; -}; - -#endif // #ifndef __CFBundle_h__ diff --git a/lldb/source/Plugins/Process/Darwin/CFString.cpp b/lldb/source/Plugins/Process/Darwin/CFString.cpp deleted file mode 100644 index 4dcc05c86657..000000000000 --- a/lldb/source/Plugins/Process/Darwin/CFString.cpp +++ /dev/null @@ -1,153 +0,0 @@ -//===-- CFString.cpp --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#include "CFString.h" -#include <glob.h> -#include <string> - -// CFString constructor -CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} - -// CFString copy constructor -CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {} - -// CFString copy constructor -CFString &CFString::operator=(const CFString &rhs) { - if (this != &rhs) - *this = rhs; - return *this; -} - -CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding) - : CFReleaser<CFStringRef>() { - if (cstr && cstr[0]) { - reset( - ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); - } -} - -// Destructor -CFString::~CFString() {} - -const char *CFString::GetFileSystemRepresentation(std::string &s) { - return CFString::FileSystemRepresentation(get(), s); -} - -CFStringRef CFString::SetFileSystemRepresentation(const char *path) { - CFStringRef new_value = NULL; - if (path && path[0]) - new_value = - ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); - reset(new_value); - return get(); -} - -CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { - CFStringRef new_value = NULL; - if (cf_type != NULL) { - CFTypeID cf_type_id = ::CFGetTypeID(cf_type); - - if (cf_type_id == ::CFStringGetTypeID()) { - // Retain since we are using the existing object - new_value = (CFStringRef)::CFRetain(cf_type); - } else if (cf_type_id == ::CFURLGetTypeID()) { - new_value = - ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); - } - } - reset(new_value); - return get(); -} - -CFStringRef -CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) { - std::string expanded_path; - if (CFString::GlobPath(path, expanded_path)) - SetFileSystemRepresentation(expanded_path.c_str()); - else - reset(); - return get(); -} - -const char *CFString::UTF8(std::string &str) { - return CFString::UTF8(get(), str); -} - -// Static function that puts a copy of the UTF8 contents of CF_STR into STR and -// returns the C string pointer that is contained in STR when successful, else -// NULL is returned. This allows the std::string parameter to own the extracted -// string, -// and also allows that string to be returned as a C string pointer that can be -// used. - -const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { - if (cf_str) { - const CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex max_utf8_str_len = CFStringGetLength(cf_str); - max_utf8_str_len = - CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); - if (max_utf8_str_len > 0) { - str.resize(max_utf8_str_len); - if (!str.empty()) { - if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { - str.resize(strlen(str.c_str())); - return str.c_str(); - } - } - } - } - return NULL; -} - -// Static function that puts a copy of the file system representation of CF_STR -// into STR and returns the C string pointer that is contained in STR when -// successful, else NULL is returned. This allows the std::string parameter to -// own the extracted string, and also allows that string to be returned as a C -// string pointer that can be used. - -const char *CFString::FileSystemRepresentation(CFStringRef cf_str, - std::string &str) { - if (cf_str) { - CFIndex max_length = - ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); - if (max_length > 0) { - str.resize(max_length); - if (!str.empty()) { - if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], - str.size())) { - str.erase(::strlen(str.c_str())); - return str.c_str(); - } - } - } - } - str.erase(); - return NULL; -} - -CFIndex CFString::GetLength() const { - CFStringRef str = get(); - if (str) - return CFStringGetLength(str); - return 0; -} - -const char *CFString::GlobPath(const char *path, std::string &expanded_path) { - glob_t globbuf; - if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { - expanded_path = globbuf.gl_pathv[0]; - ::globfree(&globbuf); - } else - expanded_path.clear(); - - return expanded_path.c_str(); -} diff --git a/lldb/source/Plugins/Process/Darwin/CFString.h b/lldb/source/Plugins/Process/Darwin/CFString.h deleted file mode 100644 index d1bd5682689e..000000000000 --- a/lldb/source/Plugins/Process/Darwin/CFString.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- CFString.h ----------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFString_h__ -#define __CFString_h__ - -#include "CFUtils.h" -#include <iosfwd> - -class CFString : public CFReleaser<CFStringRef> { -public: - // Constructors and Destructors - CFString(CFStringRef cf_str = NULL); - CFString(const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); - CFString(const CFString &rhs); - CFString &operator=(const CFString &rhs); - virtual ~CFString(); - - const char *GetFileSystemRepresentation(std::string &str); - CFStringRef SetFileSystemRepresentation(const char *path); - CFStringRef SetFileSystemRepresentationFromCFType(CFTypeRef cf_type); - CFStringRef SetFileSystemRepresentationAndExpandTilde(const char *path); - const char *UTF8(std::string &str); - CFIndex GetLength() const; - static const char *UTF8(CFStringRef cf_str, std::string &str); - static const char *FileSystemRepresentation(CFStringRef cf_str, - std::string &str); - static const char *GlobPath(const char *path, std::string &expanded_path); -}; - -#endif // #ifndef __CFString_h__ diff --git a/lldb/source/Plugins/Process/Darwin/CFUtils.h b/lldb/source/Plugins/Process/Darwin/CFUtils.h deleted file mode 100644 index b567524ce63a..000000000000 --- a/lldb/source/Plugins/Process/Darwin/CFUtils.h +++ /dev/null @@ -1,75 +0,0 @@ -//===-- CFUtils.h -----------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/5/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFUtils_h__ -#define __CFUtils_h__ - -#include <CoreFoundation/CoreFoundation.h> - -#ifdef __cplusplus - -// Templatized CF helper class that can own any CF pointer and will -// call CFRelease() on any valid pointer it owns unless that pointer is -// explicitly released using the release() member function. -template <class T> class CFReleaser { -public: - // Type names for the avlue - typedef T element_type; - - // Constructors and destructors - CFReleaser(T ptr = NULL) : _ptr(ptr) {} - CFReleaser(const CFReleaser ©) : _ptr(copy.get()) { - if (get()) - ::CFRetain(get()); - } - virtual ~CFReleaser() { reset(); } - - // Assignments - CFReleaser &operator=(const CFReleaser<T> ©) { - if (copy != *this) { - // Replace our owned pointer with the new one - reset(copy.get()); - // Retain the current pointer that we own - if (get()) - ::CFRetain(get()); - } - } - // Get the address of the contained type - T *ptr_address() { return &_ptr; } - - // Access the pointer itself - const T get() const { return _ptr; } - T get() { return _ptr; } - - // Set a new value for the pointer and CFRelease our old - // value if we had a valid one. - void reset(T ptr = NULL) { - if (ptr != _ptr) { - if (_ptr != NULL) - ::CFRelease(_ptr); - _ptr = ptr; - } - } - - // Release ownership without calling CFRelease - T release() { - T tmp = _ptr; - _ptr = NULL; - return tmp; - } - -private: - element_type _ptr; -}; - -#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 deleted file mode 100644 index f70ef97a2bc5..000000000000 --- a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ /dev/null @@ -1,638 +0,0 @@ -//===-- DarwinProcessLauncher.cpp -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// -// DarwinProcessLauncher.cpp -// lldb -// -// Created by Todd Fiala on 8/30/16. -// -// - -#include "DarwinProcessLauncher.h" - -// C includes -#include <spawn.h> -#include <sys/ptrace.h> -#include <sys/stat.h> -#include <sys/sysctl.h> - -#ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 -#endif - -// LLDB includes -#include "lldb/lldb-enumerations.h" - -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" -#include "llvm/Support/Errno.h" - -#include "CFBundle.h" -#include "CFString.h" - -using namespace lldb; -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 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; - } - } - } - - 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; -} - -// TODO check if we have a general purpose fork and exec. We may be -// able to get rid of this entirely. -static Status ForkChildForPTraceDebugging(const char *path, char const *argv[], - char const *envp[], ::pid_t *pid, - int *pty_fd) { - Status 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. - 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) { - // Status 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(); - } - } - return error; -} - -static Status -CreatePosixSpawnFileAction(const FileAction &action, - posix_spawn_file_actions_t *file_actions) { - Status 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; - } - 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; - } - 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; - } - - case FileAction::eFileActionNone: - default: - LLDB_LOGF(log, "%s(): unsupported file action %u", __FUNCTION__, - action.GetAction()); - break; - } - - return error; -} - -static Status PosixSpawnChildForPTraceDebugging(const char *path, - ProcessLaunchInfo &launch_info, - ::pid_t *pid, - cpu_type_t *actual_cpu_type) { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - 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) { - LLDB_LOGF(log, "::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) { - LLDB_LOG(log, - "::posix_spawnattr_setflags(&attr, " - "POSIX_SPAWN_START_SUSPENDED{0}) failed: {1}", - flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" - : "", - llvm::sys::StrError(error_code)); - error.SetError(error_code, eErrorTypePOSIX); - return error; - } - -#if !defined(__arm__) - - // We don't need to do this for ARM, and we really shouldn't now that we have - // multiple CPU subtypes and no posix_spawnattr call that allows us to set - // which CPU subtype to launch... - 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) { - LLDB_LOG(log, - "::posix_spawnattr_setbinpref_np(&attr, 1, " - "cpu_type = {0:x8}, count => {1}): {2}", - desired_cpu_type, ocount, llvm::sys::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 - - posix_spawn_file_actions_t file_actions; - if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) { - LLDB_LOG(log, "::posix_spawn_file_actions_init(&file_actions) failed: {0}", - llvm::sys::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()) { - LLDB_LOGF(log, - "%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) { - LLDB_LOG(log, - "::posix_spawnp(pid => {0}, path = '{1}', file_actions " - "= {2}, attr = {3}, argv = {4}, envp = {5}) failed: {6}", - pid, path, &file_actions, &attr, argv, envp, - llvm::sys::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 (actual_cpu_type) { - *actual_cpu_type = GetCPUTypeForLocalProcess(*pid); - LLDB_LOGF(log, - "%s(): cpu type for launched process pid=%i: " - "cpu_type=0x%8.8x", - __FUNCTION__, *pid, *actual_cpu_type); - } - - return error; -} - -Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, - LaunchFlavor *launch_flavor) { - Status 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; - } -#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; - } -#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 - } - - // Attempt to resolve the binary name to an absolute path. - char resolved_path[PATH_MAX]; - resolved_path[0] = '\0'; - - LLDB_LOGF(log, "%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))) { - LLDB_LOGF(log, - "%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 { - LLDB_LOGF(log, "%s(): resolved given binary path to: \"%s\"", __FUNCTION__, - resolved_path); - } - - 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; - } - - // 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; - -#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; -#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; -#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; - } - - 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 diff --git a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h b/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h deleted file mode 100644 index 0e65b56a143e..000000000000 --- a/lldb/source/Plugins/Process/Darwin/DarwinProcessLauncher.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- DarwinProcessLauncher.h ---------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef DarwinProcessLauncher_h -#define DarwinProcessLauncher_h - -// C headers -#include <mach/machine.h> -#include <sys/types.h> - -// C++ headers -#include <functional> - -// LLDB headers -#include "lldb/lldb-enumerations.h" -#include "lldb/lldb-forward.h" - -#include "LaunchFlavor.h" - -namespace lldb_private { -namespace darwin_process_launcher { -// ============================================================================= -/// Launches a process for debugging. -/// -/// \param[inout] launch_info -/// Specifies details about the process to launch (e.g. path, architecture, -/// etc.). On output, includes the launched ProcessID (pid). -/// -/// \param[out] pty_master_fd -/// Returns the master side of the pseudo-terminal used to communicate -/// with stdin/stdout from the launched process. May be nullptr. -/// -/// \param[out] launch_flavor -/// Contains the launch flavor used when launching the process. -// ============================================================================= -Status -LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, - lldb_private::process_darwin::LaunchFlavor *launch_flavor); - -} // darwin_process_launcher -} // lldb_private - -#endif /* DarwinProcessLauncher_h */ diff --git a/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h b/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h deleted file mode 100644 index cfd76d1b9c3c..000000000000 --- a/lldb/source/Plugins/Process/Darwin/LaunchFlavor.h +++ /dev/null @@ -1,32 +0,0 @@ -//===-- LaunchFlavor.h ---------------------------------------- -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LaunchFlavor_h -#define LaunchFlavor_h - -namespace lldb_private { -namespace process_darwin { - -enum class LaunchFlavor { - Default = 0, - PosixSpawn = 1, - ForkExec = 2, -#ifdef WITH_SPRINGBOARD - SpringBoard = 3, -#endif -#ifdef WITH_BKS - BKS = 4, -#endif -#ifdef WITH_FBS - FBS = 5 -#endif -}; -} -} // namespaces - -#endif /* LaunchFlavor_h */ diff --git a/lldb/source/Plugins/Process/Darwin/MachException.cpp b/lldb/source/Plugins/Process/Darwin/MachException.cpp deleted file mode 100644 index 073ad64b300c..000000000000 --- a/lldb/source/Plugins/Process/Darwin/MachException.cpp +++ /dev/null @@ -1,514 +0,0 @@ -//===-- MachException.cpp ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#include "MachException.h" - -// C includes -#include <errno.h> -#include <sys/ptrace.h> -#include <sys/types.h> - -// C++ includes -#include <mutex> - -// LLDB includes -#include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/Stream.h" - -using namespace lldb; -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); - -// 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); - -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) { - LLDB_LOGF(log, - "::%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) { - LLDB_LOGF(log, - "::%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)); - } - - 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) { - LLDB_LOGF(log, - "::%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; -} - -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)); - - 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]; - - return true; -} - -Status MachException::Message::Receive(mach_port_t port, - mach_msg_option_t options, - mach_msg_timeout_t timeout, - mach_port_t notify_port) { - Status 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 - LLDB_LOGF(log, - "::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) { - LLDB_LOGF(log, - "::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); -} - -bool MachException::Message::CatchExceptionRaise(task_t task) { - bool success = false; - 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)); - LLDB_LOGF(log, - "MachException::Message::%s(): mach_exc_server " - "returned zero...", - __FUNCTION__); - } - g_message = NULL; - return success; -} - -Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, - int signal) { - // Reply to the exception... - Status 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); - LLDB_LOGF(log, - "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); - - if (!error.Success()) { - LLDB_LOGF(log, - "::ptrace(request = PT_THUPDATE, pid = " - "0x%4.4x, tid = 0x%4.4x, signal = %i)", - state_pid, state.thread_port, soft_signal); - return error; - } - } - } - - LLDB_LOGF(log, - "::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) { - LLDB_LOGF(log, - "mach_msg(): returned an error when replying " - "to a mach exception: error = %u (%s)", - error.GetError(), error.AsCString()); - } else { - LLDB_LOGF(log, "::mach_msg() - failed (child of task): %u (%s)", - error.GetError(), error.AsCString()); - } - } - - 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) - -// Don't listen for EXC_RESOURCE, it should really get handled by the system -// handler. - -#ifndef EXC_RESOURCE -#define EXC_RESOURCE 11 -#endif - -#ifndef EXC_MASK_RESOURCE -#define EXC_MASK_RESOURCE (1 << EXC_RESOURCE) -#endif - -#define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE) - -Status MachException::PortInfo::Save(task_t task) { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - - LLDB_LOGF(log, "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; - - 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()) { - LLDB_LOGF(log, - "::task_get_exception_ports(task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors)", - task, mask, count); - } else { - LLDB_LOGF(log, - "::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()) { - LLDB_LOGF(log, - "::task_get_exception_ports(task = 0x%4.4x, " - "mask = 0x%x, maskCnt => %u, ports, behaviors, " - "flavors)", - task, mask, count); - } else { - LLDB_LOGF(log, - "::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; - } - return error; -} - -Status MachException::PortInfo::Restore(task_t task) { - Status error; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - - LLDB_LOGF(log, "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()) { - LLDB_LOGF(log, - "::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 { - LLDB_LOGF(log, - "::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; -} - -const char *MachException::Name(exception_type_t exc_type) { - switch (exc_type) { - case EXC_BAD_ACCESS: - return "EXC_BAD_ACCESS"; - case EXC_BAD_INSTRUCTION: - return "EXC_BAD_INSTRUCTION"; - case EXC_ARITHMETIC: - return "EXC_ARITHMETIC"; - case EXC_EMULATION: - return "EXC_EMULATION"; - case EXC_SOFTWARE: - return "EXC_SOFTWARE"; - case EXC_BREAKPOINT: - return "EXC_BREAKPOINT"; - case EXC_SYSCALL: - return "EXC_SYSCALL"; - case EXC_MACH_SYSCALL: - return "EXC_MACH_SYSCALL"; - case EXC_RPC_ALERT: - return "EXC_RPC_ALERT"; -#ifdef EXC_CRASH - case EXC_CRASH: - return "EXC_CRASH"; -#endif - default: - break; - } - return NULL; -} diff --git a/lldb/source/Plugins/Process/Darwin/MachException.h b/lldb/source/Plugins/Process/Darwin/MachException.h deleted file mode 100644 index 18e49173b020..000000000000 --- a/lldb/source/Plugins/Process/Darwin/MachException.h +++ /dev/null @@ -1,139 +0,0 @@ -//===-- MachException.h -----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#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" - -namespace lldb_private { -namespace process_darwin { - -typedef union MachMessageTag { - mach_msg_header_t hdr; - char data[1024]; -} MachMessage; - -class MachException { -public: - struct PortInfo { - exception_mask_t mask; // the exception mask for this device which may be a - // subset of EXC_MASK_ALL... - exception_mask_t masks[EXC_TYPES_COUNT]; - mach_port_t ports[EXC_TYPES_COUNT]; - exception_behavior_t behaviors[EXC_TYPES_COUNT]; - thread_state_flavor_t flavors[EXC_TYPES_COUNT]; - mach_msg_type_number_t count; - - Status Save(task_t task); - - Status 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); - - Status Reply(::pid_t inferior_pid, task_t inferior_task, int signal); - - Status Receive(mach_port_t receive_port, mach_msg_option_t options, - mach_msg_timeout_t timeout, - mach_port_t notify_port = MACH_PORT_NULL); - - void Dump(Stream &stream) const; - - typedef std::vector<Message> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - }; - - enum { - e_actionForward, // Forward signal to inferior process - e_actionStop, // Stop when this signal is received - }; - struct Action { - task_t task_port; // Set to TASK_NULL for any TASK - thread_t thread_port; // Set to THREAD_NULL for any thread - exception_type_t exc_mask; // Mach exception mask to watch for - std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to - // exception data, or - // empty to ignore - // exc_data value for - // exception - std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare - // to exception data - // after masking, or - // empty to ignore - // exc_data value - // for exception - uint8_t flags; // Action flags describing what to do with the exception - }; - - static const char *Name(exception_type_t exc_type); -}; - -} // namespace process_darwin -} // namespace lldb_private - -#endif diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp deleted file mode 100644 index 18dbdda9a33b..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ /dev/null @@ -1,1535 +0,0 @@ -//===-- NativeProcessDarwin.cpp ---------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "NativeProcessDarwin.h" - -// C includes -#include <mach/mach_init.h> -#include <mach/mach_traps.h> -#include <sys/ptrace.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -// C++ includes -// LLDB includes -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/StreamString.h" - -#include "CFBundle.h" -#include "CFString.h" -#include "DarwinProcessLauncher.h" - -#include "MachException.h" - -#include "llvm/Support/FileSystem.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_darwin; -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; -}; -} - -// Public Static Methods - -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - Status error; - - // Verify the working directory is valid if one was specified. - FileSpec working_dir(launch_info.GetWorkingDirectory()); - if (working_dir) { - FileInstance::Instance().Resolve(working_dir); - if (!FileSystem::Instance().IsDirectory(working_dir)) { - 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; - - error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor); - - // Handle launch failure. - if (!error.Success()) { - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, - "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()) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s() aborting, failed to finalize" - " the launching of the 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; - return error; -} - -Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - LLDB_LOGF(log, "NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__, - pid); - - // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - 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)); - - if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native " - "delegate"); - return error; - } - - 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() {} - -// Instance methods - -Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, - MainLoop &main_loop) { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - error = StartExceptionThread(); - if (!error.Success()) { - LLDB_LOGF(log, - "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); - - 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; - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): successfully spawned " - "process with pid %" PRIu64, - __FUNCTION__, m_pid); - } else { - error.SetErrorToErrno(); - SetState(eStateExited); - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): error: failed to " - "attach to spawned pid %" PRIu64 " (error=%d (%s))", - __FUNCTION__, m_pid, (int)error.GetError(), error.AsCString()); - return error; - } - } - - LLDB_LOGF(log, "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()) { - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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); - - // Success. - return error; -} - -Status 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::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); - - LLDB_LOGF(log, "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) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): cannot run mach exception " - "thread, mandatory process arg was null", - __FUNCTION__); - return nullptr; - } - - return reinterpret_cast<NativeProcessDarwin *>(arg)->DoExceptionThread(); -} - -void *NativeProcessDarwin::DoExceptionThread() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - - LLDB_LOGF(log, "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; - Status 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)); - LLDB_LOGF(log, - "::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) " - "=> %p", - pid, watchdog.get()); - - if (watchdog.get()) { - ::SBSWatchdogAssertionRenew(watchdog.get()); - - CFTimeInterval watchdogRenewalInterval = - ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get()); - LLDB_LOGF(log, - "::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) - -#ifdef WITH_BKS - 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); - } 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()) { - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, "SBSWatchdogAssertionRenew(%p)", watchdog.get()); - ::SBSWatchdogAssertionRenew(watchdog.get()); - watchdog_elapsed = 0; - } - } -#endif - } else { - LLDB_LOGF(log, - "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()); - } -#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - - LLDB_LOGF(log, "NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__, - this); - return nullptr; -} - -Status NativeProcessDarwin::StartExceptionThread() { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); - - // Make sure we've looked up the inferior port. - TaskPortForProcessID(error); - - // 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; - } - - // Get the mach port for the process monitor. - mach_port_t task_self = mach_task_self(); - - // 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()) { - LLDB_LOGF(log, - "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; - } - - // 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()) { - LLDB_LOGF(log, - "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; - } - - // Save the original state of the exception ports for our child process. - error = SaveExceptionPortInfo(); - if (error.Fail() || (m_exc_port_info.mask == 0)) { - LLDB_LOGF(log, - "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()) { - LLDB_LOGF(log, - "::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()) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): failed to create Mach " - "exception-handling thread: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); - } - - return error; -} - -lldb::addr_t -NativeProcessDarwin::GetDYLDAllImageInfosAddress(Status &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; - } - - // 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; - - 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; -} - -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. - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - - std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex); - LLDB_LOGF(log, - "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; - - // 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; - Status 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) { - LLDB_LOGF(log, - "exec: inferior task port changed " - "from 0x%4.4x to 0x%4.4x", - old_task, new_task); - } - } - } else { - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, - "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; - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): auto " - "resuming due to unhandled interrupt " - "signal %i", - __FUNCTION__, m_auto_resume_signo); - } - m_auto_resume_signo = 0; - } - } else { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): didn't get signal " - "%i after MachProcess::Interrupt()", - __FUNCTION__, m_sent_interrupt_signo); - } - } - } - - // Let all threads recover from stopping and do any clean up based on the - // previous thread state (if any). - m_thread_list.ProcessDidStop(*this); - - // 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 (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 very - // fast start/stops. - struct timespec timeout; - - //DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms - DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms - m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, - &timeout); -#endif - SetState(eStateStopped); - } else { - // Resume without checking our current state. - PrivateResume(); - } - - return m_task; -} - -void NativeProcessDarwin::StartSTDIOThread() { - // TODO implement -} - -Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { - Status 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()) { - LLDB_LOGF(log, - "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 NativeFile(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()) { - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): cannot run waitpid " - "thread, mandatory process arg was null", - __FUNCTION__); - return nullptr; - } - - 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); - } -#endif -} - -void *NativeProcessDarwin::DoWaitpidThread() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - if (m_pid == LLDB_INVALID_PROCESS_ID) { - LLDB_LOGF(log, - "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(); - - Status 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. - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) interrupted, continuing", - __FUNCTION__, m_pid); - continue; - } - - // This error is not okay, abort. - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) => %i, status = %i", - __FUNCTION__, m_pid, child_pid, status); - - // Handle the result. - if (WIFSTOPPED(status)) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ") received a stop, continuing waitpid() loop", - __FUNCTION__, m_pid); - continue; - } else // if (WIFEXITED(status) || WIFSIGNALED(status)) - { - LLDB_LOGF(log, - "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. - LLDB_LOGF(log, - "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; -} - -Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, - int status) { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - size_t bytes_written = 0; - - // Send the pid. - error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written); - if (error.Fail() || (bytes_written < sizeof(pid))) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s() - failed to write " - "waitpid exiting pid to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); - return error; - } - - // Send the status. - bytes_written = 0; - error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written); - if (error.Fail() || (bytes_written < sizeof(status))) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s() - failed to write " - "waitpid exit result to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); - } - return error; -} - -Status NativeProcessDarwin::HandleWaitpidResult() { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // 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))) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s() - failed to read " - "waitpid exiting pid from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); - SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); - return error; - } - - // Read the status. - int status = -1; - error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read); - if (error.Fail() || (bytes_read < sizeof(status))) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s() - failed to read " - "waitpid exit status from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); - SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); - return error; - } - - // Notify the monitor that our state has changed. - LLDB_LOGF(log, - "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); - - SetExitStatus(WaitStatus::Decode(status), notify_status); - return error; -} - -task_t NativeProcessDarwin::TaskPortForProcessID(Status &error, - bool force) const { - if ((m_task == TASK_NULL) || force) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (m_pid == LLDB_INVALID_PROCESS_ID) { - LLDB_LOGF(log, - "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; - LLDB_LOGF(log, - "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) { - LLDB_LOGF(log, - "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()); - } - } - - // Sleep a bit and try again - ::usleep(usec_interval); - } - - // We failed to get the task for the inferior process. Ensure that it is - // cleared out. - m_task = TASK_NULL; - } - return m_task; -} - -void NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - error.SetErrorString("TODO: implement"); -} - -Status NativeProcessDarwin::PrivateResume() { - Status 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) - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): task 0x%x resuming (with " - "unhandled interrupt signal %i)...", - __FUNCTION__, m_task, m_auto_resume_signo); - else - LLDB_LOGF(log, "NativeProcessDarwin::%s(): task 0x%x resuming...", - __FUNCTION__, m_task); - } - - error = ReplyToAllExceptions(); - if (error.Fail()) { - LLDB_LOGF(log, - "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; -} - -Status NativeProcessDarwin::ReplyToAllExceptions() { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - - TaskPortForProcessID(error); - if (error.Fail()) { - LLDB_LOGF(log, "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; - } - - size_t index = 0; - for (auto &message : m_exception_messages) { - if (log) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): replying to exception " - "%zu...", - __FUNCTION__, index++); - } - - 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); - - 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. - LLDB_LOGF(log, - "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; -} - -Status NativeProcessDarwin::ResumeTask() { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - TaskPortForProcessID(error); - if (error.Fail()) { - LLDB_LOGF(log, - "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; - } - - LLDB_LOGF(log, - "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()) { - LLDB_LOGF(log, - "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()) - LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x): success", m_task); - else - LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x) error: %s", m_task, - error.AsCString()); - } - } else { - LLDB_LOGF(log, - "::task_resume(target_task = 0x%4.4x): ignored, " - "already running", - m_task); - } - - return error; -} - -bool NativeProcessDarwin::IsTaskValid() const { - if (m_task == TASK_NULL) - return false; - - 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; - - struct task_basic_info task_info; - return GetTaskBasicInfo(task, &task_info).Success(); -} - -mach_port_t NativeProcessDarwin::GetExceptionPort() const { - return m_exception_port; -} - -bool NativeProcessDarwin::IsExceptionPortValid() const { - return MACH_PORT_VALID(m_exception_port); -} - -Status -NativeProcessDarwin::GetTaskBasicInfo(task_t task, - struct task_basic_info *info) const { - Status 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()) { - LLDB_LOGF(log, - "::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_LLDB_LOGF(log, - "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; -} - -Status NativeProcessDarwin::SuspendTask() { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - if (m_task == TASK_NULL) { - error.SetErrorString("task port is null, cannot suspend task"); - LLDB_LOGF(log, "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) - LLDB_LOGF(log, "::task_suspend(target_task = 0x%4.4x)", m_task); - - return error; -} - -Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) { - Status error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - - LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); - - if (CanResume()) { - m_thread_actions = resume_actions; - error = PrivateResume(); - return error; - } - - auto state = GetState(); - if (state == eStateRunning) { - LLDB_LOGF(log, - "NativeProcessDarwin::%s(): task 0x%x is already " - "running, ignoring...", - __FUNCTION__, TaskPortForProcessID(error)); - 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; -} - -Status NativeProcessDarwin::Halt() { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::Detach() { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::Signal(int signo) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::Interrupt() { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::Kill() { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf, - size_t size, size_t &bytes_read) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, - size_t size, - size_t &bytes_read) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf, - size_t size, size_t &bytes_written) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions, - lldb::addr_t &addr) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -lldb::addr_t NativeProcessDarwin::GetSharedLibraryInfoAddress() { - return LLDB_INVALID_ADDRESS; -} - -size_t NativeProcessDarwin::UpdateThreads() { return 0; } - -bool NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const { - return false; -} - -Status NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size, - bool hardware) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -void NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId) {} - -Status NativeProcessDarwin::GetLoadedModuleFileSpec(const char *module_path, - FileSpec &file_spec) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -Status NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef &file_name, - lldb::addr_t &load_addr) { - Status error; - error.SetErrorString("TODO: implement"); - return error; -} - -// NativeProcessProtocol protected interface -Status NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode( - size_t trap_opcode_size_hint, size_t &actual_opcode_size, - const uint8_t *&trap_opcode_bytes) { - Status 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 deleted file mode 100644 index 6741d4ddc5d8..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.h +++ /dev/null @@ -1,337 +0,0 @@ -//===-- NativeProcessDarwin.h --------------------------------- -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef NativeProcessDarwin_h -#define NativeProcessDarwin_h - -// NOTE: this code should only be compiled on Apple Darwin systems. It is -// not cross-platform code and is not intended to build on any other platform. -// Therefore, platform-specific headers and code are okay here. - -// C includes -#include <mach/mach_types.h> - -// C++ includes -#include <mutex> -#include <unordered_set> - -#include "lldb/Host/Debug.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-types.h" - -#include "LaunchFlavor.h" -#include "MachException.h" -#include "NativeThreadDarwin.h" -#include "NativeThreadListDarwin.h" - -namespace lldb_private { -class Status; -class Scalar; - -namespace process_darwin { - -/// \class NativeProcessDarwin -/// 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 Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); - - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); - -public: - ~NativeProcessDarwin() override; - - // NativeProcessProtocol Interface - Status Resume(const ResumeActionList &resume_actions) override; - - Status Halt() override; - - Status Detach() override; - - Status Signal(int signo) override; - - Status Interrupt() override; - - Status Kill() override; - - Status GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) override; - - Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, - size_t &bytes_read) override; - - Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, - size_t &bytes_read) override; - - Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, - size_t &bytes_written) override; - - Status AllocateMemory(size_t size, uint32_t permissions, - lldb::addr_t &addr) override; - - Status DeallocateMemory(lldb::addr_t addr) override; - - lldb::addr_t GetSharedLibraryInfoAddress() override; - - size_t UpdateThreads() override; - - bool GetArchitecture(ArchSpec &arch) const override; - - Status SetBreakpoint(lldb::addr_t addr, uint32_t size, - bool hardware) override; - - void DoStopIDBumped(uint32_t newBumpId) override; - - Status GetLoadedModuleFileSpec(const char *module_path, - FileSpec &file_spec) override; - - Status 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 Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, - void *data = nullptr, size_t data_size = 0, - long *result = nullptr); - - bool SupportHardwareSingleStepping() const; - -protected: - // NativeProcessProtocol protected interface - Status - GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint, - size_t &actual_opcode_size, - const uint8_t *&trap_opcode_bytes) override; - -private: - /// Mach task-related Member Variables - - // The task port for the inferior process. - mutable task_t m_task; - - // True if the inferior process did an exec since we started - // monitoring it. - bool m_did_exec; - - // The CPU type of this process. - mutable cpu_type_t m_cpu_type; - - /// Exception/Signal Handling Member Variables - - // Exception port on which we will receive child exceptions - mach_port_t m_exception_port; - - // Saved state of the child exception port prior to us installing - // our own intercepting port. - MachException::PortInfo m_exc_port_info; - - // The thread that runs the Mach exception read and reply handler. - pthread_t m_exception_thread; - - // 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; - - // 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. - Status FinalizeLaunch(LaunchFlavor launch_flavor, MainLoop &main_loop); - - Status SaveExceptionPortInfo(); - - void ExceptionMessageReceived(const MachException::Message &message); - - void MaybeRaiseThreadPriority(); - - Status StartExceptionThread(); - - Status SendInferiorExitStatusToMainLoop(::pid_t pid, int status); - - Status HandleWaitpidResult(); - - bool ProcessUsingSpringBoard() const; - - bool ProcessUsingBackBoard() const; - - static void *ExceptionThread(void *arg); - - void *DoExceptionThread(); - - lldb::addr_t GetDYLDAllImageInfosAddress(Status &error) const; - - static uint32_t GetCPUTypeForLocalProcess(::pid_t pid); - - uint32_t GetCPUType() const; - - task_t ExceptionMessageBundleComplete(); - - void StartSTDIOThread(); - - Status StartWaitpidThread(MainLoop &main_loop); - - static void *WaitpidThread(void *arg); - - void *DoWaitpidThread(); - - task_t TaskPortForProcessID(Status &error, bool force = false) const; - - /// Attaches to an existing process. Forms the implementation of - /// Process::DoAttach. - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); - - ::pid_t Attach(lldb::pid_t pid, Status &error); - - Status PrivateResume(); - - Status ReplyToAllExceptions(); - - Status ResumeTask(); - - bool IsTaskValid() const; - - bool IsTaskValid(task_t task) const; - - mach_port_t GetExceptionPort() const; - - bool IsExceptionPortValid() const; - - Status GetTaskBasicInfo(task_t task, struct task_basic_info *info) const; - - Status SuspendTask(); - - static Status SetDefaultPtraceOpts(const lldb::pid_t); - - static void *MonitorThread(void *baton); - - void MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status); - - void WaitForNewThread(::pid_t tid); - - void MonitorSIGTRAP(const siginfo_t &info, NativeThreadDarwin &thread); - - void MonitorTrace(NativeThreadDarwin &thread); - - void MonitorBreakpoint(NativeThreadDarwin &thread); - - void MonitorWatchpoint(NativeThreadDarwin &thread, uint32_t wp_index); - - void MonitorSignal(const siginfo_t &info, NativeThreadDarwin &thread, - bool exited); - - Status SetupSoftwareSingleStepping(NativeThreadDarwin &thread); - - bool HasThreadNoLock(lldb::tid_t thread_id); - - bool StopTrackingThread(lldb::tid_t thread_id); - - NativeThreadDarwinSP AddThread(lldb::tid_t thread_id); - - Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); - - Status FixupBreakpointPCAsNeeded(NativeThreadDarwin &thread); - - /// Writes a siginfo_t structure corresponding to the given thread - /// ID to the memory region pointed to by \p siginfo. - Status 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. - Status GetEventMessage(lldb::tid_t tid, unsigned long *message); - - void NotifyThreadDeath(lldb::tid_t tid); - - Status 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. - Status 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 deleted file mode 100644 index bcd6d8c2c4c1..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp +++ /dev/null @@ -1,281 +0,0 @@ -//===-- NativeThreadDarwin.cpp -------------------------------- -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "NativeThreadDarwin.h" - -// C includes -#include <libproc.h> - -// LLDB includes -#include "lldb/Utility/Stream.h" - -#include "NativeProcessDarwin.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_darwin; - -uint64_t NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID( - ::thread_t mach_port_id) { - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - - auto mach_err = ::thread_info(mach_port_id, THREAD_IDENTIFIER_INFO, - (thread_info_t)&tident, &tident_count); - if (mach_err != KERN_SUCCESS) { - // When we fail to get thread info for the supposed port, assume it is - // really a globally unique thread id already, or return the best thing we - // can, which is the thread port. - return mach_port_id; - } - return tident.thread_id; -} - -NativeThreadDarwin::NativeThreadDarwin(NativeProcessDarwin *process, - bool is_64_bit, - lldb::tid_t unique_thread_id, - ::thread_t mach_thread_port) - : NativeThreadProtocol(process, unique_thread_id), - m_mach_thread_port(mach_thread_port), m_basic_info(), - m_proc_threadinfo() {} - -bool NativeThreadDarwin::GetIdentifierInfo() { - // Don't try to get the thread info once and cache it for the life of the - // thread. It changes over time, for instance if the thread name changes, - // then the thread_handle also changes... So you have to refetch it every - // time. - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - kern_return_t kret = ::thread_info(m_mach_thread_port, THREAD_IDENTIFIER_INFO, - (thread_info_t)&m_ident_info, &count); - return kret == KERN_SUCCESS; - - return false; -} - -std::string NativeThreadDarwin::GetName() { - std::string name; - - if (GetIdentifierInfo()) { - auto process_sp = GetProcess(); - if (!process_sp) { - name = "<unavailable>"; - return name; - } - - int len = ::proc_pidinfo(process_sp->GetID(), PROC_PIDTHREADINFO, - m_ident_info.thread_handle, &m_proc_threadinfo, - sizeof(m_proc_threadinfo)); - - if (len && m_proc_threadinfo.pth_name[0]) - name = m_proc_threadinfo.pth_name; - } - return name; -} - -lldb::StateType NativeThreadDarwin::GetState() { - // TODO implement - return eStateInvalid; -} - -bool NativeThreadDarwin::GetStopReason(ThreadStopInfo &stop_info, - std::string &description) { - // TODO implement - return false; -} - -NativeRegisterContextSP NativeThreadDarwin::GetRegisterContext() { - // TODO implement - return NativeRegisterContextSP(); -} - -Status NativeThreadDarwin::SetWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags, bool hardware) { - Status error; - error.SetErrorString("not yet implemented"); - return error; -} - -Status NativeThreadDarwin::RemoveWatchpoint(lldb::addr_t addr) { - Status error; - error.SetErrorString("not yet implemented"); - return error; -} - -void NativeThreadDarwin::Dump(Stream &stream) const { -// This is what we really want once we have the thread class wired up. -#if 0 - DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", - index, - m_seq_id, - m_unique_id, - GetPC(INVALID_NUB_ADDRESS), - GetSP(INVALID_NUB_ADDRESS), - m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, - m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, - m_basic_info.cpu_usage, - m_basic_info.policy, - m_basic_info.run_state, - thread_run_state, - m_basic_info.flags, - m_basic_info.suspend_count, m_suspend_count, - m_basic_info.sleep_time); - -#else - // Here's all we have right now. - stream.Printf("tid: 0x%8.8" PRIx64 ", thread port: 0x%4.4x", GetID(), - m_mach_thread_port); -#endif -} - -bool NativeThreadDarwin::NotifyException(MachException::Data &exc) { -// TODO implement this. -#if 0 - // Allow the arch specific protocol to process (MachException::Data &)exc - // first before possible reassignment of m_stop_exception with exc. See - // also MachThread::GetStopException(). - bool handled = m_arch_up->NotifyException(exc); - - if (m_stop_exception.IsValid()) - { - // We may have more than one exception for a thread, but we need to - // only remember the one that we will say is the reason we stopped. We - // may have been single stepping and also gotten a signal exception, so - // just remember the most pertinent one. - if (m_stop_exception.IsBreakpoint()) - m_stop_exception = exc; - } - else - { - m_stop_exception = exc; - } - - return handled; -#else - // Pretend we handled it. - return true; -#endif -} - -bool NativeThreadDarwin::ShouldStop(bool &step_more) const { -// TODO: implement this -#if 0 - // See if this thread is at a breakpoint? - DNBBreakpoint *bp = CurrentBreakpoint(); - - if (bp) - { - // This thread is sitting at a breakpoint, ask the breakpoint if we - // should be stopping here. - return true; - } - else - { - if (m_arch_up->StepNotComplete()) - { - step_more = true; - return false; - } - // The thread state is used to let us know what the thread was trying - // to do. MachThread::ThreadWillResume() will set the thread state to - // various values depending if the thread was the current thread and if - // it was to be single stepped, or resumed. - if (GetState() == eStateRunning) - { - // If our state is running, then we should continue as we are in - // the process of stepping over a breakpoint. - return false; - } - else - { - // Stop if we have any kind of valid exception for this thread. - if (GetStopException().IsValid()) - return true; - } - } - return false; -#else - return false; -#endif -} - -void NativeThreadDarwin::ThreadDidStop() { -// TODO implement this. -#if 0 - // This thread has existed prior to resuming under debug nub control, and - // has just been stopped. Do any cleanup that needs to be done after - // running. - - // The thread state and breakpoint will still have the same values as they - // had prior to resuming the thread, so it makes it easy to check if we - // were trying to step a thread, or we tried to resume while being at a - // breakpoint. - - // When this method gets called, the process state is still in the state it - // was in while running so we can act accordingly. - m_arch_up->ThreadDidStop(); - - - // We may have suspended this thread so the primary thread could step - // without worrying about race conditions, so lets restore our suspend - // count. - RestoreSuspendCountAfterStop(); - - // Update the basic information for a thread - MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); - - if (m_basic_info.suspend_count > 0) - SetState(eStateSuspended); - else - SetState(eStateStopped); -#endif -} - -bool NativeThreadDarwin::MachPortNumberIsValid(::thread_t thread) { - return thread != (::thread_t)(0); -} - -const struct thread_basic_info *NativeThreadDarwin::GetBasicInfo() const { - if (GetBasicInfo(m_mach_thread_port, &m_basic_info)) - return &m_basic_info; - return NULL; -} - -bool NativeThreadDarwin::GetBasicInfo(::thread_t thread, - struct thread_basic_info *basicInfoPtr) { - if (MachPortNumberIsValid(thread)) { - unsigned int info_count = THREAD_BASIC_INFO_COUNT; - kern_return_t err = ::thread_info(thread, THREAD_BASIC_INFO, - (thread_info_t)basicInfoPtr, &info_count); - if (err == KERN_SUCCESS) - return true; - } - ::memset(basicInfoPtr, 0, sizeof(struct thread_basic_info)); - return false; -} - -bool NativeThreadDarwin::IsUserReady() const { - if (m_basic_info.run_state == 0) - GetBasicInfo(); - - switch (m_basic_info.run_state) { - default: - case TH_STATE_UNINTERRUPTIBLE: - break; - - case TH_STATE_RUNNING: - case TH_STATE_STOPPED: - case TH_STATE_WAITING: - case TH_STATE_HALTED: - return true; - } - return false; -} - -NativeProcessDarwinSP NativeThreadDarwin::GetNativeProcessDarwinSP() { - return std::static_pointer_cast<NativeProcessDarwin>(GetProcess()); -} diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h b/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h deleted file mode 100644 index 616a9a7b9bf0..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeThreadDarwin.h +++ /dev/null @@ -1,165 +0,0 @@ -//===-- NativeThreadDarwin.h ---------------------------------- -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef NativeThreadDarwin_H -#define NativeThreadDarwin_H - -// C includes -#include <mach/mach_types.h> -#include <sched.h> -#include <sys/proc_info.h> - -// C++ includes -#include <map> -#include <memory> -#include <string> - -// LLDB includes -#include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/lldb-private-forward.h" - -#include "MachException.h" - -namespace lldb_private { -namespace process_darwin { - -class NativeProcessDarwin; -using NativeProcessDarwinSP = std::shared_ptr<NativeProcessDarwin>; - -class NativeThreadListDarwin; - -class NativeThreadDarwin : public NativeThreadProtocol { - friend class NativeProcessDarwin; - friend class NativeThreadListDarwin; - -public: - static uint64_t - GetGloballyUniqueThreadIDForMachPortID(::thread_t mach_port_id); - - NativeThreadDarwin(NativeProcessDarwin *process, bool is_64_bit, - lldb::tid_t unique_thread_id = 0, - ::thread_t mach_thread_port = 0); - - // NativeThreadProtocol Interface - std::string GetName() override; - - lldb::StateType GetState() override; - - bool GetStopReason(ThreadStopInfo &stop_info, - std::string &description) override; - - NativeRegisterContextSP GetRegisterContext() override; - - Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, - bool hardware) override; - - Status RemoveWatchpoint(lldb::addr_t addr) override; - - // New methods that are fine for others to call. - void Dump(Stream &stream) const; - -private: - // Interface for friend classes - - /// Resumes the thread. If \p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Status Resume(uint32_t signo); - - /// Single steps the thread. If \p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Status SingleStep(uint32_t signo); - - bool NotifyException(MachException::Data &exc); - - bool ShouldStop(bool &step_more) const; - - void ThreadDidStop(); - - void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); - - /// Return true if the thread is stopped. - /// If stopped by a signal, indicate the signo in the signo - /// argument. Otherwise, return LLDB_INVALID_SIGNAL_NUMBER. - bool IsStopped(int *signo); - - const struct thread_basic_info *GetBasicInfo() const; - - static bool GetBasicInfo(::thread_t thread, - struct thread_basic_info *basicInfoPtr); - - bool IsUserReady() const; - - void SetStoppedByExec(); - - void SetStoppedByBreakpoint(); - - void SetStoppedByWatchpoint(uint32_t wp_index); - - bool IsStoppedAtBreakpoint(); - - bool IsStoppedAtWatchpoint(); - - void SetStoppedByTrace(); - - void SetStoppedWithNoReason(); - - void SetExited(); - - Status RequestStop(); - - /// Return the mach thread port number for this thread. - /// - /// \return - /// The mach port number for this thread. Returns NULL_THREAD - /// when the thread is invalid. - thread_t GetMachPortNumber() const { return m_mach_thread_port; } - - static bool MachPortNumberIsValid(::thread_t thread); - - // Private interface - bool GetIdentifierInfo(); - - void MaybeLogStateChange(lldb::StateType new_state); - - NativeProcessDarwinSP GetNativeProcessDarwinSP(); - - void SetStopped(); - - inline void MaybePrepareSingleStepWorkaround(); - - inline void MaybeCleanupSingleStepWorkaround(); - - // Member Variables - - // The mach thread port for the thread. - ::thread_t m_mach_thread_port; - - // The most recently-retrieved thread basic info. - mutable ::thread_basic_info m_basic_info; - - struct proc_threadinfo m_proc_threadinfo; - - thread_identifier_info_data_t m_ident_info; - -#if 0 - lldb::StateType m_state; - ThreadStopInfo m_stop_info; - NativeRegisterContextSP m_reg_context_sp; - std::string m_stop_description; - using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; - WatchpointIndexMap m_watchpoint_index_map; - // cpu_set_t m_original_cpu_set; // For single-step workaround. -#endif -}; - -typedef std::shared_ptr<NativeThreadDarwin> NativeThreadDarwinSP; - -} // namespace process_darwin -} // namespace lldb_private - -#endif // #ifndef NativeThreadDarwin_H diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp deleted file mode 100644 index 1faa5b219cbc..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp +++ /dev/null @@ -1,702 +0,0 @@ -//===-- NativeThreadListDarwin.cpp ------------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#include "NativeThreadListDarwin.h" - -// C includes -#include <inttypes.h> -#include <mach/vm_map.h> -#include <sys/sysctl.h> - -// LLDB includes -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/Stream.h" -#include "lldb/lldb-enumerations.h" - -#include "NativeProcessDarwin.h" -#include "NativeThreadDarwin.h" - -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() {} - -// These methods will be accessed directly from NativeThreadDarwin -#if 0 -nub_state_t -NativeThreadListDarwin::GetState(nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetState(); - return eStateInvalid; -} - -const char * -NativeThreadListDarwin::GetName (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetName(); - return NULL; -} -#endif - -// TODO: figure out if we need to add this to NativeThreadDarwin yet. -#if 0 -ThreadInfo::QoS -NativeThreadListDarwin::GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); - return ThreadInfo::QoS(); -} - -nub_addr_t -NativeThreadListDarwin::GetPThreadT (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetPThreadT(); - return INVALID_NUB_ADDRESS; -} - -nub_addr_t -NativeThreadListDarwin::GetDispatchQueueT (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetDispatchQueueT(); - return INVALID_NUB_ADDRESS; -} - -nub_addr_t -NativeThreadListDarwin::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) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetTSDAddressForThread(plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); - return INVALID_NUB_ADDRESS; -} -#endif - -// TODO implement these -#if 0 -nub_thread_t -NativeThreadListDarwin::SetCurrentThread(nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - { - m_current_thread = thread_sp; - return tid; - } - return INVALID_NUB_THREAD; -} - - -bool -NativeThreadListDarwin::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetStopException().GetStopInfo(stop_info); - return false; -} - -bool -NativeThreadListDarwin::GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info) -{ - thread_t mach_port_number = GetMachPortNumberByThreadID (tid); - - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - return ::thread_info (mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t)ident_info, &count) == KERN_SUCCESS; -} - -void -NativeThreadListDarwin::DumpThreadStoppedReason (nub_thread_t tid) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - thread_sp->GetStopException().DumpStopReason(); -} - -const char * -NativeThreadListDarwin::GetThreadInfo (nub_thread_t tid) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetBasicInfoAsString(); - return NULL; -} - -#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; -} - -// TODO implement -#if 0 -thread_t -NativeThreadListDarwin::GetMachPortNumberByThreadID (nub_thread_t globally_unique_id) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->ThreadID() == globally_unique_id) - { - return m_threads[idx]->MachPortNumber(); - } - } - return 0; -} - -bool -NativeThreadListDarwin::GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value ) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRegisterValue(set, reg, reg_value); - - return false; -} - -bool -NativeThreadListDarwin::SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value ) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SetRegisterValue(set, reg, reg_value); - - return false; -} - -nub_size_t -NativeThreadListDarwin::GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRegisterContext (buf, buf_len); - return 0; -} - -nub_size_t -NativeThreadListDarwin::SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SetRegisterContext (buf, buf_len); - return 0; -} - -uint32_t -NativeThreadListDarwin::SaveRegisterState (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SaveRegisterState (); - return 0; -} - -bool -NativeThreadListDarwin::RestoreRegisterState (nub_thread_t tid, uint32_t save_id) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->RestoreRegisterState (save_id); - return 0; -} -#endif - -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 -#if 0 -nub_thread_t -NativeThreadListDarwin::ThreadIDAtIndex (nub_size_t idx) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - if (idx < m_threads.size()) - return m_threads[idx]->ThreadID(); - return INVALID_NUB_THREAD; -} - -nub_thread_t -NativeThreadListDarwin::CurrentThreadID ( ) -{ - MachThreadSP thread_sp; - CurrentThread(thread_sp); - if (thread_sp.get()) - return thread_sp->ThreadID(); - return INVALID_NUB_THREAD; -} - -#endif - -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); - LLDB_LOGF(log, - "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 (m_is_64_bit) - DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); - else - DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); -#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(); - - Status error; - auto mach_err = ::task_threads(task, &thread_list, &thread_list_count); - error.SetError(mach_err, eErrorTypeMachKernel); - if (error.Fail()) { - LLDB_LOGF(log, - "::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); - } - } - } - - 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); - } - } - return static_cast<uint32_t>(m_threads.size()); -} - -// TODO implement -#if 0 - -void -NativeThreadListDarwin::CurrentThread (MachThreadSP& thread_sp) -{ - // locker will keep a mutex locked until it goes out of scope - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - if (m_current_thread.get() == NULL) - { - // Figure out which thread is going to be our current thread. This is - // currently done by finding the first thread in the list that has a - // valid exception. - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetStopException().IsValid()) - { - m_current_thread = m_threads[idx]; - break; - } - } - } - thread_sp = m_current_thread; -} - -#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::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; - -// 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. - bool run_one_thread; - thread_t solo_thread = THREAD_NULL; - if ((thread_actions.GetSize() > 0) && - (thread_actions.NumActionsWithState(eStateStepping) + - thread_actions.NumActionsWithState (eStateRunning) == 1)) - { - run_one_thread = true; - const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); - size_t num_actions = thread_actions.GetSize(); - for (size_t i = 0; i < num_actions; i++, action_ptr++) - { - if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning) - { - solo_thread = action_ptr->tid; - break; - } - } - } - else - run_one_thread = false; -#endif - - UpdateThreadList(process, true, &new_threads); - -#if 0 - DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS }; - // If we are planning to run only one thread, any new threads should be - // suspended. - if (run_one_thread) - resume_new_threads.state = eStateSuspended; - - const size_t num_new_threads = new_threads.size(); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - MachThread *thread = m_threads[idx].get(); - bool handled = false; - for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) - { - if (thread == new_threads[new_idx].get()) - { - thread->ThreadWillResume(&resume_new_threads); - handled = true; - break; - } - } - - if (!handled) - { - const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true); - // There must always be a thread action for every thread. - assert (thread_action); - bool others_stopped = false; - if (solo_thread == thread->ThreadID()) - others_stopped = true; - thread->ThreadWillResume (thread_action, others_stopped); - } - } - - if (new_threads.size()) - { - for (uint32_t idx = 0; idx < num_new_threads; ++idx) - { - DNBLogThreadedIf (LOG_THREAD, "NativeThreadListDarwin::ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%8.8" PRIx64 ", thread-is-user-ready=%i)", - process->ProcessID(), - process->StopCount(), - new_threads[idx]->ThreadID(), - new_threads[idx]->IsUserReady()); - } - } -#endif -} - -uint32_t NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process) { - std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); - - // 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(); -} - -// Check each thread in our thread list to see if we should notify our client -// of the current halt in execution. -// -// Breakpoints can have callback functions associated with them than can return -// true to stop, or false to continue executing the inferior. -// -// RETURNS -// 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; -} - -// Implement. -#if 0 - -void -NativeThreadListDarwin::NotifyBreakpointChanged (const DNBBreakpoint *bp) -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - m_threads[idx]->NotifyBreakpointChanged(bp); - } -} - - -uint32_t -NativeThreadListDarwin::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const -{ - if (bp != NULL) - { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->EnableHardwareBreakpoint(bp); - } - return INVALID_NUB_HW_INDEX; -} - -bool -NativeThreadListDarwin::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const -{ - if (bp != NULL) - { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->DisableHardwareBreakpoint(bp); - } - return false; -} - -// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> -// MachProcess::EnableWatchpoint() -> -// NativeThreadListDarwin::EnableHardwareWatchpoint(). -uint32_t -NativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const -{ - uint32_t hw_index = INVALID_NUB_HW_INDEX; - if (wp != NULL) - { - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - // On Mac OS X we have to prime the control registers for new threads. - // We do this using the control register data for the first thread, for - // lack of a better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) - { - // We know that idx failed for some reason. Let's rollback the - // transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return INVALID_NUB_HW_INDEX; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - - } - return hw_index; -} - -bool -NativeThreadListDarwin::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const -{ - if (wp != NULL) - { - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - - // On Mac OS X we have to prime the control registers for new threads. - // We do this using the control register data for the first thread, for - // lack of a better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) - { - // We know that idx failed for some reason. Let's rollback the - // transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return false; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - - return true; - } - return false; -} - -uint32_t -NativeThreadListDarwin::NumSupportedHardwareWatchpoints () const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - // Use an arbitrary thread to retrieve the number of supported hardware - // watchpoints. - if (num_threads) - return m_threads[0]->NumSupportedHardwareWatchpoints(); - return 0; -} - -uint32_t -NativeThreadListDarwin::GetThreadIndexForThreadStoppedWithSignal (const int signo) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - uint32_t should_stop = false; - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) - { - if (m_threads[idx]->GetStopException().SoftSignal () == signo) - return idx; - } - return UINT32_MAX; -} - -#endif diff --git a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h b/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h deleted file mode 100644 index 9ab0a7c8c802..000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeThreadListDarwin.h +++ /dev/null @@ -1,138 +0,0 @@ -//===-- NativeThreadListDarwin.h --------------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __NativeThreadListDarwin_h__ -#define __NativeThreadListDarwin_h__ - -#include <memory> -#include <mutex> -#include <vector> - -#include "lldb/lldb-private-forward.h" -#include "lldb/lldb-types.h" - -#include "MachException.h" - -// #include "ThreadInfo.h" - -namespace lldb_private { -namespace process_darwin { - -class NativeBreakpointDarwin; -class NativeProcessDarwin; - -class NativeThreadDarwin; -using NativeThreadDarwinSP = std::shared_ptr<NativeThreadDarwin>; - -class NativeThreadListDarwin { -public: - NativeThreadListDarwin(); - ~NativeThreadListDarwin(); - - void Clear(); - - void Dump(Stream &stream) const; - -// These methods will be accessed directly from NativeThreadDarwin -#if 0 - bool GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const; - bool SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value) const; - nub_size_t GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len); - nub_size_t SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len); - uint32_t SaveRegisterState (nub_thread_t tid); - bool RestoreRegisterState (nub_thread_t tid, uint32_t save_id); -#endif - - const char *GetThreadInfo(lldb::tid_t tid) const; - - void ProcessWillResume(NativeProcessDarwin &process, - const ResumeActionList &thread_actions); - - uint32_t ProcessDidStop(NativeProcessDarwin &process); - - bool NotifyException(MachException::Data &exc); - - bool ShouldStop(bool &step_more); - -// These methods will be accessed directly from NativeThreadDarwin -#if 0 - const char * GetName (nub_thread_t tid); - nub_state_t GetState (nub_thread_t tid); - nub_thread_t SetCurrentThread (nub_thread_t tid); -#endif - -// TODO: figure out if we need to add this to NativeThreadDarwin yet. -#if 0 - ThreadInfo::QoS GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT (nub_thread_t tid); - nub_addr_t GetDispatchQueueT (nub_thread_t tid); - nub_addr_t GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size); -#endif - -// These methods will be accessed directly from NativeThreadDarwin -#if 0 - bool GetThreadStoppedReason (nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const; - void DumpThreadStoppedReason (nub_thread_t tid) const; - bool GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info); -#endif - - size_t GetNumberOfThreads() const; - - lldb::tid_t ThreadIDAtIndex(size_t idx) const; - - lldb::tid_t GetCurrentThreadID(); - - NativeThreadDarwinSP GetCurrentThread(); - - void NotifyBreakpointChanged(const NativeBreakpointDarwin *bp); - - uint32_t EnableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const; - - bool DisableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const; - - uint32_t EnableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const; - - bool DisableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const; - - uint32_t GetNumberOfSupportedHardwareWatchpoints() const; - - size_t GetThreadIndexForThreadStoppedWithSignal(const int signo) const; - - NativeThreadDarwinSP GetThreadByID(lldb::tid_t tid) const; - - NativeThreadDarwinSP - GetThreadByMachPortNumber(::thread_t mach_port_number) const; - - lldb::tid_t GetThreadIDByMachPortNumber(::thread_t mach_port_number) const; - - thread_t GetMachPortNumberByThreadID(lldb::tid_t globally_unique_id) const; - -protected: - typedef std::vector<NativeThreadDarwinSP> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - // Consider having this return an lldb_private::Status. - 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 0a49f96f54a1..48dbddb86cca 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -1,4 +1,4 @@ -//===-- FreeBSDThread.cpp ---------------------------------------*- C++ -*-===// +//===-- FreeBSDThread.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,9 +14,6 @@ #include <sys/types.h> #include <sys/user.h> -#include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/State.h" - #include "FreeBSDThread.h" #include "POSIXStopInfo.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" @@ -26,7 +23,6 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" -#include "Plugins/Process/Utility/UnwindLLDB.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_arm.h" @@ -44,6 +40,8 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" +#include "lldb/Target/UnixSignals.h" +#include "lldb/Target/Unwind.h" #include "lldb/Utility/State.h" #include "llvm/ADT/SmallString.h" @@ -166,7 +164,6 @@ lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() { assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD); switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: - reg_interface = new RegisterInfoPOSIX_arm64(target_arch); break; case llvm::Triple::arm: reg_interface = new RegisterInfoPOSIX_arm(target_arch); @@ -195,7 +192,8 @@ lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: { RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = - new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); + new RegisterContextPOSIXProcessMonitor_arm64( + *this, std::make_unique<RegisterInfoPOSIX_arm64>(target_arch)); m_posix_thread = reg_ctx; m_reg_context_sp.reset(reg_ctx); break; @@ -254,8 +252,7 @@ FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) { if (concrete_frame_idx == 0) reg_ctx_sp = GetRegisterContext(); else { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); + reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); } return reg_ctx_sp; @@ -275,13 +272,6 @@ bool FreeBSDThread::CalculateStopInfo() { return true; } -Unwind *FreeBSDThread::GetUnwinder() { - if (!m_unwinder_up) - m_unwinder_up.reset(new UnwindLLDB(*this)); - - return m_unwinder_up.get(); -} - void FreeBSDThread::DidStop() { // Don't set the thread state to stopped unless we really stopped. } diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h index 6d3c253a519e..774ffb511bc6 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h +++ b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h @@ -102,8 +102,6 @@ protected: void ExitNotify(const ProcessMessage &message); void ExecNotify(const ProcessMessage &message); - lldb_private::Unwind *GetUnwinder() override; - // FreeBSDThread internal API. // POSIXThread override diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp index 71f012944a9a..4e6f3afda0ab 100644 --- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -1,4 +1,4 @@ -//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// +//===-- POSIXStopInfo.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 32e3320150f8..a44080640f6c 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -1,5 +1,4 @@ -//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -//-*-===// +//===-- ProcessFreeBSD.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -57,6 +56,8 @@ using namespace lldb; using namespace lldb_private; +LLDB_PLUGIN_DEFINE(ProcessFreeBSD) + namespace { UnixSignalsSP &GetFreeBSDSignals() { static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals()); @@ -379,7 +380,8 @@ Status ProcessFreeBSD::DoLaunch(Module *module, FileSpec stdout_file_spec{}; FileSpec stderr_file_spec{}; - const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL, 0)}; + const FileSpec dbg_pts_file_spec{ + launch_info.GetPTY().GetSecondaryName(NULL, 0)}; file_action = launch_info.GetFileActionForFD(STDIN_FILENO); stdin_file_spec = diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index ff3fb0a75e2d..6a9209d1214c 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -1,4 +1,4 @@ -//===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===// +//===-- ProcessMonitor.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -855,7 +855,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { // 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(); + terminal.CloseSecondaryFileDescriptor(); // Do not inherit setgid powers. if (setgid(getgid()) != 0) @@ -939,7 +939,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { #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_terminal_fd = terminal.ReleasePrimaryFileDescriptor(); monitor->m_pid = pid; // Set the terminal fd to be in non blocking mode (it simplifies the diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp index f0c4526357cc..4216f68faf5c 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm.cpp -----------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_arm.cpp ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp index 147f4b56a804..d3eafae1e6de 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm64.cpp -----------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_arm64.cpp ----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -22,9 +22,9 @@ 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) {} + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info) + : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {} ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() { lldb::ProcessSP base = CalculateProcess(); diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h index d54d34e89cad..f100d905e28f 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h @@ -17,8 +17,8 @@ class RegisterContextPOSIXProcessMonitor_arm64 public POSIXBreakpointProtocol { public: RegisterContextPOSIXProcessMonitor_arm64( - lldb_private::Thread &thread, uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info); protected: bool ReadGPR(); diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp index db9b5a6a038c..23c76f234c8e 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXProcessMonitor_mips64.cpp -----------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_mips64.cpp ---------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp index 77694733fa39..f8342775a81b 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp ----------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 3046d97f153c..b1739e1e3bd8 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXProcessMonitor_x86.cpp --------------*- C++ -*-===// +//===-- RegisterContextPOSIXProcessMonitor_x86.cpp ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 4313d27e11e9..5109022d80dd 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -1,4 +1,4 @@ -//===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===// +//===-- NativeProcessNetBSD.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -95,7 +95,7 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, Info.GetArchitecture().GetArchitectureName()); std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD( - pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate, Info.GetArchitecture(), mainloop)); // Enable event reporting diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp index a8afa0b20305..03b505c19890 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -1,4 +1,4 @@ -//===-- NativeRegisterContextNetBSD.cpp -------------------------*- C++ -*-===// +//===-- NativeRegisterContextNetBSD.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 05a35401da46..ca4706a65657 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- NativeRegisterContextNetBSD_x86_64.cpp ---------------*- C++ -*-===// +//===-- NativeRegisterContextNetBSD_x86_64.cpp ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#if defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #include "NativeRegisterContextNetBSD_x86_64.h" @@ -16,6 +16,7 @@ #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" // clang-format off @@ -135,9 +136,84 @@ static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) - k_num_dbr_registers_x86_64, "g_dbr_regnums_x86_64 has wrong number of register infos"); +// 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 64-bit registers available via XState. +static const uint32_t g_xstate_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, + // Note: we currently do not provide them but this is needed to avoid + // unnamed groups in SBFrame::GetRegisterContext(). + lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, + lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_xstate_regnums_i386) / sizeof(g_xstate_regnums_i386[0])) - + 1 == + k_num_avx_registers_i386 + k_num_mpx_registers_i386, + "g_xstate_regnums_i386 has wrong number of register infos"); + +// x86 debug registers. +static const uint32_t g_dbr_regnums_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_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) - + 1 == + k_num_dbr_registers_i386, + "g_dbr_regnums_i386 has wrong number of register infos"); + + // Number of register sets provided by this context. enum { k_num_register_sets = 4 }; +// 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}, + {"Extended State Registers", "xstate", + k_num_avx_registers_i386 + k_num_mpx_registers_i386, + g_xstate_regnums_i386}, + {"Debug Registers", "dbr", k_num_dbr_registers_i386, + g_dbr_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, @@ -164,18 +240,23 @@ NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( static RegisterInfoInterface * CreateRegisterInfoInterface(const ArchSpec &target_arch) { - 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 RegisterContextNetBSD_x86_64(target_arch); + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { + // 32-bit hosts run with a RegisterContextNetBSD_i386 context. + return new RegisterContextNetBSD_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 RegisterContextNetBSD_x86_64(target_arch); + } } NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextNetBSD(native_thread, CreateRegisterInfoInterface(target_arch)), - m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {} + m_gpr(), m_fpr(), m_dbr() {} // CONSIDER after local and llgs debugging are merged, register set support can // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. @@ -192,6 +273,8 @@ uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { const RegisterSet * NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { 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: @@ -202,36 +285,162 @@ NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { return nullptr; } +static constexpr int RegNumX86ToX86_64(int regnum) { + switch (regnum) { + case lldb_eax_i386: + return lldb_rax_x86_64; + case lldb_ebx_i386: + return lldb_rbx_x86_64; + case lldb_ecx_i386: + return lldb_rcx_x86_64; + case lldb_edx_i386: + return lldb_rdx_x86_64; + case lldb_edi_i386: + return lldb_rdi_x86_64; + case lldb_esi_i386: + return lldb_rsi_x86_64; + case lldb_ebp_i386: + return lldb_rbp_x86_64; + case lldb_esp_i386: + return lldb_rsp_x86_64; + case lldb_eip_i386: + return lldb_rip_x86_64; + case lldb_eflags_i386: + return lldb_rflags_x86_64; + case lldb_cs_i386: + return lldb_cs_x86_64; + case lldb_fs_i386: + return lldb_fs_x86_64; + case lldb_gs_i386: + return lldb_gs_x86_64; + case lldb_ss_i386: + return lldb_ss_x86_64; + case lldb_ds_i386: + return lldb_ds_x86_64; + case lldb_es_i386: + return lldb_es_x86_64; + case lldb_fctrl_i386: + return lldb_fctrl_x86_64; + case lldb_fstat_i386: + return lldb_fstat_x86_64; + case lldb_ftag_i386: + return lldb_fstat_x86_64; + case lldb_fop_i386: + return lldb_fop_x86_64; + case lldb_fiseg_i386: + return lldb_fiseg_x86_64; + case lldb_fioff_i386: + return lldb_fioff_x86_64; + case lldb_foseg_i386: + return lldb_foseg_x86_64; + case lldb_fooff_i386: + return lldb_fooff_x86_64; + case lldb_mxcsr_i386: + return lldb_mxcsr_x86_64; + case lldb_mxcsrmask_i386: + return lldb_mxcsrmask_x86_64; + case lldb_st0_i386: + case lldb_st1_i386: + case lldb_st2_i386: + case lldb_st3_i386: + case lldb_st4_i386: + case lldb_st5_i386: + case lldb_st6_i386: + case lldb_st7_i386: + return lldb_st0_x86_64 + regnum - lldb_st0_i386; + case lldb_mm0_i386: + case lldb_mm1_i386: + case lldb_mm2_i386: + case lldb_mm3_i386: + case lldb_mm4_i386: + case lldb_mm5_i386: + case lldb_mm6_i386: + case lldb_mm7_i386: + return lldb_mm0_x86_64 + regnum - lldb_mm0_i386; + case lldb_xmm0_i386: + case lldb_xmm1_i386: + case lldb_xmm2_i386: + case lldb_xmm3_i386: + case lldb_xmm4_i386: + case lldb_xmm5_i386: + case lldb_xmm6_i386: + case lldb_xmm7_i386: + return lldb_xmm0_x86_64 + regnum - lldb_xmm0_i386; + case lldb_ymm0_i386: + case lldb_ymm1_i386: + case lldb_ymm2_i386: + case lldb_ymm3_i386: + case lldb_ymm4_i386: + case lldb_ymm5_i386: + case lldb_ymm6_i386: + case lldb_ymm7_i386: + return lldb_ymm0_x86_64 + regnum - lldb_ymm0_i386; + case lldb_dr0_i386: + case lldb_dr1_i386: + case lldb_dr2_i386: + case lldb_dr3_i386: + case lldb_dr4_i386: + case lldb_dr5_i386: + case lldb_dr6_i386: + case lldb_dr7_i386: + return lldb_dr0_x86_64 + regnum - lldb_dr0_i386; + default: + assert(false && "Unhandled i386 register."); + return 0; + } +} + int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( int reg_num) const { - if (reg_num <= k_last_gpr_x86_64) - return GPRegSet; - else if (reg_num <= k_last_fpr_x86_64) - return FPRegSet; - else if (reg_num <= k_last_avx_x86_64) - return XStateRegSet; // AVX - else if (reg_num <= k_last_mpxr_x86_64) - return -1; // MPXR - else if (reg_num <= k_last_mpxc_x86_64) - return -1; // MPXC - else if (reg_num <= lldb_dr7_x86_64) - return DBRegSet; // DBR - else + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + if (reg_num <= k_last_gpr_i386) + return GPRegSet; + else if (reg_num <= k_last_fpr_i386) + return FPRegSet; + else if (reg_num <= k_last_avx_i386) + return XStateRegSet; // AVX + else if (reg_num <= lldb_dr7_i386) + return DBRegSet; // DBR + else + return -1; + case llvm::Triple::x86_64: + if (reg_num <= k_last_gpr_x86_64) + return GPRegSet; + else if (reg_num <= k_last_fpr_x86_64) + return FPRegSet; + else if (reg_num <= k_last_avx_x86_64) + return XStateRegSet; // AVX + else if (reg_num <= k_last_mpxr_x86_64) + return -1; // MPXR + else if (reg_num <= k_last_mpxc_x86_64) + return -1; // MPXC + else if (reg_num <= lldb_dr7_x86_64) + return DBRegSet; // DBR + else + return -1; + default: + assert(false && "Unhandled target architecture."); return -1; + } } Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { switch (set) { case GPRegSet: - return DoRegisterSet(PT_GETREGS, &m_gpr_x86_64); + return DoRegisterSet(PT_GETREGS, &m_gpr); case FPRegSet: - return DoRegisterSet(PT_GETFPREGS, &m_fpr_x86_64); +#if defined(__x86_64__) + return DoRegisterSet(PT_GETFPREGS, &m_fpr); +#else + return DoRegisterSet(PT_GETXMMREGS, &m_fpr); +#endif case DBRegSet: - return DoRegisterSet(PT_GETDBREGS, &m_dbr_x86_64); + return DoRegisterSet(PT_GETDBREGS, &m_dbr); case XStateRegSet: #ifdef HAVE_XSTATE { - struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)}; + struct iovec iov = {&m_xstate, sizeof(m_xstate)}; return DoRegisterSet(PT_GETXSTATE, &iov); } #else @@ -244,15 +453,19 @@ Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { switch (set) { case GPRegSet: - return DoRegisterSet(PT_SETREGS, &m_gpr_x86_64); + return DoRegisterSet(PT_SETREGS, &m_gpr); case FPRegSet: - return DoRegisterSet(PT_SETFPREGS, &m_fpr_x86_64); +#if defined(__x86_64__) + return DoRegisterSet(PT_SETFPREGS, &m_fpr); +#else + return DoRegisterSet(PT_SETXMMREGS, &m_fpr); +#endif case DBRegSet: - return DoRegisterSet(PT_SETDBREGS, &m_dbr_x86_64); + return DoRegisterSet(PT_SETDBREGS, &m_dbr); case XStateRegSet: #ifdef HAVE_XSTATE { - struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)}; + struct iovec iov = {&m_xstate, sizeof(m_xstate)}; return DoRegisterSet(PT_SETXSTATE, &iov); } #else @@ -272,7 +485,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + 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. @@ -291,112 +504,175 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86_64: + break; + case llvm::Triple::x86: + reg = RegNumX86ToX86_64(reg); + break; + default: + assert(false && "Unhandled target architecture."); + error.SetErrorString("Unhandled target architecture."); + return error; + } + error = ReadRegisterSet(set); if (error.Fail()) return error; switch (reg) { +#if defined(__x86_64__) case lldb_rax_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RAX]; + reg_value = (uint64_t)m_gpr.regs[_REG_RAX]; break; case lldb_rbx_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBX]; + reg_value = (uint64_t)m_gpr.regs[_REG_RBX]; break; case lldb_rcx_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RCX]; + reg_value = (uint64_t)m_gpr.regs[_REG_RCX]; break; case lldb_rdx_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDX]; + reg_value = (uint64_t)m_gpr.regs[_REG_RDX]; break; case lldb_rdi_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDI]; + reg_value = (uint64_t)m_gpr.regs[_REG_RDI]; break; case lldb_rsi_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSI]; + reg_value = (uint64_t)m_gpr.regs[_REG_RSI]; break; case lldb_rbp_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBP]; + reg_value = (uint64_t)m_gpr.regs[_REG_RBP]; break; case lldb_rsp_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSP]; + reg_value = (uint64_t)m_gpr.regs[_REG_RSP]; break; case lldb_r8_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R8]; + reg_value = (uint64_t)m_gpr.regs[_REG_R8]; break; case lldb_r9_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R9]; + reg_value = (uint64_t)m_gpr.regs[_REG_R9]; break; case lldb_r10_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R10]; + reg_value = (uint64_t)m_gpr.regs[_REG_R10]; break; case lldb_r11_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R11]; + reg_value = (uint64_t)m_gpr.regs[_REG_R11]; break; case lldb_r12_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R12]; + reg_value = (uint64_t)m_gpr.regs[_REG_R12]; break; case lldb_r13_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R13]; + reg_value = (uint64_t)m_gpr.regs[_REG_R13]; break; case lldb_r14_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R14]; + reg_value = (uint64_t)m_gpr.regs[_REG_R14]; break; case lldb_r15_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R15]; + reg_value = (uint64_t)m_gpr.regs[_REG_R15]; break; case lldb_rip_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RIP]; + reg_value = (uint64_t)m_gpr.regs[_REG_RIP]; break; case lldb_rflags_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RFLAGS]; + reg_value = (uint64_t)m_gpr.regs[_REG_RFLAGS]; break; case lldb_cs_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_CS]; + reg_value = (uint64_t)m_gpr.regs[_REG_CS]; break; case lldb_fs_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_FS]; + reg_value = (uint64_t)m_gpr.regs[_REG_FS]; break; case lldb_gs_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_GS]; + reg_value = (uint64_t)m_gpr.regs[_REG_GS]; break; case lldb_ss_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_SS]; + reg_value = (uint64_t)m_gpr.regs[_REG_SS]; break; case lldb_ds_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_DS]; + reg_value = (uint64_t)m_gpr.regs[_REG_DS]; break; case lldb_es_x86_64: - reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES]; + reg_value = (uint64_t)m_gpr.regs[_REG_ES]; + break; +#else + case lldb_rax_x86_64: + reg_value = (uint32_t)m_gpr.r_eax; break; + case lldb_rbx_x86_64: + reg_value = (uint32_t)m_gpr.r_ebx; + break; + case lldb_rcx_x86_64: + reg_value = (uint32_t)m_gpr.r_ecx; + break; + case lldb_rdx_x86_64: + reg_value = (uint32_t)m_gpr.r_edx; + break; + case lldb_rdi_x86_64: + reg_value = (uint32_t)m_gpr.r_edi; + break; + case lldb_rsi_x86_64: + reg_value = (uint32_t)m_gpr.r_esi; + break; + case lldb_rsp_x86_64: + reg_value = (uint32_t)m_gpr.r_esp; + break; + case lldb_rbp_x86_64: + reg_value = (uint32_t)m_gpr.r_ebp; + break; + case lldb_rip_x86_64: + reg_value = (uint32_t)m_gpr.r_eip; + break; + case lldb_rflags_x86_64: + reg_value = (uint32_t)m_gpr.r_eflags; + break; + case lldb_cs_x86_64: + reg_value = (uint32_t)m_gpr.r_cs; + break; + case lldb_fs_x86_64: + reg_value = (uint32_t)m_gpr.r_fs; + break; + case lldb_gs_x86_64: + reg_value = (uint32_t)m_gpr.r_gs; + break; + case lldb_ss_x86_64: + reg_value = (uint32_t)m_gpr.r_ss; + break; + case lldb_ds_x86_64: + reg_value = (uint32_t)m_gpr.r_ds; + break; + case lldb_es_x86_64: + reg_value = (uint32_t)m_gpr.r_es; + break; +#endif case lldb_fctrl_x86_64: - reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw; + reg_value = (uint16_t)m_fpr.fxstate.fx_cw; break; case lldb_fstat_x86_64: - reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw; + reg_value = (uint16_t)m_fpr.fxstate.fx_sw; break; case lldb_ftag_x86_64: - reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw; + reg_value = (uint8_t)m_fpr.fxstate.fx_tw; break; case lldb_fop_x86_64: - reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode; + reg_value = (uint64_t)m_fpr.fxstate.fx_opcode; break; case lldb_fiseg_x86_64: - reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64; + reg_value = (uint64_t)m_fpr.fxstate.fx_ip.fa_64; break; case lldb_fioff_x86_64: - reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off; + reg_value = (uint32_t)m_fpr.fxstate.fx_ip.fa_32.fa_off; break; case lldb_foseg_x86_64: - reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64; + reg_value = (uint64_t)m_fpr.fxstate.fx_dp.fa_64; break; case lldb_fooff_x86_64: - reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off; + reg_value = (uint32_t)m_fpr.fxstate.fx_dp.fa_32.fa_off; break; case lldb_mxcsr_x86_64: - reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr; + reg_value = (uint32_t)m_fpr.fxstate.fx_mxcsr; break; case lldb_mxcsrmask_x86_64: - reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask; + reg_value = (uint32_t)m_fpr.fxstate.fx_mxcsr_mask; break; case lldb_st0_x86_64: case lldb_st1_x86_64: @@ -406,7 +682,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_st5_x86_64: case lldb_st6_x86_64: case lldb_st7_x86_64: - reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], + reg_value.SetBytes(&m_fpr.fxstate.fx_87_ac[reg - lldb_st0_x86_64], reg_info->byte_size, endian::InlHostByteOrder()); break; case lldb_mm0_x86_64: @@ -417,7 +693,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_mm5_x86_64: case lldb_mm6_x86_64: case lldb_mm7_x86_64: - reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], + reg_value.SetBytes(&m_fpr.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], reg_info->byte_size, endian::InlHostByteOrder()); break; case lldb_xmm0_x86_64: @@ -436,7 +712,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_xmm13_x86_64: case lldb_xmm14_x86_64: case lldb_xmm15_x86_64: - reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + reg_value.SetBytes(&m_fpr.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], reg_info->byte_size, endian::InlHostByteOrder()); break; case lldb_ymm0_x86_64: @@ -456,15 +732,15 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_ymm14_x86_64: case lldb_ymm15_x86_64: #ifdef HAVE_XSTATE - if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) || - !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) { + if (!(m_xstate.xs_rfbm & XCR0_SSE) || + !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) { error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel", reg_info->name); } else { uint32_t reg_index = reg - lldb_ymm0_x86_64; YMMReg ymm = XStateToYMM( - m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, - m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); + m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); reg_value.SetBytes(ymm.bytes, reg_info->byte_size, endian::InlHostByteOrder()); } @@ -480,7 +756,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_dr5_x86_64: case lldb_dr6_x86_64: case lldb_dr7_x86_64: - reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64]; + reg_value = (uint64_t)m_dbr.dr[reg - lldb_dr0_x86_64]; break; } @@ -497,7 +773,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( return error; } - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + 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. @@ -516,112 +792,175 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( return error; } + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86_64: + break; + case llvm::Triple::x86: + reg = RegNumX86ToX86_64(reg); + break; + default: + assert(false && "Unhandled target architecture."); + error.SetErrorString("Unhandled target architecture."); + return error; + } + error = ReadRegisterSet(set); if (error.Fail()) return error; switch (reg) { +#if defined(__x86_64__) case lldb_rax_x86_64: - m_gpr_x86_64.regs[_REG_RAX] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RAX] = reg_value.GetAsUInt64(); break; case lldb_rbx_x86_64: - m_gpr_x86_64.regs[_REG_RBX] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RBX] = reg_value.GetAsUInt64(); break; case lldb_rcx_x86_64: - m_gpr_x86_64.regs[_REG_RCX] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RCX] = reg_value.GetAsUInt64(); break; case lldb_rdx_x86_64: - m_gpr_x86_64.regs[_REG_RDX] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RDX] = reg_value.GetAsUInt64(); break; case lldb_rdi_x86_64: - m_gpr_x86_64.regs[_REG_RDI] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RDI] = reg_value.GetAsUInt64(); break; case lldb_rsi_x86_64: - m_gpr_x86_64.regs[_REG_RSI] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RSI] = reg_value.GetAsUInt64(); break; case lldb_rbp_x86_64: - m_gpr_x86_64.regs[_REG_RBP] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RBP] = reg_value.GetAsUInt64(); break; case lldb_rsp_x86_64: - m_gpr_x86_64.regs[_REG_RSP] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RSP] = reg_value.GetAsUInt64(); break; case lldb_r8_x86_64: - m_gpr_x86_64.regs[_REG_R8] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R8] = reg_value.GetAsUInt64(); break; case lldb_r9_x86_64: - m_gpr_x86_64.regs[_REG_R9] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R9] = reg_value.GetAsUInt64(); break; case lldb_r10_x86_64: - m_gpr_x86_64.regs[_REG_R10] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R10] = reg_value.GetAsUInt64(); break; case lldb_r11_x86_64: - m_gpr_x86_64.regs[_REG_R11] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R11] = reg_value.GetAsUInt64(); break; case lldb_r12_x86_64: - m_gpr_x86_64.regs[_REG_R12] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R12] = reg_value.GetAsUInt64(); break; case lldb_r13_x86_64: - m_gpr_x86_64.regs[_REG_R13] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R13] = reg_value.GetAsUInt64(); break; case lldb_r14_x86_64: - m_gpr_x86_64.regs[_REG_R14] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R14] = reg_value.GetAsUInt64(); break; case lldb_r15_x86_64: - m_gpr_x86_64.regs[_REG_R15] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_R15] = reg_value.GetAsUInt64(); break; case lldb_rip_x86_64: - m_gpr_x86_64.regs[_REG_RIP] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RIP] = reg_value.GetAsUInt64(); break; case lldb_rflags_x86_64: - m_gpr_x86_64.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); break; case lldb_cs_x86_64: - m_gpr_x86_64.regs[_REG_CS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_CS] = reg_value.GetAsUInt64(); break; case lldb_fs_x86_64: - m_gpr_x86_64.regs[_REG_FS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_FS] = reg_value.GetAsUInt64(); break; case lldb_gs_x86_64: - m_gpr_x86_64.regs[_REG_GS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_GS] = reg_value.GetAsUInt64(); break; case lldb_ss_x86_64: - m_gpr_x86_64.regs[_REG_SS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_SS] = reg_value.GetAsUInt64(); break; case lldb_ds_x86_64: - m_gpr_x86_64.regs[_REG_DS] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_DS] = reg_value.GetAsUInt64(); break; case lldb_es_x86_64: - m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64(); + m_gpr.regs[_REG_ES] = reg_value.GetAsUInt64(); break; +#else + case lldb_rax_x86_64: + m_gpr.r_eax = reg_value.GetAsUInt32(); + break; + case lldb_rbx_x86_64: + m_gpr.r_ebx = reg_value.GetAsUInt32(); + break; + case lldb_rcx_x86_64: + m_gpr.r_ecx = reg_value.GetAsUInt32(); + break; + case lldb_rdx_x86_64: + m_gpr.r_edx = reg_value.GetAsUInt32(); + break; + case lldb_rdi_x86_64: + m_gpr.r_edi = reg_value.GetAsUInt32(); + break; + case lldb_rsi_x86_64: + m_gpr.r_esi = reg_value.GetAsUInt32(); + break; + case lldb_rsp_x86_64: + m_gpr.r_esp = reg_value.GetAsUInt32(); + break; + case lldb_rbp_x86_64: + m_gpr.r_ebp = reg_value.GetAsUInt32(); + break; + case lldb_rip_x86_64: + m_gpr.r_eip = reg_value.GetAsUInt32(); + break; + case lldb_rflags_x86_64: + m_gpr.r_eflags = reg_value.GetAsUInt32(); + break; + case lldb_cs_x86_64: + m_gpr.r_cs = reg_value.GetAsUInt32(); + break; + case lldb_fs_x86_64: + m_gpr.r_fs = reg_value.GetAsUInt32(); + break; + case lldb_gs_x86_64: + m_gpr.r_gs = reg_value.GetAsUInt32(); + break; + case lldb_ss_x86_64: + m_gpr.r_ss = reg_value.GetAsUInt32(); + break; + case lldb_ds_x86_64: + m_gpr.r_ds = reg_value.GetAsUInt32(); + break; + case lldb_es_x86_64: + m_gpr.r_es = reg_value.GetAsUInt32(); + break; +#endif case lldb_fctrl_x86_64: - m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16(); + m_fpr.fxstate.fx_cw = reg_value.GetAsUInt16(); break; case lldb_fstat_x86_64: - m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16(); + m_fpr.fxstate.fx_sw = reg_value.GetAsUInt16(); break; case lldb_ftag_x86_64: - m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8(); + m_fpr.fxstate.fx_tw = reg_value.GetAsUInt8(); break; case lldb_fop_x86_64: - m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16(); + m_fpr.fxstate.fx_opcode = reg_value.GetAsUInt16(); break; case lldb_fiseg_x86_64: - m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64(); + m_fpr.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64(); break; case lldb_fioff_x86_64: - m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32(); + m_fpr.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32(); break; case lldb_foseg_x86_64: - m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64(); + m_fpr.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64(); break; case lldb_fooff_x86_64: - m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32(); + m_fpr.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32(); break; case lldb_mxcsr_x86_64: - m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32(); + m_fpr.fxstate.fx_mxcsr = reg_value.GetAsUInt32(); break; case lldb_mxcsrmask_x86_64: - m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32(); + m_fpr.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32(); break; case lldb_st0_x86_64: case lldb_st1_x86_64: @@ -631,7 +970,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_st5_x86_64: case lldb_st6_x86_64: case lldb_st7_x86_64: - ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], + ::memcpy(&m_fpr.fxstate.fx_87_ac[reg - lldb_st0_x86_64], reg_value.GetBytes(), reg_value.GetByteSize()); break; case lldb_mm0_x86_64: @@ -642,7 +981,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_mm5_x86_64: case lldb_mm6_x86_64: case lldb_mm7_x86_64: - ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], + ::memcpy(&m_fpr.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], reg_value.GetBytes(), reg_value.GetByteSize()); break; case lldb_xmm0_x86_64: @@ -661,7 +1000,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_xmm13_x86_64: case lldb_xmm14_x86_64: case lldb_xmm15_x86_64: - ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + ::memcpy(&m_fpr.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], reg_value.GetBytes(), reg_value.GetByteSize()); break; case lldb_ymm0_x86_64: @@ -681,8 +1020,8 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_ymm14_x86_64: case lldb_ymm15_x86_64: #ifdef HAVE_XSTATE - if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) || - !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) { + if (!(m_xstate.xs_rfbm & XCR0_SSE) || + !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) { error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel", reg_info->name); } else { @@ -690,8 +1029,8 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( YMMReg ymm; ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); YMMToXState(ymm, - m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, - m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); + m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); } #else error.SetErrorString("XState not supported by the kernel"); @@ -705,7 +1044,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_dr5_x86_64: case lldb_dr6_x86_64: case lldb_dr7_x86_64: - m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64(); + m_dbr.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64(); break; } @@ -722,7 +1061,7 @@ Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( return error; uint8_t *dst = data_sp->GetBytes(); - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); + ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); return error; @@ -742,7 +1081,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { error.SetErrorStringWithFormat( "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, + "data size, expected %zu, actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); return error; } @@ -755,7 +1094,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( __FUNCTION__); return error; } - ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); + ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize()); error = WriteRegisterSet(GPRegSet); if (error.Fail()) @@ -765,13 +1104,25 @@ Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( return error; } +int NativeRegisterContextNetBSD_x86_64::GetDR(int num) const { + assert(num >= 0 && num <= 7); + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + return lldb_dr0_i386 + num; + case llvm::Triple::x86_64: + return lldb_dr0_x86_64 + num; + default: + return -1; + } +} + Status NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { if (wp_index >= NumSupportedHardwareWatchpoints()) return Status("Watchpoint index out of range"); RegisterValue reg_value; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64); + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(6)); Status error = ReadRegister(reg_info, reg_value); if (error.Fail()) { is_hit = false; @@ -808,7 +1159,7 @@ Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index, return Status("Watchpoint index out of range"); RegisterValue reg_value; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64); + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(7)); Status error = ReadRegister(reg_info, reg_value); if (error.Fail()) { is_vacant = false; @@ -848,8 +1199,7 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex( if (!is_vacant) return Status("Watchpoint index not vacant"); - const RegisterInfo *const reg_info_dr7 = - GetRegisterInfoAtIndex(lldb_dr7_x86_64); + const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7)); RegisterValue dr7_value; error = ReadRegister(reg_info_dr7, dr7_value); if (error.Fail()) @@ -874,7 +1224,7 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex( control_bits |= enable_bit | rw_bits | size_bits; const RegisterInfo *const reg_info_drN = - GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + GetRegisterInfoAtIndex(GetDR(wp_index)); RegisterValue drN_value; error = ReadRegister(reg_info_drN, drN_value); if (error.Fail()) @@ -906,8 +1256,7 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint( // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5 // or 6-7 of the debug control register (DR7) - const RegisterInfo *const reg_info_dr7 = - GetRegisterInfoAtIndex(lldb_dr7_x86_64); + const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7)); RegisterValue reg_value; Status error = ReadRegister(reg_info_dr7, reg_value); if (error.Fail()) @@ -924,8 +1273,7 @@ Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of // the debug status register (DR6) - const RegisterInfo *const reg_info_dr6 = - GetRegisterInfoAtIndex(lldb_dr6_x86_64); + const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6)); RegisterValue reg_value; Status error = ReadRegister(reg_info_dr6, reg_value); if (error.Fail()) @@ -940,8 +1288,7 @@ Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() { RegisterValue reg_value; // clear bits {0-4} of the debug status register (DR6) - const RegisterInfo *const reg_info_dr6 = - GetRegisterInfoAtIndex(lldb_dr6_x86_64); + const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6)); Status error = ReadRegister(reg_info_dr6, reg_value); if (error.Fail()) return error; @@ -952,8 +1299,7 @@ Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() { return error; // clear bits {0-7,16-31} of the debug control register (DR7) - const RegisterInfo *const reg_info_dr7 = - GetRegisterInfoAtIndex(lldb_dr7_x86_64); + const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7)); error = ReadRegister(reg_info_dr7, reg_value); if (error.Fail()) return error; @@ -988,7 +1334,7 @@ NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) { return LLDB_INVALID_ADDRESS; RegisterValue reg_value; const RegisterInfo *const reg_info_drN = - GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + GetRegisterInfoAtIndex(GetDR(wp_index)); if (ReadRegister(reg_info_drN, reg_value).Fail()) return LLDB_INVALID_ADDRESS; return reg_value.GetAsUInt64(); @@ -1005,10 +1351,10 @@ Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom( Status res = r_source.ReadRegisterSet(DBRegSet); if (!res.Fail()) { // copy dbregs only if any watchpoints were set - if ((r_source.m_dbr_x86_64.dr[7] & 0xFF) == 0) + if ((r_source.m_dbr.dr[7] & 0xFF) == 0) return res; - m_dbr_x86_64 = r_source.m_dbr_x86_64; + m_dbr = r_source.m_dbr; res = WriteRegisterSet(DBRegSet); } return res; diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h index 54b8a806267f..6c0632f3bce8 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#if defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #ifndef lldb_NativeRegisterContextNetBSD_x86_64_h #define lldb_NativeRegisterContextNetBSD_x86_64_h @@ -81,14 +81,19 @@ private: enum { GPRegSet, FPRegSet, XStateRegSet, DBRegSet }; // Private member variables. - struct reg m_gpr_x86_64; - struct fpreg m_fpr_x86_64; - struct dbreg m_dbr_x86_64; + struct reg m_gpr; +#if defined(__x86_64__) + struct fpreg m_fpr; +#else + struct xmmregs m_fpr; +#endif + struct dbreg m_dbr; #ifdef HAVE_XSTATE - struct xstate m_xstate_x86_64; + struct xstate m_xstate; #endif int GetSetForNativeRegNum(int reg_num) const; + int GetDR(int num) const; Status ReadRegisterSet(uint32_t set); Status WriteRegisterSet(uint32_t set); diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index dd2745d9330e..fe76fb40e0b3 100644 --- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -1,4 +1,4 @@ -//===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// +//===-- NativeThreadNetBSD.cpp --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp index b872269fdfe1..579077b45bf9 100644 --- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp @@ -1,4 +1,4 @@ -//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===// +//===-- CrashReason.cpp ---------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp index 058dc5ae2338..117d12101a0b 100644 --- a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp +++ b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp @@ -1,4 +1,4 @@ -//===-- NativeProcessELF.cpp ---------------------------------- -*- C++ -*-===// +//===-- NativeProcessELF.cpp ----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -107,6 +107,11 @@ lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { return LLDB_INVALID_ADDRESS; } +template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< + llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>(); +template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< + llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>(); + template <typename T> llvm::Expected<SVR4LibraryInfo> NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) { diff --git a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h index 4fb513baebf0..dcfa9290ff50 100644 --- a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h +++ b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -48,6 +48,14 @@ protected: llvm::Optional<lldb::addr_t> m_shared_library_info_addr; }; +// Explicitly declare the two 32/64 bit templates that NativeProcessELF.cpp will +// define. This allows us to keep the template definition here and usable +// elsewhere. +extern template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< + llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>(); +extern template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< + llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>(); + } // namespace lldb_private -#endif
\ No newline at end of file +#endif diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp index 66286dd3d9e3..4e8c6f1ba2d2 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -1,4 +1,4 @@ -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// +//===-- ProcessMessage.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp index a17558bfe7c6..f4d0803b264a 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -1,5 +1,4 @@ -//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -//-*-===// +//===-- ProcessPOSIXLog.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/ARMDefines.h b/lldb/source/Plugins/Process/Utility/ARMDefines.h index 1f7eb54d10e7..fd3965fade19 100644 --- a/lldb/source/Plugins/Process/Utility/ARMDefines.h +++ b/lldb/source/Plugins/Process/Utility/ARMDefines.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_ARMDefines_h_ -#define lldb_ARMDefines_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMDEFINES_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMDEFINES_H #include "llvm/Support/ErrorHandling.h" @@ -188,4 +188,4 @@ static inline bool ARMConditionPassed(const uint32_t condition, } // namespace lldb_private -#endif // lldb_ARMDefines_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMDEFINES_H diff --git a/lldb/source/Plugins/Process/Utility/ARMUtils.h b/lldb/source/Plugins/Process/Utility/ARMUtils.h index d860348818d3..bbe4c9a35fa6 100644 --- a/lldb/source/Plugins/Process/Utility/ARMUtils.h +++ b/lldb/source/Plugins/Process/Utility/ARMUtils.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_ARMUtils_h_ -#define lldb_ARMUtils_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H #include "ARMDefines.h" #include "InstructionUtils.h" @@ -371,4 +371,4 @@ static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; } } // namespace lldb_private -#endif // lldb_ARMUtils_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.cpp b/lldb/source/Plugins/Process/Utility/AuxVector.cpp index 25a1d0b5af06..685d9d0824f6 100644 --- a/lldb/source/Plugins/Process/Utility/AuxVector.cpp +++ b/lldb/source/Plugins/Process/Utility/AuxVector.cpp @@ -1,4 +1,4 @@ -//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===// +//===-- AuxVector.cpp -----------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h index c16be68aedb1..c8c8b1249413 100644 --- a/lldb/source/Plugins/Process/Utility/AuxVector.h +++ b/lldb/source/Plugins/Process/Utility/AuxVector.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_AuxVector_H_ -#define liblldb_AuxVector_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_AUXVECTOR_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_AUXVECTOR_H #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index a86880af2260..443638aa39f6 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -1,4 +1,4 @@ -//===-- DynamicRegisterInfo.cpp ----------------------------*- C++ -*-===// +//===-- DynamicRegisterInfo.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -742,6 +742,8 @@ const lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo( for (auto ®_info : m_regs) { // We can use pointer comparison since we used a ConstString to set the // "name" member in AddRegister() + assert(ConstString(reg_info.name).GetCString() == reg_info.name && + "reg_info.name not from a ConstString?"); if (reg_info.name == reg_name.GetCString()) { return ®_info; } diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h index aacf547e187d..48939375a504 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_DynamicRegisterInfo_h_ -#define lldb_DynamicRegisterInfo_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_DYNAMICREGISTERINFO_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_DYNAMICREGISTERINFO_H #include <map> #include <vector> @@ -90,4 +90,4 @@ protected: // all registers bool m_finalized = false; }; -#endif // lldb_DynamicRegisterInfo_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_DYNAMICREGISTERINFO_H diff --git a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp index 9f63a594e054..0a4bdc72b364 100644 --- a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp @@ -1,4 +1,4 @@ -//===-- FreeBSDSignals.cpp --------------------------------------*- C++ -*-===// +//===-- FreeBSDSignals.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h index 75462f3c76ff..c4c810e54985 100644 --- a/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h +++ b/lldb/source/Plugins/Process/Utility/FreeBSDSignals.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_FreeBSDSignals_H_ -#define liblldb_FreeBSDSignals_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_FREEBSDSIGNALS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_FREEBSDSIGNALS_H #include "lldb/Target/UnixSignals.h" @@ -24,4 +24,4 @@ private: } // namespace lldb_private -#endif // liblldb_FreeBSDSignals_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_FREEBSDSIGNALS_H diff --git a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp index ed35273ce3fe..427225c14d3b 100644 --- a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteSignals.cpp ------------------------------------*- C++ -*-===// +//===-- GDBRemoteSignals.cpp ----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h index a02dd0604e67..d37757ab60a5 100644 --- a/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h +++ b/lldb/source/Plugins/Process/Utility/GDBRemoteSignals.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteSignals_H_ -#define liblldb_GDBRemoteSignals_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_GDBREMOTESIGNALS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_GDBREMOTESIGNALS_H #include "lldb/Target/UnixSignals.h" @@ -26,4 +26,4 @@ private: } // namespace lldb_private -#endif // liblldb_GDBRemoteSignals_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_GDBREMOTESIGNALS_H diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp index 295c17e474fb..d73b132539f1 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp @@ -1,4 +1,4 @@ -//===-- HistoryThread.cpp ---------------------------------------*- C++ -*-===// +//===-- HistoryThread.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,12 +25,14 @@ using namespace lldb_private; // Constructor HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, - std::vector<lldb::addr_t> pcs) + std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses) : Thread(process, tid, true), m_framelist_mutex(), m_framelist(), m_pcs(pcs), 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_up.reset(new HistoryUnwind(*this, pcs)); + m_unwinder_up = + std::make_unique<HistoryUnwind>(*this, pcs, pcs_are_call_addresses); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); LLDB_LOGF(log, "%p HistoryThread::HistoryThread", static_cast<void *>(this)); } diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.h b/lldb/source/Plugins/Process/Utility/HistoryThread.h index 1e2658640172..a66e0f2d4207 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.h +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_HistoryThread_h_ -#define liblldb_HistoryThread_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYTHREAD_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYTHREAD_H #include <mutex> @@ -33,7 +33,8 @@ namespace lldb_private { class HistoryThread : public lldb_private::Thread { public: HistoryThread(lldb_private::Process &process, lldb::tid_t tid, - std::vector<lldb::addr_t> pcs); + std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses = false); ~HistoryThread() override; @@ -88,4 +89,4 @@ protected: } // namespace lldb_private -#endif // liblldb_HistoryThread_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYTHREAD_H diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp index 83fdb011f5a1..9b9522955de9 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -1,4 +1,4 @@ -//===-- HistoryUnwind.cpp ---------------------------------------*- C++ -*-===// +//===-- HistoryUnwind.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -23,8 +23,10 @@ using namespace lldb_private; // Constructor -HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs) - : Unwind(thread), m_pcs(pcs) {} +HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses) + : Unwind(thread), m_pcs(pcs), + m_pcs_are_call_addresses(pcs_are_call_addresses) {} // Destructor @@ -59,7 +61,10 @@ bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, if (frame_idx < m_pcs.size()) { cfa = frame_idx; pc = m_pcs[frame_idx]; - behaves_like_zeroth_frame = (frame_idx == 0); + if (m_pcs_are_call_addresses) + behaves_like_zeroth_frame = true; + else + behaves_like_zeroth_frame = (frame_idx == 0); return true; } return false; diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h index 4d16608bd8c2..cb72b5d0a176 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_HistoryUnwind_h_ -#define liblldb_HistoryUnwind_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYUNWIND_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYUNWIND_H #include <vector> @@ -18,7 +18,8 @@ namespace lldb_private { class HistoryUnwind : public lldb_private::Unwind { public: - HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs); + HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses = false); ~HistoryUnwind() override; @@ -35,8 +36,11 @@ protected: private: std::vector<lldb::addr_t> m_pcs; + /// This boolean indicates that the PCs in the non-0 frames are call + /// addresses and not return addresses. + bool m_pcs_are_call_addresses; }; } // namespace lldb_private -#endif // liblldb_HistoryUnwind_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_HISTORYUNWIND_H diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index ee939b01d350..0f331933f2ea 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -1,4 +1,4 @@ -//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===// +//===-- InferiorCallPOSIX.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h index 2008c5fe0b91..3623e10194f9 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_InferiorCallPOSIX_h_ -#define lldb_InferiorCallPOSIX_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INFERIORCALLPOSIX_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INFERIORCALLPOSIX_H // Inferior execution of POSIX functions. @@ -32,4 +32,4 @@ bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length); } // namespace lldb_private -#endif // lldb_InferiorCallPOSIX_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INFERIORCALLPOSIX_H diff --git a/lldb/source/Plugins/Process/Utility/InstructionUtils.h b/lldb/source/Plugins/Process/Utility/InstructionUtils.h index f74933e691ee..55b89440700b 100644 --- a/lldb/source/Plugins/Process/Utility/InstructionUtils.h +++ b/lldb/source/Plugins/Process/Utility/InstructionUtils.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_InstructionUtils_h_ -#define lldb_InstructionUtils_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INSTRUCTIONUTILS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INSTRUCTIONUTILS_H #include <cassert> #include <cstdint> @@ -113,4 +113,4 @@ static inline int64_t SignedBits(const uint64_t value, const uint64_t msbit, } // namespace lldb_private -#endif // lldb_InstructionUtils_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_INSTRUCTIONUTILS_H diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp index 1ba432aa542b..0c7d9ddc5ac6 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp +++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp @@ -1,4 +1,4 @@ -//===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===// +//===-- LinuxProcMaps.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h index e1f0e48ac5c9..363f248fd416 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h +++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_LinuxProcMaps_H_ -#define liblldb_LinuxProcMaps_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPROCMAPS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPROCMAPS_H #include "lldb/lldb-forward.h" #include "llvm/ADT/StringRef.h" @@ -24,4 +24,4 @@ void ParseLinuxMapRegions(llvm::StringRef linux_map, } // namespace lldb_private -#endif // liblldb_LinuxProcMaps_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPROCMAPS_H diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp index bef47cd26307..4dd619e3bade 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp @@ -1,4 +1,4 @@ -//===-- LinuxSignals.cpp ----------------------------------------*- C++ -*-===// +//===-- LinuxSignals.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.h b/lldb/source/Plugins/Process/Utility/LinuxSignals.h index 7ad8cfcbef68..32c4744a96d0 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxSignals.h +++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_LinuxSignals_H_ -#define liblldb_LinuxSignals_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXSIGNALS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXSIGNALS_H #include "lldb/Target/UnixSignals.h" @@ -24,4 +24,4 @@ private: } // namespace lldb_private -#endif // liblldb_LinuxSignals_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXSIGNALS_H diff --git a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp index d8e5426ab5a5..8f75844277c0 100644 --- a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp @@ -1,5 +1,4 @@ -//===-- MipsLinuxSignals.cpp ----------------------------------------*- C++ -//-*-===// +//===-- MipsLinuxSignals.cpp ----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h index b5e3ed86f568..6b78fc72a91c 100644 --- a/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h +++ b/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_MipsLinuxSignals_H_ -#define liblldb_MipsLinuxSignals_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MIPSLINUXSIGNALS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MIPSLINUXSIGNALS_H #include "lldb/Target/UnixSignals.h" @@ -25,4 +25,4 @@ private: } // namespace lldb_private -#endif // liblldb_MipsLinuxSignals_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MIPSLINUXSIGNALS_H diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp index be61cfdd7374..3a875f7bb39b 100644 --- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp @@ -1,4 +1,4 @@ -//===-- NativeRegisterContextRegisterInfo.cpp -------------------*- C++ -*-===// +//===-- NativeRegisterContextRegisterInfo.cpp -----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h index b285c477cd96..0e96841fd909 100644 --- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h +++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_PLUGINS_PROCESS_UTIILTY_NATIVE_REGISTER_CONTEXT_REGISTER_INFO -#define LLDB_PLUGINS_PROCESS_UTIILTY_NATIVE_REGISTER_CONTEXT_REGISTER_INFO +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NATIVEREGISTERCONTEXTREGISTERINFO_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NATIVEREGISTERCONTEXTREGISTERINFO_H #include <memory> @@ -33,7 +33,7 @@ public: const RegisterInfoInterface &GetRegisterInfoInterface() const; -private: +protected: std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up; }; } diff --git a/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp b/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp index 29967deb7e9b..ffdfd19b4efe 100644 --- a/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp @@ -1,4 +1,4 @@ -//===-- NetBSDSignals.cpp --------------------------------------*- C++ -*-===// +//===-- NetBSDSignals.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/NetBSDSignals.h b/lldb/source/Plugins/Process/Utility/NetBSDSignals.h index bf7399a89060..e6740a304a02 100644 --- a/lldb/source/Plugins/Process/Utility/NetBSDSignals.h +++ b/lldb/source/Plugins/Process/Utility/NetBSDSignals.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_NetBSDSignals_H_ -#define liblldb_NetBSDSignals_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NETBSDSIGNALS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NETBSDSIGNALS_H #include "lldb/Target/UnixSignals.h" @@ -24,4 +24,4 @@ private: } // namespace lldb_private -#endif // liblldb_NetBSDSignals_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NETBSDSIGNALS_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h index ef40162984f1..21582df91fb0 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_REGISTERCONTEXTDARWINCONSTANTS_H -#define LLDB_REGISTERCONTEXTDARWINCONSTANTS_H +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWINCONSTANTS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWINCONSTANTS_H namespace lldb_private { @@ -22,4 +22,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // LLDB_REGISTERCONTEXTDARWINCONSTANTS_H +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWINCONSTANTS_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 173e66904151..eef4541e7edd 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextDarwin_arm.cpp ---------------------------*- C++ -*-===// +//===-- RegisterContextDarwin_arm.cpp -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h index d7c1809a3222..1bd60f756487 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextDarwin_arm_h_ -#define liblldb_RegisterContextDarwin_arm_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM_H #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" @@ -261,4 +261,4 @@ protected: static const lldb_private::RegisterInfo *GetRegisterInfos(); }; -#endif // liblldb_RegisterContextDarwin_arm_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index fa5197cd6bf4..9fc275276699 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -1,5 +1,4 @@ -//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++ -//-*-===// +//===-- RegisterContextDarwin_arm64.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index abb87e3c2348..010e566be32c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextDarwin_arm64_h_ -#define liblldb_RegisterContextDarwin_arm64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" @@ -228,4 +228,4 @@ protected: static const lldb_private::RegisterInfo *GetRegisterInfos(); }; -#endif // liblldb_RegisterContextDarwin_arm64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 959b04700b17..c5ebddc56b6c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextDarwin_i386.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h index e52f0fe63250..9c759c31caed 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextDarwin_i386_h_ -#define liblldb_RegisterContextDarwin_i386_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_I386_H #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" @@ -205,4 +205,4 @@ protected: static const lldb_private::RegisterInfo *GetRegisterInfos(); }; -#endif // liblldb_RegisterContextDarwin_i386_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_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 22088a7d6448..38cd00aea9cc 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextDarwin_x86_64.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextDarwin_x86_64.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h index 1a65a4f28b33..d9ba8d0b2319 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextDarwin_x86_64_h_ -#define liblldb_RegisterContextDarwin_x86_64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" @@ -210,4 +210,4 @@ protected: static const lldb_private::RegisterInfo *GetRegisterInfos(); }; -#endif // liblldb_RegisterContextDarwin_x86_64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp index 6832b6095931..4c2e291c62d6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp @@ -1,5 +1,4 @@ -//===-- RegisterContextDummy.cpp ---------------------------------*- C++ -//-*-===// +//===-- RegisterContextDummy.cpp ------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h index bdaa2217d207..de98767693fe 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_RegisterContextDummy_h_ -#define lldb_RegisterContextDummy_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDUMMY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDUMMY_H #include <vector> @@ -56,9 +56,10 @@ private: lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only) lldb_private::RegisterInfo m_pc_reg_info; - DISALLOW_COPY_AND_ASSIGN(RegisterContextDummy); + RegisterContextDummy(const RegisterContextDummy &) = delete; + const RegisterContextDummy &operator=(const RegisterContextDummy &) = delete; }; } // namespace lldb_private -#endif // lldb_RegisterContextDummy_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDUMMY_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp index b90b38108267..10d346a3cb7e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_i386.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_i386.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h index 7aadf3a0a4c9..5a3e5b0551d6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_i386_H_ -#define liblldb_RegisterContextFreeBSD_i386_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_I386_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp index 4331ef5ad14e..0c5d34f345db 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_mips64.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_mips64.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h index 96f02b4440c5..39968eacf475 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_mips64_H_ -#define liblldb_RegisterContextFreeBSD_mips64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_MIPS64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_MIPS64_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 4f869eb3b177..9fe6255d698e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_powerpc.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_powerpc.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h index ba2751194d16..7e4c43ba908a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_powerpc_h_ -#define liblldb_RegisterContextFreeBSD_powerpc_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_POWERPC_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_POWERPC_H #include "RegisterInfoInterface.h" @@ -49,4 +49,4 @@ public: uint32_t GetRegisterCount() const override; }; -#endif // liblldb_RegisterContextFreeBSD_powerpc_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_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 bcf3951ee077..c1f390ade9b9 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_x86_64.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_x86_64.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h index c379e1a5cd75..d0f69fde1817 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ -#define liblldb_RegisterContextFreeBSD_x86_64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTFREEBSD_X86_64_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp index c19a2bfae668..577958738900 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp @@ -1,5 +1,4 @@ -//===-- RegisterContextHistory.cpp ---------------------------------*- C++ -//-*-===// +//===-- RegisterContextHistory.cpp ----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h index 952e4263d955..407640d2bdb9 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_RegisterContextHistory_h_ -#define lldb_RegisterContextHistory_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTHISTORY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTHISTORY_H #include <vector> @@ -58,8 +58,10 @@ private: lldb::addr_t m_pc_value; - DISALLOW_COPY_AND_ASSIGN(RegisterContextHistory); + RegisterContextHistory(const RegisterContextHistory &) = delete; + const RegisterContextHistory & + operator=(const RegisterContextHistory &) = delete; }; } // namespace lldb_private -#endif // lldb_RegisterContextHistory_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTHISTORY_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp deleted file mode 100644 index 49a589f14989..000000000000 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ /dev/null @@ -1,2198 +0,0 @@ -//===-- RegisterContextLLDB.cpp --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Address.h" -#include "lldb/Core/AddressRange.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DWARFExpression.h" -#include "lldb/Symbol/ArmUnwindInfo.h" -#include "lldb/Symbol/CallFrameInfo.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" -#include "lldb/Symbol/FuncUnwinders.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/SymbolFile.h" -#include "lldb/Target/ABI.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/SectionLoadList.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/lldb-private.h" - -#include "RegisterContextLLDB.h" - -#include <memory> - -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(); -} - -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_afa(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; - - // 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; - - // 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; -} - -// 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() == nullptr) { - m_frame_type = eNotAValidFrame; - UnwindLogMsg("frame does not have a register context"); - return; - } - - addr_t current_pc = reg_ctx_sp->GetPC(); - - 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"); - } - - AddressRange addr_range; - m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); - - 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); - } - - 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.GetData()); - } - } - - if (!active_row.get()) { - UnwindLogMsg("could not find an unwindplan row for this frame's pc"); - m_frame_type = eNotAValidFrame; - return; - } - - if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), 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->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_thread); - - 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; - } - } else - ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); - - UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 - " afa is 0x%" PRIx64 " using %s UnwindPlan", - (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), - (uint64_t)m_cfa, - (uint64_t)m_afa, - m_full_unwind_plan_sp->GetSourceName().GetCString()); -} - -// 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; - } - - addr_t pc; - if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { - UnwindLogMsg("could not get pc value"); - m_frame_type = eNotAValidFrame; - 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); - - 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) { - m_frame_type = eNotAValidFrame; - UnwindLogMsg("this frame has a pc of 0x0"); - return; - } - } - - const bool allow_section_end = true; - m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end); - - // 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 (abi) { - m_fast_unwind_plan_sp.reset(); - m_full_unwind_plan_sp = - std::make_shared<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 (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) { - UnwindLogMsg("failed to get cfa value"); - if (m_frame_type != eSkipFrame) // don't override eSkipFrame - { - m_frame_type = eNotAValidFrame; - } - return; - } - - ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa); - - // 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 " afa is 0x%" PRIx64, - (uint64_t)m_cfa, (uint64_t)m_afa); - return; - } - m_frame_type = eNotAValidFrame; - UnwindLogMsg("could not find any symbol for this pc, or a default unwind " - "plan, to continue unwind."); - return; - } - - AddressRange addr_range; - m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); - - 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); - } - - bool decr_pc_and_recompute_addr_range; - - if (!m_sym_ctx_valid) { - // Always decrement and recompute if the symbol lookup failed - decr_pc_and_recompute_addr_range = true; - } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame || - GetNextFrame()->m_frame_type == eDebuggerFrame) { - // Don't decrement if we're "above" an asynchronous event like - // sigtramp. - decr_pc_and_recompute_addr_range = false; - } else if (!addr_range.GetBaseAddress().IsValid() || - addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || - addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { - // If our "current" pc isn't the start of a function, no need - // to decrement and recompute. - decr_pc_and_recompute_addr_range = false; - } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { - // Signal dispatch may set the return address of the handler it calls to - // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), - // so do not decrement and recompute if the symbol we already found is a trap - // handler. - decr_pc_and_recompute_addr_range = false; - } else { - // Decrement to find the function containing the call. - 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 = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); - - 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(); - PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp); - 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.GetData()); - } - } 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(); - PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); - 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.GetData()); - } - } - } - - if (!active_row.get()) { - m_frame_type = eNotAValidFrame; - UnwindLogMsg("could not find unwind row for this pc"); - return; - } - - if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) { - UnwindLogMsg("failed to get cfa"); - m_frame_type = eNotAValidFrame; - return; - } - - ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa); - - UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa); - - 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 " afa is 0x%" PRIx64, - (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), - (uint64_t)m_cfa, - (uint64_t)m_afa); -} - -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; } - -// 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, -// 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::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() == nullptr) - return unwind_plan_sp; - - if (IsFrameZero()) - return unwind_plan_sp; - - FuncUnwindersSP func_unwinders_sp( - pc_module_sp->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; - - 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; - } 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, -// 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() : nullptr; - if (abi) { - arch_default_unwind_plan_sp = - std::make_shared<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 == nullptr && m_sym_ctx.symbol == nullptr)) && - 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 = - std::make_shared<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() == nullptr) { - 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->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->GetUnwindTable().GetEHFrameInfo(); - if (eh_frame) { - unwind_plan_sp = std::make_shared<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->GetUnwindTable().GetArmUnwindInfo(); - if (arm_exidx) { - unwind_plan_sp = std::make_shared<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(); - } - - CallFrameInfo *object_file_unwind = - pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo(); - if (object_file_unwind) { - unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); - if (object_file_unwind->GetUnwindPlan(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()); - if (!unwind_plan_sp) - unwind_plan_sp = - func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); - 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()); - if (!unwind_plan_sp) - unwind_plan_sp = - func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); - 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); - 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_thread); - 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 because this " - "is the non-call site unwind plan and this is a " - "zeroth frame", - 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 == 0) { - unwind_plan_sp = - func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry( - m_thread); - if (unwind_plan_sp) { - UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we are at " - "the first instruction of a function", - 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_thread); - } - int valid_offset = -1; - if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { - UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this " - "is the call-site unwind plan", - 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); - } - 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_thread); - 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 because we " - "failed to find a call-site unwind plan that would work", - 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 because we are falling back " - "to the arch default plan", - 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; -} - -size_t RegisterContextLLDB::GetRegisterCount() { - return m_thread.GetRegisterContext()->GetRegisterCount(); -} - -const RegisterInfo *RegisterContextLLDB::GetRegisterInfoAtIndex(size_t reg) { - return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); -} - -size_t RegisterContextLLDB::GetRegisterSetCount() { - return m_thread.GetRegisterContext()->GetRegisterSetCount(); -} - -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); -} - -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: - llvm_unreachable("FIXME debugger inferior function call unwind"); - case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { - Status error(ReadRegisterValueFromMemory( - reg_info, regloc.location.target_memory_location, reg_info->byte_size, - value)); - success = error.Success(); - } break; - default: - llvm_unreachable("Unknown RegisterLocation type."); - } - return success; -} - -bool RegisterContextLLDB::WriteRegisterValueToRegisterLocation( - lldb_private::UnwindLLDB::RegisterLocation regloc, - const RegisterInfo *reg_info, const 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); - 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: - llvm_unreachable("FIXME debugger inferior function call unwind"); - case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { - Status error(WriteRegisterValueToMemory( - reg_info, regloc.location.target_memory_location, reg_info->byte_size, - value)); - success = error.Success(); - } break; - default: - llvm_unreachable("Unknown RegisterLocation type."); - } - return success; -} - -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 this method helps to disambiguate that. - -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 process of getting back on track. - -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; - } - } - } - 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; -} - -// 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; - } - } - - // 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; - } - } - - 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 && 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 (ReadFrameAddress(unwindplan_registerkind, - active_row->GetCFAValue(), cfa_value)) { - can_fetch_cfa = true; - } - } - - have_unwindplan_regloc = can_fetch_pc_value && can_fetch_cfa; - } 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) { - // 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() : nullptr; - 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) { - 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() && - (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.IsAFAPlusOffset()) { - if (m_afa == LLDB_INVALID_ADDRESS) - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - - int offset = unwindplan_regloc.GetOffset(); - regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; - regloc.location.inferred_value = m_afa + offset; - m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; - UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus " - "offset %d [value is 0x%" PRIx64 "]", - regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset, - regloc.location.inferred_value); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - - if (unwindplan_regloc.IsAtAFAPlusOffset()) { - if (m_afa == LLDB_INVALID_ADDRESS) - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - - int offset = unwindplan_regloc.GetOffset(); - regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; - regloc.location.target_memory_location = m_afa + offset; - m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc; - UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at " - "AFA 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); - dwarfexpr.SetRegisterKind(unwindplan_registerkind); - Value cfa_val = Scalar(m_cfa); - cfa_val.SetValueType(Value::eValueTypeLoadAddress); - Value result; - Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, 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)); - - // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are - // unsupported. - - 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. -// -// 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 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; - } - - // 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; - - // 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; - 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; - - // 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; - addr_t old_afa = m_afa; - - 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::FAValue::unspecified) { - addr_t new_cfa; - if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), - active_row->GetCFAValue(), 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; - return false; - } - m_cfa = new_cfa; - - ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), - active_row->GetAFAValue(), m_afa); - - 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; - m_afa = old_afa; - return false; - } - - if (old_caller_pc_value == new_caller_pc_value && - m_cfa == old_cfa && - m_afa == old_afa) { - 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; - 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()); - - // We've copied the fallback unwind plan into the full - now clear the - // fallback. - m_fallback_unwind_plan_sp.reset(); - PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); - } - - return true; -} - -bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { - 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; - } - - UnwindPlan::RowSP active_row = - m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); - - if (active_row && - active_row->GetCFAValue().GetValueType() != - UnwindPlan::Row::FAValue::unspecified) { - addr_t new_cfa; - if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), - active_row->GetCFAValue(), 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; - } - - ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(), - active_row->GetAFAValue(), m_afa); - - m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; - m_fallback_unwind_plan_sp.reset(); - - m_registers.clear(); - - m_cfa = new_cfa; - - PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); - - UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", - m_full_unwind_plan_sp->GetSourceName().GetCString()); - return true; - } - return false; -} - -void RegisterContextLLDB::PropagateTrapHandlerFlagFromUnwindPlan( - lldb::UnwindPlanSP unwind_plan) { - if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) { - // Unwind plan does not indicate trap handler. Do nothing. We may - // already be flagged as trap handler flag due to the symbol being - // in the trap handler symbol list, and that should take precedence. - return; - } else if (m_frame_type != eNormalFrame) { - // If this is already a trap handler frame, nothing to do. - // If this is a skip or debug or invalid frame, don't override that. - return; - } - - m_frame_type = eTrapHandlerFrame; - - if (m_current_offset_backed_up_one != m_current_offset) { - // We backed up the pc by 1 to compute the symbol context, but - // now need to undo that because the pc of the trap handler - // frame may in fact be the first instruction of a signal return - // trampoline, rather than the instruction after a call. This - // happens on systems where the signal handler dispatch code, rather - // than calling the handler and being returned to, jumps to the - // handler after pushing the address of a return trampoline on the - // stack -- on these systems, when the handler returns, control will - // be transferred to the return trampoline, so that's the best - // symbol we can present in the callstack. - UnwindLogMsg("Resetting current offset and re-doing symbol lookup; " - "old symbol was %s", - GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - m_current_offset_backed_up_one = m_current_offset; - - AddressRange addr_range; - m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); - - UnwindLogMsg("Symbol is now %s", - GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); - - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - Target *target = &process->GetTarget(); - - m_start_pc = addr_range.GetBaseAddress(); - m_current_offset = - m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target); - } -} - -bool RegisterContextLLDB::ReadFrameAddress( - lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa, - addr_t &address) { - RegisterValue reg_value; - - address = LLDB_INVALID_ADDRESS; - addr_t cfa_reg_contents; - - switch (fa.GetValueType()) { - case UnwindPlan::Row::FAValue::isRegisterDereferenced: { - RegisterNumber cfa_reg(m_thread, row_register_kind, - fa.GetRegisterNumber()); - if (ReadGPRValue(cfa_reg, cfa_reg_contents)) { - const RegisterInfo *reg_info = - GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB)); - RegisterValue reg_value; - if (reg_info) { - Status error = ReadRegisterValueFromMemory( - reg_info, cfa_reg_contents, reg_info->byte_size, reg_value); - if (error.Success()) { - address = 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, address); - 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::FAValue::isRegisterPlusOffset: { - RegisterNumber cfa_reg(m_thread, row_register_kind, - fa.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; - } - address = cfa_reg_contents + fa.GetOffset(); - UnwindLogMsg( - "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 - ", offset is %d", - address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB), - cfa_reg_contents, fa.GetOffset()); - return true; - } - break; - } - case UnwindPlan::Row::FAValue::isDWARFExpression: { - ExecutionContext exe_ctx(m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(), - fa.GetDWARFExpressionLength(), - process->GetByteOrder(), - process->GetAddressByteSize()); - ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); - dwarfexpr.SetRegisterKind(row_register_kind); - Value result; - Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, - &error)) { - address = result.GetScalar().ULongLong(); - - UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, - address); - return true; - } - UnwindLogMsg("Failed to set CFA value via DWARF expression: %s", - error.AsCString()); - break; - } - case UnwindPlan::Row::FAValue::isRaSearch: { - Process &process = *m_thread.GetProcess(); - lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset()); - if (return_address_hint == LLDB_INVALID_ADDRESS) - return false; - const unsigned max_iterations = 256; - for (unsigned i = 0; i < max_iterations; ++i) { - Status st; - lldb::addr_t candidate_addr = - return_address_hint + i * process.GetAddressByteSize(); - lldb::addr_t candidate = - process.ReadPointerFromMemory(candidate_addr, st); - if (st.Fail()) { - UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr, - st.AsCString()); - return false; - } - Address addr; - uint32_t permissions; - if (process.GetLoadAddressPermissions(candidate, permissions) && - permissions & lldb::ePermissionsExecutable) { - address = candidate_addr; - UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address); - return true; - } - } - UnwindLogMsg("No suitable CFA found"); - break; - } - default: - return false; - } - return false; -} - -lldb::addr_t RegisterContextLLDB::GetReturnAddressHint(int32_t plan_offset) { - addr_t hint; - if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint)) - return LLDB_INVALID_ADDRESS; - if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol) - return LLDB_INVALID_ADDRESS; - - hint += plan_offset; - - if (auto next = GetNextFrame()) { - if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol) - return LLDB_INVALID_ADDRESS; - if (auto expected_size = - next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize( - *next->m_sym_ctx.symbol)) - hint += *expected_size; - else { - UnwindLogMsgVerbose("Could not retrieve parameter size: %s", - llvm::toString(expected_size.takeError()).c_str()); - return LLDB_INVALID_ADDRESS; - } - } - return hint; -} - -// 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 () { } -// bar () { foo (); } -// main () { bar (); } -// -// stopped in foo() so -// 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 -// 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; - } - - 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); -} - -// 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; - } - - 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); -} - -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); - } - - 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); -} - -// Don't need to implement this one -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; -} - -// 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; -} - -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); -} - -// Retrieve the address of the start of the function of THIS frame - -bool RegisterContextLLDB::GetStartPC(addr_t &start_pc) { - if (!IsValid()) - return false; - - if (!m_start_pc.IsValid()) { - bool read_successfully = ReadPC (start_pc); - if (read_successfully) - { - ProcessSP process_sp (m_thread.GetProcess()); - if (process_sp) - { - ABI *abi = process_sp->GetABI().get(); - if (abi) - start_pc = abi->FixCodeAddress(start_pc); - } - } - return read_successfully; - } - 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; - - 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. - - ProcessSP process_sp (m_thread.GetProcess()); - if (process_sp) - { - ABI *abi = process_sp->GetABI().get(); - if (abi) - pc = abi->FixCodeAddress(pc); - } - - return !(m_all_registers_available == false && - above_trap_handler == false && (pc == 0 || pc == 1)); - } 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 == nullptr) { - if (logmsg) - free(logmsg); - va_end(args); - return; - } - va_end(args); - - LLDB_LOGF(log, "%*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 == nullptr) { - if (logmsg) - free(logmsg); - va_end(args); - return; - } - va_end(args); - - LLDB_LOGF(log, "%*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 deleted file mode 100644 index 114ac35591e7..000000000000 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ /dev/null @@ -1,259 +0,0 @@ -//===-- RegisterContextLLDB.h --------------------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_RegisterContextLLDB_h_ -#define lldb_RegisterContextLLDB_h_ - -#include <vector> - -#include "UnwindLLDB.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/UnwindPlan.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/RegisterNumber.h" -#include "lldb/lldb-private.h" - -namespace lldb_private { - -class UnwindLLDB; - -class RegisterContextLLDB : public lldb_private::RegisterContext { -public: - 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() override = default; - - 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; - - 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 IsValid() const; - - bool IsTrapHandlerFrame() const; - - bool GetCFA(lldb::addr_t &cfa); - - bool GetStartPC(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; - - /// Check if the given unwind plan indicates a signal trap handler, and - /// update frame type and symbol context if so. - void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan); - - // 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 Frame Address register for a given frame. - bool ReadFrameAddress(lldb::RegisterKind register_kind, - UnwindPlan::Row::FAValue &fa, lldb::addr_t &address); - - 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::addr_t GetReturnAddressHint(int32_t plan_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::addr_t m_afa; - 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 - -#endif // lldb_RegisterContextLLDB_h_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index 79979639dc7e..518dc273faf4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_i386.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextLinux_i386.cpp -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index 5567a1ac42e5..ef731a5a7994 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_i386_H_ -#define liblldb_RegisterContextLinux_i386_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_I386_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp index fc60fea79176..837549e2a495 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_mips.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextLinux_mips.cpp -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h index e637dfc15e4d..9b59ab421ff4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_mips_H_ -#define liblldb_RegisterContextLinux_mips_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H #include "RegisterInfoInterface.h" #include "lldb/lldb-private.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp index 3927883c47a4..432a78129fde 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_mips64.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextLinux_mips64.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h index ca0f0140a22d..899f0a40e4ae 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_mips64_H_ -#define liblldb_RegisterContextLinux_mips64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H #include "RegisterInfoInterface.h" #include "lldb/lldb-private.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp index d6401d788ab2..7a8989cd1225 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_s390x.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextLinux_s390x.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h index 10810c97af80..f381f38ecbf9 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_s390x_h_ -#define liblldb_RegisterContextLinux_s390x_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_S390X_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_S390X_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 640d5bc02256..f9d4e23fcde2 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_x86_64.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextLinux_x86_64.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index 02f273cb02c9..ea21b913d5c5 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_x86_64_H_ -#define liblldb_RegisterContextLinux_x86_64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_X86_64_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp deleted file mode 100644 index bc78c1d6160c..000000000000 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "RegisterContextMacOSXFrameBackchain.h" - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Scalar.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/StringExtractorGDBRemote.h" - -using namespace lldb; -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) {} - -// Destructor -RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() {} - -void RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters() { - m_cursor_is_valid = false; -} - -size_t RegisterContextMacOSXFrameBackchain::GetRegisterCount() { - return m_thread.GetRegisterContext()->GetRegisterCount(); -} - -const RegisterInfo * -RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex(size_t reg) { - return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); -} - -size_t RegisterContextMacOSXFrameBackchain::GetRegisterSetCount() { - return m_thread.GetRegisterContext()->GetRegisterSetCount(); -} - -const RegisterSet * -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; - - 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 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__) - 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; -} - -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::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); -} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h deleted file mode 100644 index 36e5538daa8a..000000000000 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- RegisterContextMacOSXFrameBackchain.h -------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_RegisterContextMacOSXFrameBackchain_h_ -#define lldb_RegisterContextMacOSXFrameBackchain_h_ - -#include "lldb/Target/RegisterContext.h" -#include "lldb/lldb-private.h" - -#include "UnwindMacOSXFrameBackchain.h" - -class RegisterContextMacOSXFrameBackchain - : public lldb_private::RegisterContext { -public: - RegisterContextMacOSXFrameBackchain( - lldb_private::Thread &thread, uint32_t concrete_frame_idx, - const UnwindMacOSXFrameBackchain::Cursor &cursor); - - ~RegisterContextMacOSXFrameBackchain() 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; - - 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; - -private: - UnwindMacOSXFrameBackchain::Cursor m_cursor; - bool m_cursor_is_valid; - - 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 c7042ab5137a..1394cb7f00a1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMach_arm.cpp -----------------------------*- C++ -*-===// +//===-- RegisterContextMach_arm.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h index 8b2425a193be..e7c180dbdd27 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.h @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMach_arm_h_ -#define liblldb_RegisterContextMach_arm_h_ - +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_ARM_H #include "RegisterContextDarwin_arm.h" @@ -37,4 +36,4 @@ protected: int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); }; -#endif // liblldb_RegisterContextMach_arm_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_ARM_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp index e631ab9bb26c..b97166b6eebe 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMach_i386.cpp ----------------------------*- C++ -*-===// +//===-- RegisterContextMach_i386.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h index b8835561e98c..09966be60c92 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMach_i386_h_ -#define liblldb_RegisterContextMach_i386_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_I386_H #include "RegisterContextDarwin_i386.h" @@ -32,4 +32,4 @@ protected: int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); }; -#endif // liblldb_RegisterContextMach_i386_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_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 db17d7d88778..8933f136789f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMach_x86_64.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextMach_x86_64.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h index 688009aef8af..2a8a2cca2f8a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMach_x86_64_h_ -#define liblldb_RegisterContextMach_x86_64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_X86_64_H #include "RegisterContextDarwin_x86_64.h" @@ -33,4 +33,4 @@ protected: int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); }; -#endif // liblldb_RegisterContextMach_x86_64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMACH_X86_64_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp index 946d4fa9f8e5..f2d230b54053 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMemory.cpp -------------------------------*- C++ -*-===// +//===-- RegisterContextMemory.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h index 68223eaeffd7..764ee9b97211 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_RegisterContextMemory_h_ -#define lldb_RegisterContextMemory_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMEMORY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMEMORY_H #include <vector> @@ -67,7 +67,9 @@ protected: // context that is stored in memmory private: - DISALLOW_COPY_AND_ASSIGN(RegisterContextMemory); + RegisterContextMemory(const RegisterContextMemory &) = delete; + const RegisterContextMemory & + operator=(const RegisterContextMemory &) = delete; }; -#endif // lldb_RegisterContextMemory_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTMEMORY_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp new file mode 100644 index 000000000000..bd7830e42b42 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp @@ -0,0 +1,96 @@ +//===-- RegisterContextNetBSD_i386.cpp -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include "RegisterContextNetBSD_i386.h" +#include "RegisterContextPOSIX_x86.h" + +using namespace lldb_private; +using namespace lldb; + +// this needs to match 'struct reg' +struct GPR { + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t eip; + uint32_t eflags; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; +}; + +struct FPR_i386 { + uint16_t fctrl; // FPU Control Word (fcw) + uint16_t fstat; // FPU Status Word (fsw) + uint16_t ftag; // FPU Tag Word (ftw) + 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 gpr; + FPR_i386 i387; + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). + uint32_t tlsbase; +}; + +#define DR_SIZE sizeof(((UserArea *)NULL)->u_debugreg[0]) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index])) + +// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. +#define DECLARE_REGISTER_INFOS_I386_STRUCT +#include "RegisterInfos_i386.h" +#undef DECLARE_REGISTER_INFOS_I386_STRUCT + +RegisterContextNetBSD_i386::RegisterContextNetBSD_i386( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} + +size_t RegisterContextNetBSD_i386::GetGPRSize() const { return sizeof(GPR); } + +const RegisterInfo *RegisterContextNetBSD_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 nullptr; + } +} + +uint32_t RegisterContextNetBSD_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/RegisterContextNetBSD_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.h new file mode 100644 index 000000000000..742bb18b8306 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.h @@ -0,0 +1,25 @@ +//===-- RegisterContextNetBSD_i386.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTNETBSD_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTNETBSD_I386_H + +#include "RegisterInfoInterface.h" + +class RegisterContextNetBSD_i386 : public lldb_private::RegisterInfoInterface { +public: + RegisterContextNetBSD_i386(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; +}; + +#endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp index e620ff66c922..21aad92ecda8 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextNetBSD_x86_64.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextNetBSD_x86_64.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RegisterContextNetBSD_x86_64.h" +#include "RegisterContextNetBSD_i386.h" #include "RegisterContextPOSIX_x86.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Compiler.h" @@ -83,9 +84,40 @@ struct UserArea { #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 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<RegisterContextNetBSD_i386> reg_interface( + new RegisterContextNetBSD_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: @@ -97,6 +129,11 @@ PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { static uint32_t PrivateGetRegisterCount(const lldb_private::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])); @@ -106,11 +143,25 @@ PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { } } +static uint32_t +PrivateGetUserRegisterCount(const lldb_private::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; + } +} + 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)) {} + m_register_count(PrivateGetRegisterCount(target_arch)), + m_user_register_count(PrivateGetUserRegisterCount(target_arch)) {} size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } @@ -121,3 +172,7 @@ const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const { uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { return m_register_count; } + +uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const { + return m_user_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 4820ef8d17ba..b7b8d33b7c37 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextNetBSD_x86_64_H_ -#define liblldb_RegisterContextNetBSD_x86_64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTNETBSD_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTNETBSD_X86_64_H #include "RegisterInfoInterface.h" @@ -22,9 +22,12 @@ public: uint32_t GetRegisterCount() const override; + uint32_t GetUserRegisterCount() const override; + private: const lldb_private::RegisterInfo *m_register_info_p; const uint32_t m_register_count; + const uint32_t m_user_register_count; }; #endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp index 06eac6f7f991..7183ffcfd0f6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextOpenBSD_i386.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextOpenBSD_i386.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h index 992ce0959fdf..e6e24525b7fd 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextOpenBSD_i386_H_ -#define liblldb_RegisterContextOpenBSD_i386_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTOPENBSD_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTOPENBSD_I386_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp index e210196d921d..05c1f83efded 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextOpenBSD_x86_64.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextOpenBSD_x86_64.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h index 9c76e7211132..b399c721546a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextOpenBSD_x86_64_H_ -#define liblldb_RegisterContextOpenBSD_x86_64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTOPENBSD_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTOPENBSD_X86_64_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index 821e2aa73b5b..617893b6b3b0 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_arm.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_arm.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -178,35 +178,6 @@ const char *RegisterContextPOSIX_arm::GetRegisterName(unsigned reg) { 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(); - - if (process) - byte_order = process->GetByteOrder(); - return byte_order; -} - 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; - } - - 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 603ba76430e6..d6967f05ed48 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_arm_h_ -#define liblldb_RegisterContextPOSIX_arm_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM_H #include "RegisterInfoInterface.h" #include "lldb-arm-register-enums.h" @@ -44,9 +44,6 @@ public: const char *GetRegisterName(unsigned reg); - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) override; - protected: struct RegInfo { uint32_t num_registers; @@ -95,12 +92,10 @@ protected: 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_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index db1aa1b8b093..8ef587f13e3a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_arm64.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_arm64.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,105 +25,25 @@ 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, gpr_w0_arm64, gpr_w1_arm64, - gpr_w2_arm64, gpr_w3_arm64, gpr_w4_arm64, gpr_w5_arm64, - gpr_w6_arm64, gpr_w7_arm64, gpr_w8_arm64, gpr_w9_arm64, - gpr_w10_arm64, gpr_w11_arm64, gpr_w12_arm64, gpr_w13_arm64, - gpr_w14_arm64, gpr_w15_arm64, gpr_w16_arm64, gpr_w17_arm64, - gpr_w18_arm64, gpr_w19_arm64, gpr_w20_arm64, gpr_w21_arm64, - gpr_w22_arm64, gpr_w23_arm64, gpr_w24_arm64, gpr_w25_arm64, - gpr_w26_arm64, gpr_w27_arm64, gpr_w28_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, - "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_s0_arm64, fpu_s1_arm64, fpu_s2_arm64, fpu_s3_arm64, - fpu_s4_arm64, fpu_s5_arm64, fpu_s6_arm64, fpu_s7_arm64, - fpu_s8_arm64, fpu_s9_arm64, fpu_s10_arm64, fpu_s11_arm64, - fpu_s12_arm64, fpu_s13_arm64, fpu_s14_arm64, fpu_s15_arm64, - fpu_s16_arm64, fpu_s17_arm64, fpu_s18_arm64, fpu_s19_arm64, - fpu_s20_arm64, fpu_s21_arm64, fpu_s22_arm64, fpu_s23_arm64, - fpu_s24_arm64, fpu_s25_arm64, fpu_s26_arm64, fpu_s27_arm64, - fpu_s28_arm64, fpu_s29_arm64, fpu_s30_arm64, fpu_s31_arm64, - - fpu_d0_arm64, fpu_d1_arm64, fpu_d2_arm64, fpu_d3_arm64, - fpu_d4_arm64, fpu_d5_arm64, fpu_d6_arm64, fpu_d7_arm64, - fpu_d8_arm64, fpu_d9_arm64, fpu_d10_arm64, fpu_d11_arm64, - fpu_d12_arm64, fpu_d13_arm64, fpu_d14_arm64, fpu_d15_arm64, - fpu_d16_arm64, fpu_d17_arm64, fpu_d18_arm64, fpu_d19_arm64, - fpu_d20_arm64, fpu_d21_arm64, fpu_d22_arm64, fpu_d23_arm64, - fpu_d24_arm64, fpu_d25_arm64, fpu_d26_arm64, fpu_d27_arm64, - fpu_d28_arm64, fpu_d29_arm64, fpu_d30_arm64, fpu_d31_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, - "g_fpu_regnums_arm64 has wrong number of register infos"); - -// Number of register sets provided by this context. -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}}; - bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg) { - return reg <= m_reg_info.last_gpr; // GPR's come first. + if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_arm64::GPRegSet) + return true; + return false; } bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) { - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); + if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_arm64::FPRegSet) + return true; + return false; } 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_up.reset(register_info); - - switch (register_info->m_target_arch.GetMachine()) { - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - 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; - } + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info) + : lldb_private::RegisterContext(thread, 0), + m_register_info_up(std::move(register_info)) { ::memset(&m_fpr, 0, sizeof m_fpr); } @@ -135,19 +55,15 @@ void RegisterContextPOSIX_arm64::Invalidate() {} 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; + return m_register_info_up->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; + return m_register_info_up->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; + return m_register_info_up->GetRegisterCount(); } size_t RegisterContextPOSIX_arm64::GetGPRSize() { @@ -164,71 +80,23 @@ RegisterContextPOSIX_arm64::GetRegisterInfo() { const lldb_private::RegisterInfo * RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg) { - if (reg < m_reg_info.num_registers) + if (reg < GetRegisterCount()) return &GetRegisterInfo()[reg]; else return nullptr; } 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 m_register_info_up->GetRegisterSetCount(); } const lldb_private::RegisterSet * RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) { - if (IsRegisterSetAvailable(set)) { - switch (m_register_info_up->m_target_arch.GetMachine()) { - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - return &g_reg_sets_arm64[set]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } - } - return nullptr; + return m_register_info_up->GetRegisterSet(set); } 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(); - - if (process) - byte_order = process->GetByteOrder(); - return byte_order; -} - -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; - } - - return LLDB_INVALID_REGNUM; + if (reg < GetRegisterCount()) + return GetRegisterInfo()[reg].name; + return nullptr; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index 49a49b69da6b..c2d5aee7f73c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -6,10 +6,11 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_arm64_h_ -#define liblldb_RegisterContextPOSIX_arm64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM64_H #include "RegisterInfoInterface.h" +#include "RegisterInfoPOSIX_arm64.h" #include "lldb-arm64-register-enums.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/Log.h" @@ -19,8 +20,8 @@ class ProcessMonitor; class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext { public: RegisterContextPOSIX_arm64( - lldb_private::Thread &thread, uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info); ~RegisterContextPOSIX_arm64() override; @@ -44,50 +45,15 @@ public: const char *GetRegisterName(unsigned reg); - 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_up; // 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); + struct RegisterInfoPOSIX_arm64::FPU + m_fpr; // floating-point registers including extended register sets. + std::unique_ptr<RegisterInfoPOSIX_arm64> m_register_info_up; virtual const lldb_private::RegisterInfo *GetRegisterInfo(); @@ -95,7 +61,7 @@ protected: bool IsFPR(unsigned reg); - lldb::ByteOrder GetByteOrder(); + size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm64::FPU); } virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; @@ -103,4 +69,4 @@ protected: virtual bool WriteFPR() = 0; }; -#endif // liblldb_RegisterContextPOSIX_arm64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_ARM64_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp index f1fa3035b2ef..c41c4bd7a7ea 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_mips64.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_mips64.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -149,17 +149,6 @@ const char *RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) { 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(); - - if (process) - byte_order = process->GetByteOrder(); - return byte_order; -} - bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) { size_t num_sets = GetRegisterSetCount(); diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h index c507e14bd5b6..1843a2a6aff3 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_mips64_h_ -#define liblldb_RegisterContextPOSIX_mips64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_MIPS64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_MIPS64_H #include "RegisterContext_mips.h" #include "RegisterInfoInterface.h" @@ -73,12 +73,10 @@ protected: 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_mips64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_MIPS64_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index a78e9ed37947..cd65b96d373e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -1,5 +1,4 @@ -//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ -//-*-===// +//===-- RegisterContextPOSIX_powerpc.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -158,36 +157,8 @@ const char *RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) { 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(); - - 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; 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; -} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 1a21a717b22b..e2c33461c8f1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_powerpc_h_ -#define liblldb_RegisterContextPOSIX_powerpc_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_POWERPC_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_POWERPC_H #include "RegisterContext_powerpc.h" #include "RegisterInfoInterface.h" @@ -165,9 +165,6 @@ public: const char *GetRegisterName(unsigned reg); - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) override; - protected: uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. @@ -189,8 +186,6 @@ protected: bool IsVMX(unsigned reg); - lldb::ByteOrder GetByteOrder(); - virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; virtual bool ReadVMX() = 0; @@ -199,4 +194,4 @@ protected: virtual bool WriteVMX() = 0; }; -#endif // liblldb_RegisterContextPOSIX_powerpc_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_POWERPC_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp index 02546c0ed16f..f670be2ef3c4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_ppc64le.cpp -------------------------*- C++-*-===// +//===-- RegisterContextPOSIX_ppc64le.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -176,36 +176,8 @@ const char *RegisterContextPOSIX_ppc64le::GetRegisterName(unsigned reg) { return GetRegisterInfo()[reg].name; } -lldb::ByteOrder RegisterContextPOSIX_ppc64le::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; -} - bool RegisterContextPOSIX_ppc64le::IsRegisterSetAvailable(size_t set_index) { size_t num_sets = k_num_register_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_ppc64le::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_ppc64le.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h index 37079775a3c7..66794ec9e9ca 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_ppc64le_h_ -#define liblldb_RegisterContextPOSIX_ppc64le_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_PPC64LE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_PPC64LE_H #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" #include "RegisterInfoInterface.h" @@ -39,9 +39,6 @@ public: const char *GetRegisterName(unsigned reg); - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) override; - protected: // 64-bit general purpose registers. uint64_t m_gpr_ppc64le[k_num_gpr_registers_ppc64le]; @@ -71,7 +68,6 @@ protected: bool IsVSX(unsigned reg); - lldb::ByteOrder GetByteOrder(); }; -#endif // liblldb_RegisterContextPOSIX_ppc64le_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_PPC64LE_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index e040e5075721..e746ec642b38 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_s390x.cpp --------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_s390x.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -161,31 +161,3 @@ const RegisterSet *RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) { } return nullptr; } - -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; -} - -// 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(); - - 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_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h index 54993ce6c3ec..7df732d13ffa 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_s390x_h_ -#define liblldb_RegisterContextPOSIX_s390x_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_S390X_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_S390X_H #include "RegisterContext_s390x.h" #include "RegisterInfoInterface.h" @@ -43,9 +43,6 @@ public: const char *GetRegisterName(unsigned reg); - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) override; - protected: struct RegInfo { uint32_t num_registers; @@ -68,12 +65,10 @@ protected: 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_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_S390X_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 4d5991f08f1d..ac271a90d6a1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_x86.cpp ----------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_x86.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -456,17 +456,6 @@ const char *RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) { 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(); - - 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) { @@ -509,20 +498,3 @@ bool RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t 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_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; - } - - 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 932f97bb567f..c4886ae618a2 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_x86_h_ -#define liblldb_RegisterContextPOSIX_x86_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_X86_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_X86_H #include "RegisterContext_x86.h" #include "RegisterInfoInterface.h" @@ -47,9 +47,6 @@ public: 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, @@ -160,8 +157,6 @@ protected: 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); @@ -173,4 +168,4 @@ protected: virtual bool WriteFPR() = 0; }; -#endif // liblldb_RegisterContextPOSIX_x86_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_X86_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index bcf60cc7a338..31e2944084ed 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextThreadMemory.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h index 09a679ab2c9f..40688a502a66 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_RegisterContextThreadMemory_h_ -#define lldb_RegisterContextThreadMemory_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTTHREADMEMORY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTTHREADMEMORY_H #include <vector> @@ -92,9 +92,11 @@ protected: uint32_t m_stop_id; private: - DISALLOW_COPY_AND_ASSIGN(RegisterContextThreadMemory); + RegisterContextThreadMemory(const RegisterContextThreadMemory &) = delete; + const RegisterContextThreadMemory & + operator=(const RegisterContextThreadMemory &) = delete; }; } // namespace lldb_private -#endif // lldb_RegisterContextThreadMemory_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTTHREADMEMORY_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp index 916d3233cde5..11556e802e33 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextWindows_i386.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextWindows_i386.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.h index 7779cc357526..6a5d3524300d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextWindows_i386_H_ -#define liblldb_RegisterContextWindows_i386_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTWINDOWS_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTWINDOWS_I386_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp index e90584de1a44..4ffc4d25781c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextWindows_x86_64.cpp -----------------------*- C++ -*-===// +//===-- RegisterContextWindows_x86_64.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h index 18198b5b25b3..c29acf284841 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextWindows_x86_64_H_ -#define liblldb_RegisterContextWindows_x86_64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTWINDOWS_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTWINDOWS_X86_64_H #include "RegisterInfoInterface.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h b/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h index 7780be51baad..15081f974c66 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContext_mips64_H_ -#define liblldb_RegisterContext_mips64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_MIPS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_MIPS_H #include <cstddef> #include <cstdint> @@ -371,4 +371,4 @@ struct UserArea { MSA_linux_mips msa; // MSA registers. }; -#endif // liblldb_RegisterContext_mips64_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_MIPS_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h index 1ffcbeb5ec48..7407e2f402e0 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContext_powerpc_H_ -#define liblldb_RegisterContext_powerpc_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_POWERPC_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_POWERPC_H // eh_frame and DWARF Register numbers (eRegisterKindEHFrame & // eRegisterKindDWARF) @@ -120,4 +120,4 @@ enum { dwarf_v31_powerpc, }; -#endif // liblldb_RegisterContext_powerpc_H_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_POWERPC_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h b/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h index 2cf39e9eb8e2..248b3bd0beac 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContext_s390x_h_ -#define liblldb_RegisterContext_s390x_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_S390X_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_S390X_H // SystemZ ehframe, dwarf regnums diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h index 2b79f778aa56..27a1bad4d53f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContext_x86_H_ -#define liblldb_RegisterContext_x86_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H #include <cstddef> #include <cstdint> diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoAndSetInterface.h b/lldb/source/Plugins/Process/Utility/RegisterInfoAndSetInterface.h new file mode 100644 index 000000000000..7e569dc9ba78 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoAndSetInterface.h @@ -0,0 +1,36 @@ +//===-- RegisterInfoAndSetInterface.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOANDSETINTERFACE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOANDSETINTERFACE_H + +#include "RegisterInfoInterface.h" + +#include "lldb/Utility/ArchSpec.h" +#include "lldb/lldb-private-types.h" +#include <vector> + +namespace lldb_private { + +class RegisterInfoAndSetInterface : public RegisterInfoInterface { +public: + RegisterInfoAndSetInterface(const lldb_private::ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} + + virtual size_t GetFPRSize() const = 0; + + virtual const lldb_private::RegisterSet * + GetRegisterSet(size_t reg_set) const = 0; + + virtual size_t GetRegisterSetCount() const = 0; + + virtual size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const = 0; +}; +} // namespace lldb_private + +#endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h index 4b58e749adce..88c2ae7c5010 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_RegisterInfoInterface_h -#define lldb_RegisterInfoInterface_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOINTERFACE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOINTERFACE_H #include "lldb/Utility/ArchSpec.h" #include "lldb/lldb-private-types.h" @@ -61,7 +61,6 @@ public: return nullptr; } -public: // FIXME make private. lldb_private::ArchSpec m_target_arch; }; diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp index d392d3be1c41..8fc4d5282b06 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterInfoPOSIX_arm.cpp ------------------------------*- C++ -*-===// +//===-- RegisterInfoPOSIX_arm.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h index 39c2047600aa..1cf896e3decf 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterInfoPOSIX_arm_h_ -#define liblldb_RegisterInfoPOSIX_arm_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM_H #include "RegisterInfoInterface.h" #include "lldb/Target/RegisterContext.h" @@ -58,4 +58,4 @@ private: uint32_t m_register_info_count; }; -#endif // liblldb_RegisterInfoPOSIX_arm_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM_H diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 8b367bdc6448..4537cee42ad9 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterInfoPOSIX_arm64.cpp ----------------------------*- C++ -*-===// +//===-- RegisterInfoPOSIX_arm64.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -65,6 +65,82 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { } } +// Number of register sets provided by this context. +enum { + k_num_gpr_registers = gpr_w28 - gpr_x0 + 1, + k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1, + k_num_register_sets = 2 +}; + +// ARM64 general purpose registers. +static const uint32_t g_gpr_regnums_arm64[] = { + 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, gpr_w0, gpr_w1, + gpr_w2, gpr_w3, gpr_w4, gpr_w5, + gpr_w6, gpr_w7, gpr_w8, gpr_w9, + gpr_w10, gpr_w11, gpr_w12, gpr_w13, + gpr_w14, gpr_w15, gpr_w16, gpr_w17, + gpr_w18, gpr_w19, gpr_w20, gpr_w21, + gpr_w22, gpr_w23, gpr_w24, gpr_w25, + gpr_w26, gpr_w27, gpr_w28, LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - + 1) == k_num_gpr_registers, + "g_gpr_regnums_arm64 has wrong number of register infos"); + +// ARM64 floating point registers. +static const uint32_t g_fpu_regnums_arm64[] = { + 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_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_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_fpsr, fpu_fpcr, LLDB_INVALID_REGNUM}; +static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - + 1) == k_num_fpr_registers, + "g_fpu_regnums_arm64 has wrong number of register infos"); +// clang-format on +// 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, + g_gpr_regnums_arm64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers, + g_fpu_regnums_arm64}}; + static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { @@ -80,19 +156,60 @@ GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( const lldb_private::ArchSpec &target_arch) - : lldb_private::RegisterInfoInterface(target_arch), + : lldb_private::RegisterInfoAndSetInterface(target_arch), m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) {} + m_register_info_count(GetRegisterInfoCount(target_arch)) { + + switch (target_arch.GetMachine()) { + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: + num_registers = k_num_gpr_registers + k_num_fpr_registers; + num_gpr_registers = k_num_gpr_registers; + num_fpr_registers = k_num_fpr_registers; + last_gpr = gpr_w28; + first_fpr = fpu_v0; + last_fpr = fpu_fpcr; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } +} + +uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { + return num_gpr_registers + num_fpr_registers; +} size_t RegisterInfoPOSIX_arm64::GetGPRSize() const { return sizeof(struct RegisterInfoPOSIX_arm64::GPR); } +size_t RegisterInfoPOSIX_arm64::GetFPRSize() const { + return sizeof(struct RegisterInfoPOSIX_arm64::FPU); +} + const lldb_private::RegisterInfo * RegisterInfoPOSIX_arm64::GetRegisterInfo() const { return m_register_info_p; } -uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { - return m_register_info_count; +size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const { + return k_num_register_sets; +} + +size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex( + uint32_t reg_index) const { + if (reg_index <= last_gpr) + return GPRegSet; + else if (reg_index <= last_fpr) + return FPRegSet; + return LLDB_INVALID_REGNUM; +} + +const lldb_private::RegisterSet * +RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const { + if (set_index < k_num_register_sets) + return &g_reg_sets_arm64[set_index]; + + return nullptr; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h index ace179a81814..2da6a531a6b6 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -6,15 +6,18 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_arm64_H_ -#define liblldb_RegisterContextLinux_arm64_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM64_H -#include "RegisterInfoInterface.h" +#include "RegisterInfoAndSetInterface.h" #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" -class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoInterface { +class RegisterInfoPOSIX_arm64 + : public lldb_private::RegisterInfoAndSetInterface { public: + enum { GPRegSet = 0, FPRegSet }; + // based on RegisterContextDarwin_arm64.h struct GPR { uint64_t x[29]; // x0-x28 @@ -57,11 +60,28 @@ public: size_t GetGPRSize() const override; + size_t GetFPRSize() const override; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; uint32_t GetRegisterCount() const override; + const lldb_private::RegisterSet * + GetRegisterSet(size_t reg_set) const override; + + size_t GetRegisterSetCount() const override; + + size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override; + private: + 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; + const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; }; diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp index 35051a3ce095..3461d38a3901 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -1,4 +1,4 @@ -//===-- RegisterInfoPOSIX_ppc64le.cpp --------------------------*- C++ -*-===// +//===-- RegisterInfoPOSIX_ppc64le.cpp -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h index c4d4d3b546e2..98549ac0dda4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextLinux_ppc64le_H_ -#define liblldb_RegisterContextLinux_ppc64le_H_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_PPC64LE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_PPC64LE_H #include "RegisterInfoInterface.h" #include "lldb/Target/RegisterContext.h" diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 68c12aa6e529..4aee55e7afba 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -456,37 +456,26 @@ static uint32_t g_d29_invalidates[] = {fpu_v29, fpu_s29, LLDB_INVALID_REGNUM}; static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM}; static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; -// Generates register kinds array for 64-bit general purpose registers -#define GPR64_KIND(reg, generic_kind) \ +// Generates register kinds array with DWARF, EH frame and generic kind +#define MISC_KIND(reg, type, generic_kind) \ { \ arm64_ehframe::reg, arm64_dwarf::reg, generic_kind, LLDB_INVALID_REGNUM, \ - gpr_##reg \ + type##_##reg \ } -// Generates register kinds array for registers with lldb kind -#define MISC_KIND(lldb_kind) \ +// Generates register kinds array for registers with only lldb kind +#define LLDB_KIND(lldb_kind) \ { \ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ LLDB_INVALID_REGNUM, lldb_kind \ } // Generates register kinds array for vector registers -#define VREG_KIND(reg) \ - { \ - LLDB_INVALID_REGNUM, arm64_dwarf::reg, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, fpu_##reg \ - } - -// Generates register kinds array for cpsr -#define CPSR_KIND(lldb_kind) \ - { \ - arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, \ - LLDB_INVALID_REGNUM, lldb_kind \ - } - -#define MISC_GPR_KIND(lldb_kind) CPSR_KIND(lldb_kind) -#define MISC_FPU_KIND(lldb_kind) MISC_KIND(lldb_kind) -#define MISC_EXC_KIND(lldb_kind) MISC_KIND(lldb_kind) +#define GPR64_KIND(reg, generic_kind) MISC_KIND(reg, gpr, generic_kind) +#define VREG_KIND(reg) MISC_KIND(reg, fpu, LLDB_INVALID_REGNUM) +#define MISC_GPR_KIND(lldb_kind) MISC_KIND(cpsr, gpr, LLDB_REGNUM_GENERIC_FLAGS) +#define MISC_FPU_KIND(lldb_kind) LLDB_KIND(lldb_kind) +#define MISC_EXC_KIND(lldb_kind) LLDB_KIND(lldb_kind) // Defines a 64-bit general purpose register #define DEFINE_GPR64(reg, generic_kind) \ @@ -509,7 +498,7 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; { \ #wreg, nullptr, 4, \ GPR_OFFSET(gpr_##xreg) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, \ - lldb::eEncodingUint, lldb::eFormatHex, MISC_KIND(gpr_##wreg), \ + lldb::eEncodingUint, lldb::eFormatHex, LLDB_KIND(gpr_##wreg), \ g_contained_##xreg, g_##wreg##_invalidates, nullptr, 0 \ } @@ -521,11 +510,11 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; 0 \ } -// Defines S and D pseudo registers mapping over correspondig vector register +// Defines S and D pseudo registers mapping over corresponding vector register #define DEFINE_FPU_PSEUDO(reg, size, offset, vreg) \ { \ #reg, nullptr, size, FPU_OFFSET(fpu_##vreg - fpu_v0) + offset, \ - lldb::eEncodingIEEE754, lldb::eFormatFloat, MISC_KIND(fpu_##reg), \ + lldb::eEncodingIEEE754, lldb::eFormatFloat, LLDB_KIND(fpu_##reg), \ g_contained_##vreg, g_##reg##_invalidates, nullptr, 0 \ } diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h index 72ff904520ad..343579cd2657 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -145,7 +145,7 @@ DR_OFFSET(i), eEncodingUint, eFormatHex, \ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM }, \ + lldb_##reg##i##_i386 }, \ nullptr, nullptr, nullptr, 0 \ } diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index 6d03bd534f37..2d8e8ef21612 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -1,4 +1,4 @@ -//===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===// +//===-- StopInfoMachException.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -8,6 +8,7 @@ #include "StopInfoMachException.h" +#include "lldb/lldb-forward.h" #if defined(__APPLE__) // Needed for the EXC_RESOURCE interpretation macros @@ -289,10 +290,48 @@ const char *StopInfoMachException::GetDescription() { if (m_exc_data_count > 0) strm.PutChar(')'); - m_description = strm.GetString(); + m_description = std::string(strm.GetString()); return m_description.c_str(); } +static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, + uint32_t exc_data_count, + uint64_t exc_sub_code, + uint64_t exc_sub_sub_code) { + // Try hardware watchpoint. + if (target) { + // The exc_sub_code indicates the data break address. + lldb::WatchpointSP 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()); + } + } + + // Try hardware breakpoint. + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + // The exc_sub_code indicates the data break address. + lldb::BreakpointSiteSP bp_sp = + process_sp->GetBreakpointSiteList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (bp_sp && bp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired breakpoint + // in the exception data. Set the hardware index if that's the case. + if (exc_data_count >= 3) + bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithBreakpointSiteID(thread, + bp_sp->GetID()); + } + } + + return nullptr; +} + 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, @@ -350,22 +389,10 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( 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()); - } + if (StopInfoSP stop_info = + GetStopInfoForHardwareBP(thread, target, exc_data_count, + exc_sub_code, exc_sub_sub_code)) + return stop_info; } } else if (exc_code == 2 || // EXC_I386_BPT exc_code == 3) // EXC_I386_BPTFLT diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h index 74c05812ab00..d9c1886d7096 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StopInfoMachException_h_ -#define liblldb_StopInfoMachException_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_STOPINFOMACHEXCEPTION_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_STOPINFOMACHEXCEPTION_H #include <string> @@ -48,4 +48,4 @@ protected: } // namespace lldb_private -#endif // liblldb_StopInfoMachException_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_STOPINFOMACHEXCEPTION_H diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 80b04bb14f77..7469e7633e71 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -1,5 +1,4 @@ -//===-- ThreadMemory.cpp ----------------------------------------------*- C++ -//-*-===// +//===-- ThreadMemory.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -30,7 +29,8 @@ ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, llvm::StringRef name, llvm::StringRef queue, lldb::addr_t register_data_addr) : Thread(process, tid), m_backing_thread_sp(), m_thread_info_valobj_sp(), - m_name(name), m_queue(queue), m_register_data_addr(register_data_addr) {} + m_name(std::string(name)), m_queue(std::string(queue)), + m_register_data_addr(register_data_addr) {} ThreadMemory::~ThreadMemory() { DestroyThread(); } @@ -54,20 +54,14 @@ RegisterContextSP ThreadMemory::GetRegisterContext() { 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 != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); - } - return reg_ctx_sp; + if (concrete_frame_idx == 0) + return GetRegisterContext(); + return GetUnwinder().CreateRegisterContextForFrame(frame); } bool ThreadMemory::CalculateStopInfo() { diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index 85bc1451e4a0..d124f5780ea9 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ThreadMemory_h_ -#define liblldb_ThreadMemory_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H #include <string> @@ -100,7 +100,8 @@ protected: lldb::addr_t m_register_data_addr; private: - DISALLOW_COPY_AND_ASSIGN(ThreadMemory); + ThreadMemory(const ThreadMemory &) = delete; + const ThreadMemory &operator=(const ThreadMemory &) = delete; }; -#endif // liblldb_ThreadMemory_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp deleted file mode 100644 index 74fc90e88547..000000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ /dev/null @@ -1,519 +0,0 @@ -//===-- UnwindLLDB.cpp -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#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/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/Log.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)); - } - } -} - -uint32_t UnwindLLDB::DoGetFrameCount() { - if (!m_unwind_complete) { -//#define DEBUG_FRAME_SPEED 1 -#if DEBUG_FRAME_SPEED -#define FRAME_COUNT 10000 - using namespace std::chrono; - auto time_value = steady_clock::now(); -#endif - if (!AddFirstFrame()) - return 0; - - ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; - - while (AddOneMoreFrame(abi)) { -#if DEBUG_FRAME_SPEED - if ((m_frames.size() % FRAME_COUNT) == 0) { - const auto now = steady_clock::now(); - const auto delta_t = now - time_value; - printf("%u frames in %.9f ms (%g frames/sec)\n", FRAME_COUNT, - duration<double, std::milli>(delta_t).count(), - (float)FRAME_COUNT / duration<double>(delta_t).count()); - time_value = now; - } -#endif - } - } - 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() : nullptr; - - // 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() == nullptr) - goto unwind_done; - - if (!reg_ctx_sp->IsValid()) - goto unwind_done; - - if (!reg_ctx_sp->GetCFA(first_cursor_sp->cfa)) - goto unwind_done; - - if (!reg_ctx_sp->ReadPC(first_cursor_sp->start_pc)) - 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); - - // 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) { - LLDB_LOGF(log, "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)); - - uint64_t max_stack_depth = m_thread.GetMaxBacktraceDepth(); - - // 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 >= max_stack_depth) { - LLDB_LOGF(log, - "%*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() == nullptr) { - // 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); - } - - LLDB_LOGF(log, "%*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); - } - - LLDB_LOGF(log, - "%*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); - } - - LLDB_LOGF(log, - "%*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()) { - // 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() || - !reg_ctx_sp->GetCFA(cursor_sp->cfa) || - !abi->CallFrameAddressIsValid(cursor_sp->cfa)) { - 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); - } - - LLDB_LOGF(log, - "%*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 { - LLDB_LOGF(log, - "%*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); - } - - LLDB_LOGF(log, - "%*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); - } - - LLDB_LOGF(log, "%*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) { - LLDB_LOGF(log, - "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; -} - -bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); - - // Frame zero is a little different - if (m_frames.empty()) - return false; - - // If we've already gotten to the end of the stack, don't bother to try - // again... - if (m_unwind_complete) - return false; - - CursorSP new_frame = m_candidate_frame; - if (new_frame == nullptr) - new_frame = GetOneMoreFrame(abi); - - if (new_frame == nullptr) { - LLDB_LOGF(log, "th%d Unwind of this thread is complete.", - m_thread.GetIndexID()); - m_unwind_complete = true; - return false; - } - - m_frames.push_back(new_frame); - - // 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. - return m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA( - m_frames[m_frames.size() - 2]->cfa); - } - - // 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, - bool &behaves_like_zeroth_frame) { - if (m_frames.size() == 0) { - if (!AddFirstFrame()) - return false; - } - - ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; - - while (idx >= m_frames.size() && AddOneMoreFrame(abi)) - ; - - if (idx < m_frames.size()) { - cfa = m_frames[idx]->cfa; - pc = m_frames[idx]->start_pc; - if (idx == 0) { - // Frame zero always behaves like it. - behaves_like_zeroth_frame = true; - } else if (m_frames[idx - 1]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { - // This could be an asynchronous signal, thus the - // pc might point to the interrupted instruction rather - // than a post-call instruction - behaves_like_zeroth_frame = true; - } else if (m_frames[idx]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { - // This frame may result from signal processing installing - // a pointer to the first byte of a signal-return trampoline - // in the return address slot of the frame below, so this - // too behaves like the zeroth frame (i.e. the pc might not - // be pointing just past a call in it) - behaves_like_zeroth_frame = true; - } else { - behaves_like_zeroth_frame = false; - } - 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() : nullptr; - - 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; -} - -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); - return result == UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - 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 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; - } - - 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 deleted file mode 100644 index ff5db39730b5..000000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h +++ /dev/null @@ -1,158 +0,0 @@ -//===-- UnwindLLDB.h --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_UnwindLLDB_h_ -#define lldb_UnwindLLDB_h_ - -#include <vector> - -#include "lldb/Symbol/FuncUnwinders.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/UnwindPlan.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Unwind.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/lldb-public.h" - -namespace lldb_private { - -class RegisterContextLLDB; - -class UnwindLLDB : public lldb_private::Unwind { -public: - UnwindLLDB(lldb_private::Thread &thread); - - ~UnwindLLDB() override = default; - - 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; - }; - - 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, - bool &behaves_like_zeroth_frame) 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; - } - -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); - }; - - 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); -}; - -} // namespace lldb_private - -#endif // lldb_UnwindLLDB_h_ diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp deleted file mode 100644 index 558edeec1a37..000000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ /dev/null @@ -1,247 +0,0 @@ -//===-- UnwindMacOSXFrameBackchain.cpp --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Symbol/Function.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" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ArchSpec.h" - -#include "RegisterContextMacOSXFrameBackchain.h" - -#include <memory> - -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); - } - } - return m_cursors.size(); -} - -bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex( - uint32_t idx, addr_t &cfa, addr_t &pc, bool &behaves_like_zeroth_frame) { - 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; - behaves_like_zeroth_frame = (idx == 0); - - 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 = std::make_shared<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 == nullptr) - return 0; - - 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); - Status 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 SymbolContextItem resolve_scope = - eSymbolContextModule | eSymbolContextCompUnit | - eSymbolContextFunction | eSymbolContextSymbol; - - SymbolContext first_frame_sc( - first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = nullptr; - 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(); -} - -size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( - const ExecutionContext &exe_ctx) { - m_cursors.clear(); - - Process *process = exe_ctx.GetProcessPtr(); - if (process == nullptr) - return 0; - - StackFrame *first_frame = exe_ctx.GetFramePtr(); - - 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); - Status 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 SymbolContextItem resolve_scope = - eSymbolContextModule | eSymbolContextCompUnit | - eSymbolContextFunction | eSymbolContextSymbol; - - SymbolContext first_frame_sc( - first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = nullptr; - 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(); -} diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h deleted file mode 100644 index f0bde90a53be..000000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- UnwindMacOSXFrameBackchain.h ----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_UnwindMacOSXFrameBackchain_h_ -#define lldb_UnwindMacOSXFrameBackchain_h_ - -#include <vector> - -#include "lldb/Target/Unwind.h" -#include "lldb/lldb-private.h" - -class UnwindMacOSXFrameBackchain : public lldb_private::Unwind { -public: - UnwindMacOSXFrameBackchain(lldb_private::Thread &thread); - - ~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, - bool &behaves_like_zeroth_frame) 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; - - size_t GetStackFrameData_i386(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); -}; - -#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 39cbf01ea9d2..8f0eed4f02c9 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_arm_register_enums_h -#define lldb_arm_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_ARM_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_ARM_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -196,4 +196,4 @@ enum { }; } -#endif // #ifndef lldb_arm64_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_ARM_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 cc414dcde3cf..39d47b8801cc 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_arm64_register_enums_h -#define lldb_arm64_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_ARM64_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_ARM64_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -261,4 +261,4 @@ enum { }; } -#endif // #ifndef lldb_arm64_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_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 d97f77122426..e6a7efd00f67 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 @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_mips_freebsd_register_enums_h -#define lldb_mips_freebsd_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_FREEBSD_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_FREEBSD_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -62,4 +62,4 @@ enum { k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1 }; } -#endif // #ifndef lldb_mips_freebsd_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_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 2f68b8022c9a..348af27d2809 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 @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_mips_linux_register_enums_h -#define lldb_mips_linux_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -357,4 +357,4 @@ enum { }; } -#endif // #ifndef lldb_mips_linux_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H diff --git a/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h index 6edf7ee3864d..40a75c006d84 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_ppc64_register_enums_h -#define lldb_ppc64_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64_REGISTER_ENUMS_H // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -133,4 +133,4 @@ enum { k_num_vmx_registers_ppc64 = k_last_vmx_ppc64 - k_first_vmx_ppc64 + 1, }; -#endif // #ifndef lldb_ppc64_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64_REGISTER_ENUMS_H diff --git a/lldb/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h index 0c381a5f3918..a7b5bc5ad9e3 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_ppc64le_register_enums_h -#define lldb_ppc64le_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64LE_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64LE_REGISTER_ENUMS_H // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -204,4 +204,4 @@ enum { k_num_vsx_registers_ppc64le = k_last_vsx_ppc64le - k_first_vsx_ppc64le + 1, }; -#endif // #ifndef lldb_ppc64le_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_PPC64LE_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 bd6626108290..23c441e1c803 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_s390x_register_enums_h -#define lldb_s390x_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_S390X_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_S390X_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -87,4 +87,4 @@ enum { }; } -#endif // #ifndef lldb_s390x_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_S390X_REGISTER_ENUMS_H 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 bfdd586d9ded..35f1a4075d09 100644 --- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_x86_register_enums_h -#define lldb_x86_register_enums_h +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_X86_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_X86_REGISTER_ENUMS_H namespace lldb_private { // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) @@ -113,7 +113,8 @@ enum { lldb_bndstatus_i386, k_last_mpxc_i386 = lldb_bndstatus_i386, - lldb_dr0_i386, + k_first_dbr_i386, + lldb_dr0_i386 = k_first_dbr_i386, lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386, @@ -121,6 +122,7 @@ enum { lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386, + k_last_dbr_i386 = lldb_dr7_i386, k_num_registers_i386, k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, @@ -131,6 +133,7 @@ enum { k_num_fpr_registers_i386 + k_num_avx_registers_i386 + k_num_mpx_registers_i386, + k_num_dbr_registers_i386 = k_last_dbr_i386 - k_first_dbr_i386 + 1, }; // Internal codes for all x86_64 registers. @@ -318,4 +321,4 @@ enum { }; } -#endif // #ifndef lldb_x86_register_enums_h +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_X86_REGISTER_ENUMS_H diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index ab23589ae9a9..aa95e92607ad 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -1,4 +1,4 @@ -//===-- ProcessElfCore.cpp --------------------------------------*- C++ -*-===// +//===-- ProcessElfCore.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -35,6 +35,8 @@ using namespace lldb_private; namespace ELF = llvm::ELF; +LLDB_PLUGIN_DEFINE(ProcessElfCore) + ConstString ProcessElfCore::GetPluginNameStatic() { static ConstString g_name("elf-core"); return g_name; diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index 829fe9ac7199..6f6309799f43 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -13,8 +13,8 @@ // space. //===----------------------------------------------------------------------===// -#ifndef liblldb_ProcessElfCore_h_ -#define liblldb_ProcessElfCore_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H #include <list> #include <vector> @@ -125,7 +125,8 @@ private: lldb::ModuleSP m_core_module_sp; lldb_private::FileSpec m_core_file; std::string m_dyld_plugin_name; - DISALLOW_COPY_AND_ASSIGN(ProcessElfCore); + ProcessElfCore(const ProcessElfCore &) = delete; + const ProcessElfCore &operator=(const ProcessElfCore &) = delete; // True if m_thread_contexts contains valid entries bool m_thread_data_valid = false; @@ -165,4 +166,4 @@ private: llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); }; -#endif // liblldb_ProcessElfCore_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_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 fa05c457fc61..b76f26a584c0 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_arm.cpp ------------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_arm.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -44,10 +44,12 @@ bool RegisterContextCorePOSIX_arm::WriteFPR() { 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; + if (offset + reg_info->byte_size <= GetGPRSize()) { + 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; } diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index adda43ebccbc..f9ec08ed35fc 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_arm_h_ -#define liblldb_RegisterContextCorePOSIX_arm_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_ARM_H #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -50,4 +50,4 @@ private: lldb_private::DataExtractor m_gpr; }; -#endif // liblldb_RegisterContextCorePOSIX_arm_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_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 e477c438ba12..685567416983 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_arm64.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_arm64.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,13 +17,16 @@ using namespace lldb_private; RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( - Thread &thread, RegisterInfoInterface *register_info, + Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) - : RegisterContextPOSIX_arm64(thread, 0, register_info) { + : RegisterContextPOSIX_arm64(thread, std::move(register_info)) { m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(), gpregset.GetByteSize()); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + m_fpregset = getRegset( + notes, m_register_info_up->GetTargetArchitecture().GetTriple(), FPR_Desc); } RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {} @@ -45,11 +48,26 @@ bool RegisterContextCorePOSIX_arm64::WriteFPR() { 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; + if (offset + reg_info->byte_size <= GetGPRSize()) { + 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; + } } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return false; + + offset -= GetGPRSize(); + if (IsFPR(reg) && offset + reg_info->byte_size <= GetFPUSize()) { + Status error; + value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, error); + return error.Success(); + } + 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 de6d819c29ce..830e0ff91e4c 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_arm64_h_ -#define liblldb_RegisterContextCorePOSIX_arm64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_ARM64_H #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -18,7 +18,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { public: RegisterContextCorePOSIX_arm64( lldb_private::Thread &thread, - lldb_private::RegisterInfoInterface *register_info, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef<lldb_private::CoreNote> notes); @@ -48,6 +48,7 @@ protected: private: lldb::DataBufferSP m_gpr_buffer; lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpregset; }; -#endif // liblldb_RegisterContextCorePOSIX_arm64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_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 3601f3b3b216..b5b83d899a44 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_mips64.cpp ---------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_mips64.cpp -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index 999c9451573b..b42a76c082f0 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_mips64_h_ -#define liblldb_RegisterContextCorePOSIX_mips64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_MIPS64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_MIPS64_H #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -52,4 +52,4 @@ private: lldb_private::DataExtractor m_fpr; }; -#endif // liblldb_RegisterContextCorePOSIX_mips64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_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 6984bf4ee9b8..e15cd47cd7da 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_powerpc.cpp --------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_powerpc.cpp ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index 7684c0b31837..cf50b6e0bf70 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_ -#define liblldb_RegisterContextCorePOSIX_powerpc_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_POWERPC_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_POWERPC_H #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -57,4 +57,4 @@ private: lldb_private::DataExtractor m_vec; }; -#endif // liblldb_RegisterContextCorePOSIX_powerpc_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_POWERPC_H diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp index 0eebf474f60e..d44fb399e18a 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_ppc64le.cpp --------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_ppc64le.cpp ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h index 6e01d23dd656..8de77a7e25bf 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_ppc64le_h_ -#define liblldb_RegisterContextCorePOSIX_ppc64le_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_PPC64LE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_PPC64LE_H #include "Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -45,4 +45,4 @@ private: lldb_private::DataExtractor m_vsx; }; -#endif // liblldb_RegisterContextCorePOSIX_ppc64le_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_PPC64LE_H diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index d84fc3e74395..c3aa92c9f86c 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_s390x.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_s390x.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h index 729617649c4f..4560f062e06f 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_s390x_h_ -#define liblldb_RegisterContextCorePOSIX_s390x_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_S390X_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_S390X_H #include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -52,4 +52,4 @@ private: lldb_private::DataExtractor m_fpr; }; -#endif // liblldb_RegisterContextCorePOSIX_s390x_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_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 4454857e1799..6eaad9f381d6 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIXCore_x86_64.cpp ---------------------*- C++ -*-===// +//===-- RegisterContextPOSIXCore_x86_64.cpp -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. 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 f41991c240d2..9adfbf7e6852 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_ -#define liblldb_RegisterContextCorePOSIX_x86_64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_X86_64_H #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -46,4 +46,4 @@ private: std::unique_ptr<uint8_t[]> m_fpregset; }; -#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_X86_64_H diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp index c8829d612b31..0c21c0f50abb 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp @@ -1,4 +1,4 @@ -//===-- RegisterUtilities.cpp -----------------------------------*- C++ -*-===// +//===-- RegisterUtilities.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h index 49ad425db445..4e08aa280817 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_REGISTERUTILITIES_H -#define LLDB_REGISTERUTILITIES_H +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERUTILITIES_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERUTILITIES_H #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Utility/DataExtractor.h" @@ -118,4 +118,4 @@ constexpr RegsetDesc PPC_VSX_Desc[] = { } // namespace lldb_private -#endif // #ifndef LLDB_REGISTERUTILITIES_H +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERUTILITIES_H diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 508c8a3108a6..6b5acfa4bc1b 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -1,4 +1,4 @@ -//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===// +//===-- ThreadElfCore.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -82,7 +82,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { case llvm::Triple::FreeBSD: { switch (arch.GetMachine()) { case llvm::Triple::aarch64: - reg_interface = new RegisterInfoPOSIX_arm64(arch); break; case llvm::Triple::arm: reg_interface = new RegisterInfoPOSIX_arm(arch); @@ -111,7 +110,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { case llvm::Triple::NetBSD: { switch (arch.GetMachine()) { case llvm::Triple::aarch64: - reg_interface = new RegisterInfoPOSIX_arm64(arch); break; case llvm::Triple::x86_64: reg_interface = new RegisterContextNetBSD_x86_64(arch); @@ -128,7 +126,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { reg_interface = new RegisterInfoPOSIX_arm(arch); break; case llvm::Triple::aarch64: - reg_interface = new RegisterInfoPOSIX_arm64(arch); break; case llvm::Triple::mipsel: case llvm::Triple::mips: @@ -159,7 +156,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { case llvm::Triple::OpenBSD: { switch (arch.GetMachine()) { case llvm::Triple::aarch64: - reg_interface = new RegisterInfoPOSIX_arm64(arch); break; case llvm::Triple::arm: reg_interface = new RegisterInfoPOSIX_arm(arch); @@ -180,7 +176,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { break; } - if (!reg_interface) { + if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64) { LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported", __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); assert(false && "Architecture or OS not supported"); @@ -189,7 +185,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>( - *this, reg_interface, m_gpregset_data, m_notes); + *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch), + m_gpregset_data, m_notes); break; case llvm::Triple::arm: m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>( @@ -229,9 +226,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { reg_ctx_sp = m_thread_reg_ctx_sp; } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); } return reg_ctx_sp; } @@ -296,25 +291,25 @@ Status ELFLinuxPrStatus::Parse(const DataExtractor &data, pr_cursig = data.GetU16(&offset); offset += 2; // pad - pr_sigpend = data.GetPointer(&offset); - pr_sighold = data.GetPointer(&offset); + pr_sigpend = data.GetAddress(&offset); + pr_sighold = data.GetAddress(&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.GetPointer(&offset); - pr_utime.tv_usec = data.GetPointer(&offset); + pr_utime.tv_sec = data.GetAddress(&offset); + pr_utime.tv_usec = data.GetAddress(&offset); - pr_stime.tv_sec = data.GetPointer(&offset); - pr_stime.tv_usec = data.GetPointer(&offset); + pr_stime.tv_sec = data.GetAddress(&offset); + pr_stime.tv_usec = data.GetAddress(&offset); - pr_cutime.tv_sec = data.GetPointer(&offset); - pr_cutime.tv_usec = data.GetPointer(&offset); + pr_cutime.tv_sec = data.GetAddress(&offset); + pr_cutime.tv_usec = data.GetAddress(&offset); - pr_cstime.tv_sec = data.GetPointer(&offset); - pr_cstime.tv_usec = data.GetPointer(&offset); + pr_cstime.tv_sec = data.GetAddress(&offset); + pr_cstime.tv_usec = data.GetAddress(&offset); return error; } @@ -367,7 +362,7 @@ Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data, offset += 4; } - pr_flag = data.GetPointer(&offset); + pr_flag = data.GetAddress(&offset); if (arch.IsMIPS()) { // The pr_uid and pr_gid is always 32 bit irrespective of platforms diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index ddcf35013b34..8d973bb840d2 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ThreadElfCore_h_ -#define liblldb_ThreadElfCore_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H #include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Target/Thread.h" @@ -173,4 +173,4 @@ protected: bool CalculateStopInfo() override; }; -#endif // liblldb_ThreadElfCore_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index 064bbde8442e..fdaa60e2df41 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteClientBase.cpp ---------------------------------*- C++ -*-===// +//===-- GDBRemoteClientBase.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -41,7 +41,7 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( { std::lock_guard<std::mutex> lock(m_mutex); - m_continue_packet = payload; + m_continue_packet = std::string(payload); m_should_stop = false; } ContinueLock cont_lock(*this); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index ea294ffcef26..cd9f6ebd7642 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteClientBase_h_ -#define liblldb_GDBRemoteClientBase_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H #include "GDBRemoteCommunication.h" @@ -149,4 +149,4 @@ private: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationClient_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 7cea013eea7f..bfacd41dc1a3 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===// +//===-- GDBRemoteCommunication.cpp ----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -50,7 +50,7 @@ #include <compression.h> #endif -#if LLVM_ENABLE_ZLIB +#if defined(HAVE_LIBZ) #include <zlib.h> #endif @@ -125,7 +125,7 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) { packet.Write(payload.data(), payload.size()); packet.PutChar('#'); packet.PutHex8(CalculcateChecksum(payload)); - std::string packet_str = packet.GetString(); + std::string packet_str = std::string(packet.GetString()); return SendRawPacketNoLock(packet_str); } @@ -582,7 +582,7 @@ bool GDBRemoteCommunication::DecompressPacket() { } #endif -#if LLVM_ENABLE_ZLIB +#if defined(HAVE_LIBZ) if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr && m_compression_type == CompressionType::ZlibDeflate) { @@ -763,7 +763,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, if (m_bytes[0] == '$' && total_length > 4) { for (size_t i = 0; !binary && i < total_length; ++i) { unsigned char c = m_bytes[i]; - if (isprint(c) == 0 && isspace(c) == 0) { + if (!llvm::isPrint(c) && !llvm::isSpace(c)) { binary = true; } } @@ -810,31 +810,9 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, GDBRemotePacket::ePacketTypeRecv, total_length); // 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) - std ::string packet_str; - 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); - } - } + // encoding in the process. + std ::string packet_str = + ExpandRLE(m_bytes.substr(content_start, content_end - content_start)); packet = StringExtractorGDBRemote(packet_str); if (m_bytes[0] == '$' || m_bytes[0] == '%') { @@ -891,7 +869,7 @@ Status GDBRemoteCommunication::StartListenThread(const char *hostname, else snprintf(listen_url, sizeof(listen_url), "listen://%i", port); m_listen_url = listen_url; - SetConnection(new ConnectionFileDescriptor()); + SetConnection(std::make_unique<ConnectionFileDescriptor>()); llvm::Expected<HostThread> listen_thread = ThreadLauncher::LaunchThread( listen_url, GDBRemoteCommunication::ListenThread, this); if (!listen_thread) @@ -1274,11 +1252,12 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client, return llvm::createStringError(llvm::inconvertibleErrorCode(), "Unable to connect: %s", status.AsCString()); - client.SetConnection(conn_up.release()); + client.SetConnection(std::move(conn_up)); if (llvm::Error error = accept_status.get().ToError()) return error; - server.SetConnection(new ConnectionFileDescriptor(accept_socket)); + server.SetConnection( + std::make_unique<ConnectionFileDescriptor>(accept_socket)); return llvm::Error::success(); } @@ -1382,3 +1361,30 @@ void llvm::format_provider<GDBRemoteCommunication::PacketResult>::format( break; } } + +std::string GDBRemoteCommunication::ExpandRLE(std::string packet) { + // Reserve enough byte for the most common case (no RLE used). + std::string decoded; + decoded.reserve(packet.size()); + for (std::string::const_iterator c = packet.begin(); c != packet.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 = decoded.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) + decoded.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; + decoded.push_back(escapee); + } else { + decoded.push_back(*c); + } + } + return decoded; +} diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 0b670018bd69..b1e2075a64fe 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunication_h_ -#define liblldb_GDBRemoteCommunication_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H #include "GDBRemoteCommunicationHistory.h" @@ -142,6 +142,9 @@ public: static llvm::Error ConnectLocally(GDBRemoteCommunication &client, GDBRemoteCommunication &server); + /// Expand GDB run-length encoding. + static std::string ExpandRLE(std::string); + protected: std::chrono::seconds m_packet_timeout; uint32_t m_echo_number; @@ -223,7 +226,9 @@ private: void *m_decompression_scratch = nullptr; #endif - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication); + GDBRemoteCommunication(const GDBRemoteCommunication &) = delete; + const GDBRemoteCommunication & + operator=(const GDBRemoteCommunication &) = delete; }; } // namespace process_gdb_remote @@ -239,4 +244,4 @@ struct format_provider< }; } // namespace llvm -#endif // liblldb_GDBRemoteCommunication_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b2f1ee527e8b..c75d5e106cd0 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationClient.cpp ------------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationClient.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -45,6 +45,13 @@ using namespace lldb_private::process_gdb_remote; using namespace lldb_private; using namespace std::chrono; +llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os, + const QOffsets &offsets) { + return os << llvm::formatv( + "QOffsets({0}, [{1:@[x]}])", offsets.segments, + llvm::make_range(offsets.offsets.begin(), offsets.offsets.end())); +} + // GDBRemoteCommunicationClient constructor GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"), @@ -573,7 +580,8 @@ StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { if (response.IsUnsupportedResponse()) { m_supports_jThreadsInfo = false; } else if (!response.Empty()) { - object_sp = StructuredData::ParseJSON(response.GetStringRef()); + object_sp = + StructuredData::ParseJSON(std::string(response.GetStringRef())); } } } @@ -685,7 +693,7 @@ GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( if (result != PacketResult::Success) return result; - const std::string &this_string = this_response.GetStringRef(); + const std::string &this_string = std::string(this_response.GetStringRef()); // Check for m or l as first character; l seems to mean this is the last // chunk @@ -757,7 +765,7 @@ bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { return true; if (response.GetChar() == 'E') { // A string the describes what failed when launching... - error_str = response.GetStringRef().substr(1); + error_str = std::string(response.GetStringRef().substr(1)); } else { error_str.assign("unknown error occurred launching process"); } @@ -833,7 +841,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket( bool send_hex_encoding = false; for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding; ++p) { - if (isprint(*p)) { + if (llvm::isPrint(*p)) { switch (*p) { case '$': case '#': @@ -1000,7 +1008,7 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() { while (response.GetNameColonValue(name, value)) { if (name.equals("name")) { success = true; - m_gdb_server_name = value; + m_gdb_server_name = std::string(value); } else if (name.equals("version")) { llvm::StringRef major, minor; std::tie(major, minor) = value.split('.'); @@ -1045,7 +1053,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( } #endif -#if LLVM_ENABLE_ZLIB +#if defined(HAVE_LIBZ) if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { @@ -1123,6 +1131,20 @@ bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) { return true; } +static void ParseOSType(llvm::StringRef value, std::string &os_name, + std::string &environment) { + if (value.equals("iossimulator") || value.equals("tvossimulator") || + value.equals("watchossimulator")) { + environment = "simulator"; + os_name = value.drop_back(environment.size()).str(); + } else if (value.equals("maccatalyst")) { + os_name = "ios"; + environment = "macabi"; + } else { + os_name = value.str(); + } +} + bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS)); @@ -1158,7 +1180,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { if (!value.getAsInteger(0, sub)) ++num_keys_decoded; } else if (name.equals("arch")) { - arch_name = value; + arch_name = std::string(value); ++num_keys_decoded; } else if (name.equals("triple")) { StringExtractor extractor(value); @@ -1181,14 +1203,10 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { extractor.GetHexByteString(m_os_kernel); ++num_keys_decoded; } else if (name.equals("ostype")) { - if (value.equals("maccatalyst")) { - os_name = "ios"; - environment = "macabi"; - } else - os_name = value; + ParseOSType(value, os_name, environment); ++num_keys_decoded; } else if (name.equals("vendor")) { - vendor_name = value; + vendor_name = std::string(value); ++num_keys_decoded; } else if (name.equals("endian")) { byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) @@ -1956,9 +1974,9 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( } else if (name.equals("cpusubtype")) { value.getAsInteger(0, sub); } else if (name.equals("vendor")) { - vendor = value; + vendor = std::string(value); } else if (name.equals("ostype")) { - os_type = value; + os_type = std::string(value); } } @@ -2045,14 +2063,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { extractor.GetHexByteString(triple); ++num_keys_decoded; } else if (name.equals("ostype")) { - if (value.equals("maccatalyst")) { - os_name = "ios"; - environment = "macabi"; - } else - os_name = value; + ParseOSType(value, os_name, environment); ++num_keys_decoded; } else if (name.equals("vendor")) { - vendor_name = value; + vendor_name = std::string(value); ++num_keys_decoded; } else if (name.equals("endian")) { byte_order = llvm::StringSwitch<lldb::ByteOrder>(value) @@ -2069,7 +2083,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { if (!value.getAsInteger(16, pid)) ++num_keys_decoded; } else if (name.equals("elf_abi")) { - elf_abi = value; + elf_abi = std::string(value); ++num_keys_decoded; } } @@ -2140,7 +2154,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { uint32_t GDBRemoteCommunicationClient::FindProcesses( const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { - process_infos.Clear(); + process_infos.clear(); if (m_supports_qfProcessInfo) { StreamString packet; @@ -2220,7 +2234,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( ProcessInstanceInfo process_info; if (!DecodeProcessInfoResponse(response, process_info)) break; - process_infos.Append(process_info); + process_infos.push_back(process_info); response = StringExtractorGDBRemote(); } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == PacketResult::Success); @@ -2229,7 +2243,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( return 0; } } - return process_infos.GetSize(); + return process_infos.size(); } bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid, @@ -2536,7 +2550,7 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer( return 0; StructuredData::ObjectSP data = - StructuredData::ParseJSON(response.GetStringRef()); + StructuredData::ParseJSON(std::string(response.GetStringRef())); if (!data) return 0; @@ -2557,7 +2571,7 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer( std::string socket_name; if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name"))) - socket_name = socket_name_osp->GetStringValue(); + socket_name = std::string(socket_name_osp->GetStringValue()); if (port != 0 || !socket_name.empty()) connection_urls.emplace_back(port, socket_name); @@ -2783,12 +2797,10 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( thread_ids.push_back(1); } } else { -#if !defined(LLDB_CONFIGURATION_DEBUG) Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - LLDB_LOGF(log, "error: failed to get packet sequence mutex, not sending " - "packet 'qfThreadInfo'"); -#endif + LLDB_LOG(log, "error: failed to get packet sequence mutex, not sending " + "packet 'qfThreadInfo'"); sequence_mutex_unavailable = true; } return thread_ids.size(); @@ -3478,7 +3490,7 @@ GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, return error; } else options.setTraceParams( - static_pointer_cast<StructuredData::Dictionary>( + std::static_pointer_cast<StructuredData::Dictionary>( custom_params_sp)); } } else { @@ -3530,6 +3542,46 @@ Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( return error; } +llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse( + "qOffsets", response, /*send_async=*/false) != PacketResult::Success) + return llvm::None; + if (!response.IsNormalResponse()) + return llvm::None; + + QOffsets result; + llvm::StringRef ref = response.GetStringRef(); + const auto &GetOffset = [&] { + addr_t offset; + if (ref.consumeInteger(16, offset)) + return false; + result.offsets.push_back(offset); + return true; + }; + + if (ref.consume_front("Text=")) { + result.segments = false; + if (!GetOffset()) + return llvm::None; + if (!ref.consume_front(";Data=") || !GetOffset()) + return llvm::None; + if (ref.empty()) + return result; + if (ref.consume_front(";Bss=") && GetOffset() && ref.empty()) + return result; + } else if (ref.consume_front("TextSeg=")) { + result.segments = true; + if (!GetOffset()) + return llvm::None; + if (ref.empty()) + return result; + if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty()) + return result; + } + return llvm::None; +} + bool GDBRemoteCommunicationClient::GetModuleInfo( const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, ModuleSpec &module_spec) { @@ -3571,7 +3623,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( StringExtractor extractor(value); std::string uuid; extractor.GetHexByteString(uuid); - module_spec.GetUUID().SetFromStringRef(uuid, uuid.size() / 2); + module_spec.GetUUID().SetFromStringRef(uuid); } else if (name == "triple") { StringExtractor extractor(value); std::string triple; @@ -3607,8 +3659,7 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict->GetValueForKeyAsString("uuid", string)) return llvm::None; - if (result.GetUUID().SetFromStringRef(string, string.size() / 2) != - string.size()) + if (!result.GetUUID().SetFromStringRef(string)) return llvm::None; if (!dict->GetValueForKeyAsInteger("file_offset", integer)) @@ -3667,7 +3718,7 @@ GDBRemoteCommunicationClient::GetModulesInfo( } StructuredData::ObjectSP response_object_sp = - StructuredData::ParseJSON(response.GetStringRef()); + StructuredData::ParseJSON(std::string(response.GetStringRef())); if (!response_object_sp) return llvm::None; @@ -3722,7 +3773,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature( return false; } - const std::string &str = chunk.GetStringRef(); + const std::string &str = std::string(chunk.GetStringRef()); if (str.length() == 0) { // should have some data in chunk err.SetErrorString("Empty response from $qXfer packet"); @@ -3936,7 +3987,7 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, send_async) == PacketResult::Success) { m_supported_async_json_packets_sp = - StructuredData::ParseJSON(response.GetStringRef()); + StructuredData::ParseJSON(std::string(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 @@ -4002,7 +4053,7 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( // Build command: Configure{type_name}: serialized config data. StreamGDBRemote stream; stream.PutCString("QConfigure"); - stream.PutCString(type_name.AsCString()); + stream.PutCString(type_name.GetStringRef()); stream.PutChar(':'); if (config_sp) { // Gather the plain-text version of the configuration data. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 11fd40bce44f..8df08cbde735 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationClient_h_ -#define liblldb_GDBRemoteCommunicationClient_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONCLIENT_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONCLIENT_H #include "GDBRemoteClientBase.h" @@ -20,6 +20,7 @@ #include "lldb/Host/File.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/GDBRemote.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/StructuredData.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" @@ -31,6 +32,22 @@ namespace lldb_private { namespace process_gdb_remote { +/// The offsets used by the target when relocating the executable. Decoded from +/// qOffsets packet response. +struct QOffsets { + /// If true, the offsets field describes segments. Otherwise, it describes + /// sections. + bool segments; + + /// The individual offsets. Section offsets have two or three members. + /// Segment offsets have either one of two. + std::vector<uint64_t> offsets; +}; +inline bool operator==(const QOffsets &a, const QOffsets &b) { + return a.segments == b.segments && a.offsets == b.offsets; +} +llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets); + class GDBRemoteCommunicationClient : public GDBRemoteClientBase { public: GDBRemoteCommunicationClient(); @@ -425,6 +442,11 @@ public: bool GetSharedCacheInfoSupported(); + /// Use qOffsets to query the offset used when relocating the target + /// executable. If successful, the returned structure will contain at least + /// one value in the offsets field. + llvm::Optional<QOffsets> GetQOffsets(); + bool GetModuleInfo(const FileSpec &module_file_spec, const ArchSpec &arch_spec, ModuleSpec &module_spec); @@ -599,10 +621,12 @@ protected: LazyBool GetThreadPacketSupported(lldb::tid_t tid, llvm::StringRef packetStr); private: - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); + GDBRemoteCommunicationClient(const GDBRemoteCommunicationClient &) = delete; + const GDBRemoteCommunicationClient & + operator=(const GDBRemoteCommunicationClient &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationClient_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONCLIENT_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index 9e5646985f87..3984a45c3da1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationHistory.cpp -----------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationHistory.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index ee265ef86dff..e783e59c3455 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationHistory_h_ -#define liblldb_GDBRemoteCommunicationHistory_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONHISTORY_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONHISTORY_H #include <string> #include <vector> @@ -83,4 +83,4 @@ private: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationHistory_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONHISTORY_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 15c73e78bd44..920327e7d0ab 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationReplayServer.cpp ------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationReplayServer.cpp ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -131,22 +131,26 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( GDBRemotePacket entry = m_packet_history.back(); m_packet_history.pop_back(); + // Decode run-length encoding. + const std::string expanded_data = + GDBRemoteCommunication::ExpandRLE(entry.packet.data); + // We've handled the handshake implicitly before. Skip the packet and move // on. if (entry.packet.data == "+") continue; if (entry.type == GDBRemotePacket::ePacketTypeSend) { - if (unexpected(entry.packet.data, packet.GetStringRef())) { + if (unexpected(expanded_data, packet.GetStringRef())) { LLDB_LOG(log, "GDBRemoteCommunicationReplayServer expected packet: '{0}'", - entry.packet.data); + expanded_data); LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'", packet.GetStringRef()); #ifndef NDEBUG // This behaves like a regular assert, but prints the expected and // received packet before aborting. - printf("Reproducer expected packet: '%s'\n", entry.packet.data.c_str()); + printf("Reproducer expected packet: '%s'\n", expanded_data.c_str()); printf("Reproducer received packet: '%s'\n", packet.GetStringRef().data()); llvm::report_fatal_error("Encountered unexpected packet during replay"); @@ -155,7 +159,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( } // Ignore QEnvironment packets as they're handled earlier. - if (entry.packet.data.find("QEnvironment") == 1) { + if (expanded_data.find("QEnvironment") == 1) { assert(m_packet_history.back().type == GDBRemotePacket::ePacketTypeRecv); m_packet_history.pop_back(); @@ -283,3 +287,28 @@ thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) { return {}; } + +Status GDBRemoteCommunicationReplayServer::Connect( + process_gdb_remote::GDBRemoteCommunicationClient &client) { + repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); + if (!loader) + return Status("No loader provided."); + + static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> + multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create( + repro::Reproducer::Instance().GetLoader()); + if (!multi_loader) + return Status("No gdb remote provider found."); + + llvm::Optional<std::string> history_file = multi_loader->GetNextFile(); + if (!history_file) + return Status("No gdb remote packet log found."); + + if (auto error = LoadReplayHistory(FileSpec(*history_file))) + return Status("Unable to load replay history"); + + if (auto error = GDBRemoteCommunication::ConnectLocally(client, *this)) + return Status("Unable to connect to replay server"); + + return {}; +} diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h index 0b5e910f7c6a..c13e5ee0bf92 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -6,11 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationReplayServer_h_ -#define liblldb_GDBRemoteCommunicationReplayServer_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H // Other libraries and framework includes #include "GDBRemoteCommunication.h" +#include "GDBRemoteCommunicationClient.h" #include "GDBRemoteCommunicationHistory.h" // Project includes @@ -51,6 +52,8 @@ public: bool StartAsyncThread(); void StopAsyncThread(); + Status Connect(process_gdb_remote::GDBRemoteCommunicationClient &client); + protected: enum { eBroadcastBitAsyncContinue = (1 << 0), @@ -73,10 +76,13 @@ protected: bool m_skip_acks; private: - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationReplayServer); + GDBRemoteCommunicationReplayServer( + const GDBRemoteCommunicationReplayServer &) = delete; + const GDBRemoteCommunicationReplayServer & + operator=(const GDBRemoteCommunicationReplayServer &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationReplayServer_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index ac6ecffcf854..b78f0916b9b9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationServer.cpp ----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 86f0abf45e06..a7c2ea47e3ba 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationServer_h_ -#define liblldb_GDBRemoteCommunicationServer_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H #include <functional> #include <map> @@ -74,7 +74,9 @@ protected: PacketResult SendOKResponse(); private: - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServer); + GDBRemoteCommunicationServer(const GDBRemoteCommunicationServer &) = delete; + const GDBRemoteCommunicationServer & + operator=(const GDBRemoteCommunicationServer &) = delete; }; class PacketUnimplementedError @@ -92,4 +94,4 @@ public: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationServer_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 4b5fc0774a6d..08d489851799 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationServerCommon.cpp ------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationServerCommon.cpp ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -334,7 +334,7 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( StringExtractorGDBRemote &packet) { m_proc_infos_index = 0; - m_proc_infos.Clear(); + m_proc_infos.clear(); ProcessInstanceInfoMatch match_info; packet.SetFilePos(::strlen("qfProcessInfo")); @@ -416,10 +416,9 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo( StringExtractorGDBRemote &packet) { - if (m_proc_infos_index < m_proc_infos.GetSize()) { + if (m_proc_infos_index < m_proc_infos.size()) { StreamString response; - CreateProcessInfoResponse( - m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); + CreateProcessInfoResponse(m_proc_infos[m_proc_infos_index], response); ++m_proc_infos_index; return SendPacketNoLock(response.GetString()); } @@ -843,6 +842,7 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported( response.PutCString(";QThreadSuffixSupported+"); response.PutCString(";QListThreadsInStopReply+"); response.PutCString(";qEcho+"); + response.PutCString(";qXfer:features:read+"); #if defined(__linux__) || defined(__NetBSD__) response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); @@ -1228,7 +1228,7 @@ void GDBRemoteCommunicationServerCommon:: if (cpu_subtype != 0) response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype); - const std::string vendor = proc_triple.getVendorName(); + const std::string vendor = proc_triple.getVendorName().str(); if (!vendor.empty()) response.Printf("vendor:%s;", vendor.c_str()); #else @@ -1237,7 +1237,7 @@ void GDBRemoteCommunicationServerCommon:: response.PutStringAsRawHex8(proc_triple.getTriple()); response.PutChar(';'); #endif - std::string ostype = proc_triple.getOSName(); + std::string ostype = std::string(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()) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 525546312470..0f933c09cbd4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationServerCommon_h_ -#define liblldb_GDBRemoteCommunicationServerCommon_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERCOMMON_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERCOMMON_H #include <string> @@ -152,4 +152,4 @@ private: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationServerCommon_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERCOMMON_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index f33f0ee66304..ae2f4bd041c9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationServerLLGS.cpp --------------------*- C++ -*-===// +//===-- GDBRemoteCommunicationServerLLGS.cpp ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -377,6 +377,99 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf, } } +static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo ®_info) { + switch (reg_info.encoding) { + case eEncodingUint: + return "uint"; + case eEncodingSint: + return "sint"; + case eEncodingIEEE754: + return "ieee754"; + case eEncodingVector: + return "vector"; + default: + return ""; + } +} + +static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo ®_info) { + switch (reg_info.format) { + case eFormatBinary: + return "binary"; + case eFormatDecimal: + return "decimal"; + case eFormatHex: + return "hex"; + case eFormatFloat: + return "float"; + case eFormatVectorOfSInt8: + return "vector-sint8"; + case eFormatVectorOfUInt8: + return "vector-uint8"; + case eFormatVectorOfSInt16: + return "vector-sint16"; + case eFormatVectorOfUInt16: + return "vector-uint16"; + case eFormatVectorOfSInt32: + return "vector-sint32"; + case eFormatVectorOfUInt32: + return "vector-uint32"; + case eFormatVectorOfFloat32: + return "vector-float32"; + case eFormatVectorOfUInt64: + return "vector-uint64"; + case eFormatVectorOfUInt128: + return "vector-uint128"; + default: + return ""; + }; +} + +static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo ®_info) { + switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) { + case LLDB_REGNUM_GENERIC_PC: + return "pc"; + case LLDB_REGNUM_GENERIC_SP: + return "sp"; + case LLDB_REGNUM_GENERIC_FP: + return "fp"; + case LLDB_REGNUM_GENERIC_RA: + return "ra"; + case LLDB_REGNUM_GENERIC_FLAGS: + return "flags"; + case LLDB_REGNUM_GENERIC_ARG1: + return "arg1"; + case LLDB_REGNUM_GENERIC_ARG2: + return "arg2"; + case LLDB_REGNUM_GENERIC_ARG3: + return "arg3"; + case LLDB_REGNUM_GENERIC_ARG4: + return "arg4"; + case LLDB_REGNUM_GENERIC_ARG5: + return "arg5"; + case LLDB_REGNUM_GENERIC_ARG6: + return "arg6"; + case LLDB_REGNUM_GENERIC_ARG7: + return "arg7"; + case LLDB_REGNUM_GENERIC_ARG8: + return "arg8"; + default: + return ""; + } +} + +static void CollectRegNums(const uint32_t *reg_num, StreamString &response, + bool usehex) { + for (int i = 0; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { + if (i > 0) + response.PutChar(','); + if (usehex) + response.Printf("%" PRIx32, *reg_num); + else + response.Printf("%" PRIu32, *reg_num); + } +} + static void WriteRegisterValueInHexFixedWidth( StreamString &response, NativeRegisterContext ®_ctx, const RegisterInfo ®_info, const RegisterValue *reg_value_p, @@ -922,9 +1015,9 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { } Status GDBRemoteCommunicationServerLLGS::InitializeConnection( - std::unique_ptr<Connection> &&connection) { + std::unique_ptr<Connection> connection) { IOObjectSP read_object_sp = connection->GetReadObject(); - GDBRemoteCommunicationServer::SetConnection(connection.release()); + GDBRemoteCommunicationServer::SetConnection(std::move(connection)); Status error; m_network_handle_up = m_mainloop.RegisterReadObject( @@ -960,7 +1053,7 @@ Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { } m_stdio_communication.SetCloseOnEOF(false); - m_stdio_communication.SetConnection(conn_up.release()); + m_stdio_communication.SetConnection(std::move(conn_up)); if (!m_stdio_communication.IsConnected()) { error.SetErrorString( "failed to set connection for inferior I/O communication"); @@ -1072,7 +1165,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); options.setTraceParams( - static_pointer_cast<StructuredData::Dictionary>(custom_params_sp)); + std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp)); if (buffersize == std::numeric_limits<uint64_t>::max() || type != lldb::TraceType::eTraceTypeProcessorTrace) { @@ -1699,74 +1792,18 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( 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; - } + llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); + if (!encoding.empty()) + response << "encoding:" << encoding << ';'; - 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 eFormatVectorOfUInt64: - response.PutCString("format:vector-uint64;"); - break; - case eFormatVectorOfUInt128: - response.PutCString("format:vector-uint128;"); - break; - default: - break; - }; + llvm::StringRef format = GetFormatNameOrEmpty(*reg_info); + if (!format.empty()) + response << "format:" << format << ';'; const char *const register_set_name = reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); - if (register_set_name) { - response.PutCString("set:"); - response.PutCString(register_set_name); - response.PutChar(';'); - } + if (register_set_name) + response << "set:" << register_set_name << ';'; if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) @@ -1777,71 +1814,19 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( 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; - } + llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info); + if (!kind_generic.empty()) + response << "generic:" << kind_generic << ';'; 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); - } + CollectRegNums(reg_info->value_regs, response, true); 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); - } + CollectRegNums(reg_info->invalidate_regs, response, true); response.PutChar(';'); } @@ -2055,7 +2040,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { packet, "P packet missing '=' char after register number"); // Parse out the value. - uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register + uint8_t reg_bytes[RegisterValue::kMaxRegisterByteSize]; size_t reg_size = packet.GetHexBytesAvail(reg_bytes); // Get the thread to use. @@ -2510,7 +2495,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( ConstString name = region_info.GetName(); if (name) { response.PutCString("name:"); - response.PutStringAsRawHex8(name.AsCString()); + response.PutStringAsRawHex8(name.GetStringRef()); response.PutChar(';'); } } @@ -2751,16 +2736,118 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { } llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> +GDBRemoteCommunicationServerLLGS::BuildTargetXml() { + // Ensure we have a thread. + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); + if (!thread) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "No thread available"); + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + // Get the register context for the first thread. + NativeRegisterContext ®_context = thread->GetRegisterContext(); + + StreamString response; + + response.Printf("<?xml version=\"1.0\"?>"); + response.Printf("<target version=\"1.0\">"); + + response.Printf("<architecture>%s</architecture>", + m_debugged_process_up->GetArchitecture() + .GetTriple() + .getArchName() + .str() + .c_str()); + + response.Printf("<feature>"); + + const int registers_count = reg_context.GetUserRegisterCount(); + for (int reg_index = 0; reg_index < registers_count; reg_index++) { + const RegisterInfo *reg_info = + reg_context.GetRegisterInfoAtIndex(reg_index); + + if (!reg_info) { + LLDB_LOGF(log, + "%s failed to get register info for register index %" PRIu32, + "target.xml", reg_index); + continue; + } + + response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" offset=\"%" PRIu32 + "\" regnum=\"%d\" ", + reg_info->name, reg_info->byte_size * 8, + reg_info->byte_offset, reg_index); + + if (reg_info->alt_name && reg_info->alt_name[0]) + response.Printf("altname=\"%s\" ", reg_info->alt_name); + + llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); + if (!encoding.empty()) + response << "encoding=\"" << encoding << "\" "; + + llvm::StringRef format = GetFormatNameOrEmpty(*reg_info); + if (!format.empty()) + response << "format=\"" << format << "\" "; + + const char *const register_set_name = + reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); + if (register_set_name) + response << "group=\"" << register_set_name << "\" "; + + if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != + LLDB_INVALID_REGNUM) + response.Printf("ehframe_regnum=\"%" PRIu32 "\" ", + reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); + + if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != + LLDB_INVALID_REGNUM) + response.Printf("dwarf_regnum=\"%" PRIu32 "\" ", + reg_info->kinds[RegisterKind::eRegisterKindDWARF]); + + llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info); + if (!kind_generic.empty()) + response << "generic=\"" << kind_generic << "\" "; + + if (reg_info->value_regs && + reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { + response.PutCString("value_regnums=\""); + CollectRegNums(reg_info->value_regs, response, false); + response.Printf("\" "); + } + + if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { + response.PutCString("invalidate_regnums=\""); + CollectRegNums(reg_info->invalidate_regs, response, false); + response.Printf("\" "); + } + + 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.Printf("\" "); + } + + response.Printf("/>"); + } + + response.Printf("</feature>"); + response.Printf("</target>"); + return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml"); +} + +llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, llvm::StringRef annex) { - if (object == "auxv") { - // Make sure we have a valid process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "No process available"); - } + // Make sure we have a valid process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "No process available"); + } + if (object == "auxv") { // Grab the auxv data. auto buffer_or_error = m_debugged_process_up->GetAuxvData(); if (!buffer_or_error) @@ -2786,6 +2873,9 @@ GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__); } + if (object == "features" && annex == "target.xml") + return BuildTargetXml(); + return llvm::make_error<PacketUnimplementedError>( "Xfer object not supported"); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 088ba92ad11a..3ce285910c25 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationServerLLGS_h_ -#define liblldb_GDBRemoteCommunicationServerLLGS_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERLLGS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERLLGS_H #include <mutex> #include <unordered_map> @@ -67,7 +67,7 @@ public: void DidExec(NativeProcessProtocol *process) override; - Status InitializeConnection(std::unique_ptr<Connection> &&connection); + Status InitializeConnection(std::unique_ptr<Connection> connection); protected: MainLoop &m_mainloop; @@ -199,6 +199,8 @@ protected: static std::string XMLEncodeAttributeValue(llvm::StringRef value); private: + llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml(); + void HandleInferiorState_Exited(NativeProcessProtocol *process); void HandleInferiorState_Stopped(NativeProcessProtocol *process); @@ -222,10 +224,13 @@ private: void StopSTDIOForwarding(); // For GDBRemoteCommunicationServerLLGS only - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerLLGS); + GDBRemoteCommunicationServerLLGS(const GDBRemoteCommunicationServerLLGS &) = + delete; + const GDBRemoteCommunicationServerLLGS & + operator=(const GDBRemoteCommunicationServerLLGS &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERLLGS_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 25cebbba8f7b..d14b79a03d17 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===// +//===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -173,7 +173,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( uint16_t port = UINT16_MAX; while (packet.GetNameColonValue(name, value)) { if (name.equals("host")) - hostname = value; + hostname = std::string(value); else if (name.equals("port")) value.getAsInteger(0, port); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index eacc99a012db..a8cacea78835 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_ -#define liblldb_GDBRemoteCommunicationServerPlatform_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H #include <map> #include <mutex> @@ -100,10 +100,13 @@ private: static FileSpec GetDomainSocketPath(const char *prefix); - DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerPlatform); + GDBRemoteCommunicationServerPlatform( + const GDBRemoteCommunicationServerPlatform &) = delete; + const GDBRemoteCommunicationServerPlatform & + operator=(const GDBRemoteCommunicationServerPlatform &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVERPLATFORM_H diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index ec1a54afd727..1f31b45d0fa9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -1,4 +1,4 @@ -//===-- GDBRemoteRegisterContext.cpp ----------------------------*- C++ -*-===// +//===-- GDBRemoteRegisterContext.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index b42c87b5991b..015862587103 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_GDBRemoteRegisterContext_h_ -#define lldb_GDBRemoteRegisterContext_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERCONTEXT_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERCONTEXT_H #include <vector> @@ -88,9 +88,7 @@ protected: void SetAllRegisterValid(bool b); 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; @@ -103,9 +101,7 @@ protected: } 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; } @@ -124,10 +120,12 @@ private: bool SetPrimordialRegister(const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm); - DISALLOW_COPY_AND_ASSIGN(GDBRemoteRegisterContext); + GDBRemoteRegisterContext(const GDBRemoteRegisterContext &) = delete; + const GDBRemoteRegisterContext & + operator=(const GDBRemoteRegisterContext &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // lldb_GDBRemoteRegisterContext_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERCONTEXT_H diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index a49db5d9a934..1fed8e064267 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1,4 +1,4 @@ -//===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===// +//===-- ProcessGDBRemote.cpp ----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,6 +17,9 @@ #include <unistd.h> #endif #include <sys/stat.h> +#if defined(__APPLE__) +#include <sys/sysctl.h> +#endif #include <sys/types.h> #include <time.h> @@ -90,6 +93,8 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +LLDB_PLUGIN_DEFINE(ProcessGDBRemote) + 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 @@ -184,21 +189,6 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { #define HIGH_PORT (49151u) #endif -#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); - - 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; @@ -359,7 +349,8 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition( 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(); + std::string triple_string = + std::string(triple_string_value->GetValue()); ArchSpec host_arch(triple_string.c_str()); if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) { GetTarget().SetArchitecture(host_arch); @@ -638,15 +629,17 @@ Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, return WillLaunchOrAttach(); } -Status ProcessGDBRemote::DoConnectRemote(Stream *strm, - llvm::StringRef remote_url) { +Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error(WillLaunchOrAttach()); if (error.Fail()) return error; - error = ConnectToDebugserver(remote_url); + if (repro::Reproducer::Instance().IsReplaying()) + error = ConnectToReplayServer(); + else + error = ConnectToDebugserver(remote_url); if (error.Fail()) return error; @@ -824,22 +817,23 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, // 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, nullptr, 0)) { - FileSpec slave_name{pty.GetSlaveName(nullptr, 0)}; + pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY, nullptr, 0)) { + FileSpec secondary_name{pty.GetSecondaryName(nullptr, 0)}; if (!stdin_file_spec) - stdin_file_spec = slave_name; + stdin_file_spec = secondary_name; if (!stdout_file_spec) - stdout_file_spec = slave_name; + stdout_file_spec = secondary_name; if (!stderr_file_spec) - stderr_file_spec = slave_name; + stderr_file_spec = secondary_name; } LLDB_LOGF( log, "ProcessGDBRemote::%s adjusted STDIO paths for local platform " - "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", + "(IsHost() is true) using secondary: stdin=%s, stdout=%s, " + "stderr=%s", __FUNCTION__, stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", @@ -924,8 +918,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, SetPrivateState(SetThreadStopInfo(response)); if (!disable_stdio) { - if (pty.GetMasterFileDescriptor() != PseudoTerminal::invalid_fd) - SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor()); + if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd) + SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor()); } } } else { @@ -957,7 +951,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { uint32_t retry_count = 0; while (!m_gdb_comm.IsConnected()) { if (conn_up->Connect(connect_url, &error) == eConnectionStatusSuccess) { - m_gdb_comm.SetConnection(conn_up.release()); + m_gdb_comm.SetConnection(std::move(conn_up)); break; } else if (error.WasInterrupted()) { // If we were interrupted, don't keep retrying. @@ -1023,122 +1017,113 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); - if (GetID() != LLDB_INVALID_PROCESS_ID) { - BuildDynamicRegisterInfo(false); + BuildDynamicRegisterInfo(false); - // See if the GDB server supports the qHostInfo information + // See if the GDB server supports qHostInfo or qProcessInfo packets. Prefer + // qProcessInfo 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; + LLDB_LOG(log, "gdb-remote had process architecture, using {0} {1}", + process_arch.GetArchitectureName(), + process_arch.GetTriple().getTriple()); + } else { + process_arch = m_gdb_comm.GetHostArchitecture(); + LLDB_LOG(log, + "gdb-remote did not have process architecture, using gdb-remote " + "host architecture {0} {1}", + process_arch.GetArchitectureName(), + process_arch.GetTriple().getTriple()); + } - const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); - if (remote_process_arch.IsValid()) { - process_arch = remote_process_arch; - LLDB_LOGF(log, - "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(); - LLDB_LOGF(log, - "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()) { + LLDB_LOG(log, "analyzing target arch, currently {0} {1}", + target_arch.GetArchitectureName(), + target_arch.GetTriple().getTriple()); + + // 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); + LLDB_LOG(log, + "remote process is ARM/Apple, " + "setting target arch to {0} {1}", + process_arch.GetArchitectureName(), + process_arch.GetTriple().getTriple()); + } 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 (process_arch.IsValid()) { - const ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid()) { - LLDB_LOGF(log, - "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); - LLDB_LOGF(log, - "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()); - } + if (new_target_triple.getOSName().size() == 0) { + new_target_triple.setOS(remote_triple.getOS()); - ArchSpec new_target_arch = target_arch; - new_target_arch.SetTriple(new_target_triple); - GetTarget().SetArchitecture(new_target_arch); + if (new_target_triple.getEnvironmentName().size() == 0) + new_target_triple.setEnvironment(remote_triple.getEnvironment()); } - } - LLDB_LOGF(log, - "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); + ArchSpec new_target_arch = target_arch; + new_target_arch.SetTriple(new_target_triple); + GetTarget().SetArchitecture(new_target_arch); + } } + + LLDB_LOG(log, + "final target arch after adjustments for remote architecture: " + "{0} {1}", + target_arch.GetArchitectureName(), + target_arch.GetTriple().getTriple()); + } 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); } + } + + MaybeLoadExecutableModule(); + + // Find out which StructuredDataPlugins are supported by the debug monitor. + // These plugins transmit data over async $J packets. + if (StructuredData::Array *supported_packets = + m_gdb_comm.GetSupportedStructuredDataPlugins()) + MapSupportedStructuredDataPlugins(*supported_packets); +} + +void ProcessGDBRemote::MaybeLoadExecutableModule() { + ModuleSP module_sp = GetTarget().GetExecutableModule(); + if (!module_sp) + return; + + llvm::Optional<QOffsets> offsets = m_gdb_comm.GetQOffsets(); + if (!offsets) + return; - // 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); + bool is_uniform = + size_t(llvm::count(offsets->offsets, offsets->offsets[0])) == + offsets->offsets.size(); + if (!is_uniform) + return; // TODO: Handle non-uniform responses. + + bool changed = false; + module_sp->SetLoadAddress(GetTarget(), offsets->offsets[0], + /*value_is_offset=*/true, changed); + if (changed) { + ModuleList list; + list.Append(module_sp); + m_process->GetTarget().ModulesDidLoad(list); } } @@ -1576,7 +1561,8 @@ bool ProcessGDBRemote::UpdateThreadIDList() { 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(); + const std::string &stop_info_str = + std::string(stop_info.GetStringRef()); m_thread_pcs.clear(); const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); @@ -2040,14 +2026,14 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { }); } } else if (key == g_key_name) { - thread_name = object->GetStringValue(); + thread_name = std::string(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(); + queue_name = std::string(object->GetStringValue()); } else if (key == g_key_queue_kind) { - std::string queue_kind_str = object->GetStringValue(); + std::string queue_kind_str = std::string(object->GetStringValue()); if (queue_kind_str == "serial") { queue_vars_valid = true; queue_kind = eQueueKindSerial; @@ -2071,9 +2057,9 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { else associated_with_dispatch_queue = eLazyBoolNo; } else if (key == g_key_reason) { - reason = object->GetStringValue(); + reason = std::string(object->GetStringValue()); } else if (key == g_key_description) { - description = object->GetStringValue(); + description = std::string(object->GetStringValue()); } else if (key == g_key_registers) { StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); @@ -2084,7 +2070,8 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { const uint32_t reg = StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10); if (reg != UINT32_MAX) - expedited_register_map[reg] = object->GetStringValue(); + expedited_register_map[reg] = + std::string(object->GetStringValue()); return true; // Keep iterating through all array items }); } @@ -2227,7 +2214,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { // Now convert the HEX bytes into a string value name_extractor.GetHexByteString(thread_name); } else if (key.compare("name") == 0) { - thread_name = value; + thread_name = std::string(value); } else if (key.compare("qaddr") == 0) { value.getAsInteger(16, thread_dispatch_qaddr); } else if (key.compare("dispatch_queue_t") == 0) { @@ -2248,7 +2235,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { if (!value.getAsInteger(0, queue_serial_number)) queue_vars_valid = true; } else if (key.compare("reason") == 0) { - reason = value; + reason = std::string(value); } else if (key.compare("description") == 0) { StringExtractor desc_extractor(value); // Now convert the HEX bytes into a string value @@ -2297,7 +2284,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { reason = "watchpoint"; StreamString ostr; ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); - description = ostr.GetString(); + description = std::string(ostr.GetString()); } else if (key.compare("library") == 0) { auto error = LoadModules(); if (error) { @@ -2308,7 +2295,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { } 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); + expedited_register_map[reg] = std::string(std::move(value)); } } @@ -2585,7 +2572,7 @@ Status ProcessGDBRemote::DoDestroy() { "to k packet: %s", response.GetStringRef().data()); exit_string.assign("got unexpected response to k packet: "); - exit_string.append(response.GetStringRef()); + exit_string.append(std::string(response.GetStringRef())); } } else { LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy - failed to send k packet"); @@ -3127,7 +3114,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { if (error_no != UINT8_MAX) error.SetErrorStringWithFormat( - "error: %d sending the breakpoint request", errno); + "error: %d sending the breakpoint request", error_no); else error.SetErrorString("error sending the breakpoint request"); return error; @@ -3356,30 +3343,10 @@ Status ProcessGDBRemote::DoSignal(int signo) { return error; } -Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { - if (!loader) - return Status("No loader provided."); - - static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> - multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create( - repro::Reproducer::Instance().GetLoader()); - - if (!multi_loader) - return Status("No gdb remote provider found."); - - llvm::Optional<std::string> history_file = multi_loader->GetNextFile(); - if (!history_file) - return Status("No gdb remote packet log found."); - - // Load replay history. - if (auto error = - m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file))) - return Status("Unable to load replay history"); - - // Make a local connection. - if (auto error = GDBRemoteCommunication::ConnectLocally(m_gdb_comm, - m_gdb_replay_server)) - return Status("Unable to connect to replay server"); +Status ProcessGDBRemote::ConnectToReplayServer() { + Status status = m_gdb_replay_server.Connect(m_gdb_comm); + if (status.Fail()) + return status; // Enable replay mode. m_replay_mode = true; @@ -3404,8 +3371,8 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { if (platform_sp && !platform_sp->IsHost()) return Status("Lost debug server connection"); - if (repro::Loader *loader = repro::Reproducer::Instance().GetLoader()) - return ConnectToReplayServer(loader); + if (repro::Reproducer::Instance().IsReplaying()) + return ConnectToReplayServer(); auto error = LaunchAndConnectToDebugserver(process_info); if (error.Fail()) { @@ -3452,6 +3419,23 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false); debugserver_launch_info.SetUserID(process_info.GetUserID()); +#if defined(__APPLE__) + // On macOS 11, we need to support x86_64 applications translated to + // arm64. We check whether a binary is translated and spawn the correct + // debugserver accordingly. + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, + static_cast<int>(process_info.GetProcessID()) }; + 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_TRANSLATED) { + FileSpec rosetta_debugserver("/Library/Apple/usr/libexec/oah/debugserver"); + debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false); + } + } +#endif + int communication_fd = -1; #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION // Use a socketpair on non-Windows systems for security and performance @@ -3486,7 +3470,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( // Our process spawned correctly, we can now set our connection to use // our end of the socket pair cleanup_our.release(); - m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true)); + m_gdb_comm.SetConnection( + std::make_unique<ConnectionFileDescriptor>(our_socket, true)); #endif StartAsyncThread(); } @@ -3648,7 +3633,7 @@ void ProcessGDBRemote::StopAsyncThread() { bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) { // get the packet at a string - const std::string &pkt = packet.GetStringRef(); + const std::string &pkt = std::string(packet.GetStringRef()); // skip %stop: StringExtractorGDBRemote stop_info(pkt.c_str() + 5); @@ -3794,7 +3779,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { } // switch(stop_state) } // else // if in All-stop-mode } // if (continue_packet) - } // case eBroadcastBitAysncContinue + } // case eBroadcastBitAsyncContinue break; case eBroadcastBitAsyncThreadShouldExit: @@ -4030,7 +4015,8 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { - object_sp = StructuredData::ParseJSON(response.GetStringRef()); + object_sp = + StructuredData::ParseJSON(std::string(response.GetStringRef())); } } } @@ -4102,7 +4088,8 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { - object_sp = StructuredData::ParseJSON(response.GetStringRef()); + object_sp = + StructuredData::ParseJSON(std::string(response.GetStringRef())); } } } @@ -4135,7 +4122,8 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { - object_sp = StructuredData::ParseJSON(response.GetStringRef()); + object_sp = + StructuredData::ParseJSON(std::string(response.GetStringRef())); } } } @@ -4419,7 +4407,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, }); if (!gdb_type.empty() && !(encoding_set || format_set)) { - if (gdb_type.find("int") == 0) { + if (llvm::StringRef(gdb_type).startswith("int")) { reg_info.format = eFormatHex; reg_info.encoding = eEncodingUint; } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { @@ -4682,7 +4670,7 @@ llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { // value. module.set_base_is_offset(true); } else if (name == "l_ld") { - // the memory address of the libraries PT_DYAMIC section. + // the memory address of the libraries PT_DYNAMIC section. module.set_dynamic(StringConvert::ToUInt64( value.data(), LLDB_INVALID_ADDRESS, 0)); } @@ -5069,7 +5057,8 @@ ParseStructuredDataPacket(llvm::StringRef packet) { } // This is an asynchronous JSON packet, destined for a StructuredDataPlugin. - StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet); + StructuredData::ObjectSP json_sp = + StructuredData::ParseJSON(std::string(packet)); if (log) { if (json_sp) { StreamString json_str; @@ -5276,7 +5265,7 @@ public: result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); - std::string response_str = response.GetStringRef(); + std::string response_str = std::string(response.GetStringRef()); if (strstr(packet_cstr, "qGetProfileData") != nullptr) { response_str = process->HarmonizeThreadIdsForProfileData(response); @@ -5329,7 +5318,7 @@ public: [&output_strm](llvm::StringRef output) { output_strm << output; }); result.SetStatus(eReturnStatusSuccessFinishResult); output_strm.Printf(" packet: %s\n", packet.GetData()); - const std::string &response_str = response.GetStringRef(); + const std::string &response_str = std::string(response.GetStringRef()); if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 9ea3940103b6..ba967727ae3b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ProcessGDBRemote_h_ -#define liblldb_ProcessGDBRemote_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTE_H #include <atomic> #include <map> @@ -85,7 +85,7 @@ public: Status WillAttachToProcessWithName(const char *process_name, bool wait_for_launch) override; - Status DoConnectRemote(Stream *strm, llvm::StringRef remote_url) override; + Status DoConnectRemote(llvm::StringRef remote_url) override; Status WillLaunchOrAttach(); @@ -312,7 +312,7 @@ protected: bool UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - Status ConnectToReplayServer(repro::Loader *loader); + Status ConnectToReplayServer(); Status EstablishConnectionIfNeeded(const ProcessInfo &process_info); @@ -377,6 +377,7 @@ protected: bool UpdateThreadIDList(); void DidLaunchOrAttach(ArchSpec &process_arch); + void MaybeLoadExecutableModule(); Status ConnectToDebugserver(llvm::StringRef host_port); @@ -386,7 +387,7 @@ protected: DynamicLoader *GetDynamicLoader() override; bool GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, - std::string xml_filename, + std::string xml_filename, uint32_t &cur_reg_num, uint32_t ®_offset); @@ -449,10 +450,11 @@ private: llvm::DenseMap<ModuleCacheKey, ModuleSpec, ModuleCacheInfo> m_cached_module_specs; - DISALLOW_COPY_AND_ASSIGN(ProcessGDBRemote); + ProcessGDBRemote(const ProcessGDBRemote &) = delete; + const ProcessGDBRemote &operator=(const ProcessGDBRemote &) = delete; }; } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_ProcessGDBRemote_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTE_H diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index 8cadc45824b3..40990ef66494 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -1,4 +1,4 @@ -//===-- ProcessGDBRemoteLog.cpp ---------------------------------*- C++ -*-===// +//===-- ProcessGDBRemoteLog.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index d9b8d4536afe..bd3e993cf72a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ProcessGDBRemoteLog_h_ -#define liblldb_ProcessGDBRemoteLog_h_ - +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H #include "lldb/Utility/Log.h" @@ -43,4 +42,4 @@ public: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_ProcessGDBRemoteLog_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td index 9cbe3d40ca2c..d4c3c8b94b7e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td @@ -11,8 +11,8 @@ let Definition = "processgdbremote" in { Desc<"The file that provides the description for remote target registers.">; def UseSVR4: Property<"use-libraries-svr4", "Boolean">, Global, - DefaultFalse, - Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">; + DefaultTrue, + Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules. This setting is only effective if lldb was build with xml support.">; def UseGPacketForReading: Property<"use-g-packet-for-reading", "Boolean">, Global, DefaultFalse, diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 9da481979f73..6deabf8d5d71 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -1,4 +1,4 @@ -//===-- ThreadGDBRemote.cpp -------------------------------------*- C++ -*-===// +//===-- ThreadGDBRemote.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -311,9 +311,7 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) { read_all_registers_at_once, write_all_registers_at_once); } } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); + reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); } return reg_ctx_sp; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index c74be169abaf..5ad11170fec4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ThreadGDBRemote_h_ -#define liblldb_ThreadGDBRemote_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_THREADGDBREMOTE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_THREADGDBREMOTE_H #include <string> @@ -116,4 +116,4 @@ protected: } // namespace process_gdb_remote } // namespace lldb_private -#endif // liblldb_ThreadGDBRemote_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_THREADGDBREMOTE_H diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp index 3c0e1cb49d1d..0c7f4cbbb859 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -1,4 +1,4 @@ -//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===// +//===-- MinidumpParser.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h index 4bcb2b47d45a..c4d7612b5f8d 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_MinidumpParser_h_ -#define liblldb_MinidumpParser_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPPARSER_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPPARSER_H #include "MinidumpTypes.h" @@ -100,7 +100,6 @@ private: MinidumpParser(lldb::DataBufferSP data_sp, std::unique_ptr<llvm::object::MinidumpFile> file); -private: lldb::DataBufferSP m_data_sp; std::unique_ptr<llvm::object::MinidumpFile> m_file; ArchSpec m_arch; @@ -108,4 +107,4 @@ private: } // end namespace minidump } // end namespace lldb_private -#endif // liblldb_MinidumpParser_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPPARSER_H diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp index ed00b1cc07db..abddd79ad7dc 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -1,4 +1,4 @@ -//===-- MinidumpTypes.cpp ---------------------------------------*- C++ -*-===// +//===-- MinidumpTypes.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h index a9c807930ebf..a7ac65120e2b 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_MinidumpTypes_h_ -#define liblldb_MinidumpTypes_h_ - +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPTYPES_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPTYPES_H #include "lldb/Utility/Status.h" @@ -120,4 +119,4 @@ private: } // namespace minidump } // namespace lldb_private -#endif // liblldb_MinidumpTypes_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_MINIDUMPTYPES_H diff --git a/lldb/source/Plugins/Process/minidump/NtStructures.h b/lldb/source/Plugins/Process/minidump/NtStructures.h index fdb0cfb7981e..1dafbe4a4f50 100644 --- a/lldb/source/Plugins/Process/minidump/NtStructures.h +++ b/lldb/source/Plugins/Process/minidump/NtStructures.h @@ -1,3 +1,7 @@ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_NTSTRUCTURES_H + +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_NTSTRUCTURES_H + //===-- NtStructures.h ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -34,3 +38,5 @@ struct TEB64 { #endif // liblldb_Plugins_Process_Minidump_NtStructures_h_ } // namespace minidump } // namespace lldb_private + +#endif diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index 5c090dc6e12f..fc8ee346f449 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -1,4 +1,4 @@ -//===-- ProcessMinidump.cpp -------------------------------------*- C++ -*-===// +//===-- ProcessMinidump.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -41,6 +41,8 @@ using namespace lldb; using namespace lldb_private; using namespace minidump; +LLDB_PLUGIN_DEFINE(ProcessMinidump) + namespace { /// A minimal ObjectFile implementation providing a dummy object file for the @@ -226,8 +228,10 @@ Status ProcessMinidump::DoLoadCore() { llvm::Optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); if (!pid) { - error.SetErrorString("failed to parse PID"); - return error; + GetTarget().GetDebugger().GetAsyncErrorStream()->PutCString( + "Unable to retrieve process ID from minidump file, setting process ID " + "to 1.\n"); + pid = 1; } SetID(pid.getValue()); @@ -253,7 +257,7 @@ void ProcessMinidump::RefreshStateAfterStop() { // TODO: The definition and use of this "dump requested" constant // in Breakpad are actually Linux-specific, and for similar use - // cases on Mac/Windows it defines differnt constants, referring + // cases on Mac/Windows it defines different constants, referring // to them as "simulated" exceptions; consider moving this check // down to the OS-specific paths and checking each OS for its own // constant. diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h index 750164cf8aaf..839b0e7563f7 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ProcessMinidump_h_ -#define liblldb_ProcessMinidump_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_PROCESSMINIDUMP_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_PROCESSMINIDUMP_H #include "MinidumpParser.h" #include "MinidumpTypes.h" @@ -119,4 +119,4 @@ private: } // namespace minidump } // namespace lldb_private -#endif // liblldb_ProcessMinidump_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_PROCESSMINIDUMP_H diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp index 72dead07dcb4..eb48785263fc 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMinidump_ARM.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextMinidump_ARM.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h index 7af3b98a6fe7..857f9c0a3767 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMinidump_ARM_h_ -#define liblldb_RegisterContextMinidump_ARM_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM_H #include "MinidumpTypes.h" @@ -95,4 +95,4 @@ protected: } // end namespace minidump } // end namespace lldb_private -#endif // liblldb_RegisterContextMinidump_ARM_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM_H diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp index bbd0e14a3267..c7809c5f19b6 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMinidump_ARM64.cpp -----------------------*- C++ -*-===// +//===-- RegisterContextMinidump_ARM64.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h index f9e7f39eea60..8ae751095c04 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMinidump_ARM64_h_ -#define liblldb_RegisterContextMinidump_ARM64_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM64_H #include "MinidumpTypes.h" @@ -79,4 +79,4 @@ protected: } // end namespace minidump } // end namespace lldb_private -#endif // liblldb_RegisterContextMinidump_ARM64_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_ARM64_H diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp index 8ac2abb22093..38d7de77e3bf 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMinidump_x86_32.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextMinidump_x86_32.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h index d787f78ec7d3..9592d335eff7 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMinidump_x86_32_h_ -#define liblldb_RegisterContextMinidump_x86_32_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_32_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_32_H #include "MinidumpTypes.h" @@ -132,4 +132,4 @@ enum class MinidumpContext_x86_32_Flags : uint32_t { } // end namespace minidump } // end namespace lldb_private -#endif // liblldb_RegisterContextMinidump_x86_32_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_32_H diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp index 515ccf6b2c3c..3c593f0db6ec 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextMinidump_x86_64.cpp ----------------------*- C++ -*-===// +//===-- RegisterContextMinidump_x86_64.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h index 34ddd477a9d1..d920ea9d823f 100644 --- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h +++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextMinidump_h_ -#define liblldb_RegisterContextMinidump_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_64_H #include "MinidumpTypes.h" @@ -177,4 +177,4 @@ enum class MinidumpContext_x86_64_Flags : uint32_t { } // end namespace minidump } // end namespace lldb_private -#endif // liblldb_RegisterContextMinidump_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_REGISTERCONTEXTMINIDUMP_X86_64_H diff --git a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp index 5262de5a94c4..e146a1a1af92 100644 --- a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp @@ -1,4 +1,4 @@ -//===-- ThreadMinidump.cpp --------------------------------------*- C++ -*-===// +//===-- ThreadMinidump.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Plugins/Process/minidump/ThreadMinidump.h b/lldb/source/Plugins/Process/minidump/ThreadMinidump.h index 44c41bc9f50e..aed7cfbc1b16 100644 --- a/lldb/source/Plugins/Process/minidump/ThreadMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ThreadMinidump.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ThreadMinidump_h_ -#define liblldb_ThreadMinidump_h_ +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_THREADMINIDUMP_H +#define LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_THREADMINIDUMP_H #include "MinidumpTypes.h" @@ -42,4 +42,4 @@ protected: } // namespace minidump } // namespace lldb_private -#endif // liblldb_ThreadMinidump_h_ +#endif // LLDB_SOURCE_PLUGINS_PROCESS_MINIDUMP_THREADMINIDUMP_H |