diff options
Diffstat (limited to 'source/Host')
24 files changed, 1105 insertions, 791 deletions
diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index b82fbea90c6c..a127d58b2767 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -24,6 +24,20 @@ using namespace lldb_private; using namespace lldb_private::line_editor; +// Workaround for what looks like an OS X-specific issue, but other platforms +// may benefit from something similar if issues arise. The libedit library +// doesn't explicitly initialize the curses termcap library, which it gets away +// with until TERM is set to VT100 where it stumbles over an implementation +// assumption that may not exist on other platforms. The setupterm() function +// would normally require headers that don't work gracefully in this context, so +// the function declaraction has been hoisted here. +#if defined(__APPLE__) +extern "C" { + int setupterm(char *term, int fildes, int *errret); +} +#define USE_SETUPTERM_WORKAROUND +#endif + // Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text // with a single line editor. Preserving this illusion requires fairly careful management of cursor // state. Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(), @@ -1313,6 +1327,10 @@ Editline::GetLine (std::string &line, bool &interrupted) m_editor_getting_char = false; m_revert_cursor_index = -1; +#ifdef USE_SETUPTERM_WORKAROUND + setupterm((char *)0, fileno(m_output_file), (int *)0); +#endif + int count; auto input = el_wgets (m_editline, &count); @@ -1359,6 +1377,9 @@ Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted) m_revert_cursor_index = -1; while (m_editor_status == EditorStatus::Editing) { +#ifdef USE_SETUPTERM_WORKAROUND + setupterm((char *)0, fileno(m_output_file), (int *)0); +#endif int count; m_current_line_rows = -1; el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index c3c77835ce86..946f3dd6fef5 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -288,6 +288,8 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) #ifndef _WIN32 if (options & eOpenOptionNonBlocking) oflag |= O_NONBLOCK; + if (options & eOpenOptionCloseOnExec) + oflag |= O_CLOEXEC; #else oflag |= O_BINARY; #endif @@ -742,8 +744,9 @@ File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP if (num_bytes > bytes_left) num_bytes = bytes_left; + size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); std::unique_ptr<DataBufferHeap> data_heap_ap; - data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0')); + data_heap_ap.reset(new DataBufferHeap(num_bytes_plus_nul_char, '\0')); if (data_heap_ap.get()) { @@ -752,8 +755,8 @@ File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP { // Make sure we read exactly what we asked for and if we got // less, adjust the array - if (num_bytes < data_heap_ap->GetByteSize()) - data_heap_ap->SetByteSize(num_bytes); + if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); data_buffer_sp.reset(data_heap_ap.release()); return error; } diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp index 0af0556d30c9..6a6de53cd311 100644 --- a/source/Host/common/FileSpec.cpp +++ b/source/Host/common/FileSpec.cpp @@ -65,7 +65,7 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl<char> &path) if (path.empty() || path[0] != '~') return; - llvm::StringRef path_str(path.data()); + llvm::StringRef path_str(path.data(), path.size()); size_t slash_pos = path_str.find_first_of("/", 1); if (slash_pos == 1 || path.size() == 1) { @@ -240,6 +240,12 @@ void FileSpec::Normalize(llvm::SmallVectorImpl<char> &path, PathSyntax syntax) return; std::replace(path.begin(), path.end(), '\\', '/'); + // Windows path can have \\ slashes which can be changed by replace + // call above to //. Here we remove the duplicate. + auto iter = std::unique ( path.begin(), path.end(), + []( char &c1, char &c2 ){ + return (c1 == '/' && c2 == '/');}); + path.erase(iter, path.end()); } void FileSpec::DeNormalize(llvm::SmallVectorImpl<char> &path, PathSyntax syntax) @@ -1330,8 +1336,7 @@ FileSpec::IsSourceImplementationFile () const ConstString extension (GetFileNameExtension()); if (extension) { - static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$", - REG_EXTENDED | REG_ICASE); + static RegularExpression g_source_file_regex ("^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])$"); return g_source_file_regex.Execute (extension.GetCString()); } return false; diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index c8daa175d1bd..30f5c8683060 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C includes #include <errno.h> #include <limits.h> @@ -48,20 +46,21 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Host/Predicate.h" #include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/lldb-private-forward.h" +#include "llvm/Support/FileSystem.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Target/TargetList.h" +#include "lldb/Target/UnixSignals.h" #include "lldb/Utility/CleanUp.h" +#include "llvm/ADT/SmallString.h" #if defined(_WIN32) #include "lldb/Host/windows/ProcessLauncherWindows.h" @@ -170,7 +169,7 @@ MonitorChildProcessThreadFunction (void *arg) { log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); if (log) - log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); + log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); // Wait for all child processes #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) @@ -233,9 +232,9 @@ MonitorChildProcessThreadFunction (void *arg) if (log) log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", function, - wait_pid, - options, pid, + options, + wait_pid, status, status_cstr, signal, @@ -1053,12 +1052,6 @@ Host::SetCrashDescription (const char *description) { } -lldb::pid_t -Host::LaunchApplication (const FileSpec &app_file_spec) -{ - return LLDB_INVALID_PROCESS_ID; -} - #endif #if !defined (__linux__) && !defined (__FreeBSD__) && !defined (__NetBSD__) diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index d65b79698384..9816c1ebf080 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -23,60 +23,56 @@ #include "llvm/Support/raw_ostream.h" #include <thread> +#include <mutex> // std::once using namespace lldb; using namespace lldb_private; namespace { -void -CleanupProcessSpecificLLDBTempDir() -{ - // Get the process specific LLDB temporary directory and delete it. - FileSpec tmpdir_file_spec; - if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - return; - - // Remove the LLDB temporary directory if we have one. Set "recurse" to - // true to all files that were created for the LLDB process can be cleaned up. - FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); -} + void + CleanupProcessSpecificLLDBTempDir() + { + // Get the process specific LLDB temporary directory and delete it. + FileSpec tmpdir_file_spec; + if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + return; + + // Remove the LLDB temporary directory if we have one. Set "recurse" to + // true to all files that were created for the LLDB process can be cleaned up. + FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); + } -struct HostInfoBaseFields -{ - uint32_t m_number_cpus; - std::string m_vendor_string; - std::string m_os_string; - std::string m_host_triple; - - ArchSpec m_host_arch_32; - ArchSpec m_host_arch_64; - - FileSpec m_lldb_so_dir; - FileSpec m_lldb_support_exe_dir; - FileSpec m_lldb_headers_dir; - FileSpec m_lldb_python_dir; - FileSpec m_lldb_clang_resource_dir; - FileSpec m_lldb_system_plugin_dir; - FileSpec m_lldb_user_plugin_dir; - FileSpec m_lldb_tmp_dir; -}; - -HostInfoBaseFields *g_fields = nullptr; -} + //---------------------------------------------------------------------- + // The HostInfoBaseFields is a work around for windows not supporting + // static variables correctly in a thread safe way. Really each of the + // variables in HostInfoBaseFields should live in the functions in which + // they are used and each one should be static, but the work around is + // in place to avoid this restriction. Ick. + //---------------------------------------------------------------------- -#define COMPUTE_LLDB_PATH(compute_function, member_var) \ - { \ - static bool is_initialized = false; \ - static bool success = false; \ - if (!is_initialized) \ - { \ - is_initialized = true; \ - success = HostInfo::compute_function(member_var); \ - } \ - if (success) \ - result = &member_var; \ - } + struct HostInfoBaseFields + { + uint32_t m_number_cpus; + std::string m_vendor_string; + std::string m_os_string; + std::string m_host_triple; + + ArchSpec m_host_arch_32; + ArchSpec m_host_arch_64; + + FileSpec m_lldb_so_dir; + FileSpec m_lldb_support_exe_dir; + FileSpec m_lldb_headers_dir; + FileSpec m_lldb_python_dir; + FileSpec m_lldb_clang_resource_dir; + FileSpec m_lldb_system_plugin_dir; + FileSpec m_lldb_user_plugin_dir; + FileSpec m_lldb_tmp_dir; + }; + + HostInfoBaseFields *g_fields = nullptr; +} void HostInfoBase::Initialize() @@ -87,13 +83,10 @@ HostInfoBase::Initialize() uint32_t HostInfoBase::GetNumberCPUS() { - static bool is_initialized = false; - if (!is_initialized) - { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { g_fields->m_number_cpus = std::thread::hardware_concurrency(); - is_initialized = true; - } - + }); return g_fields->m_number_cpus; } @@ -106,53 +99,40 @@ HostInfoBase::GetMaxThreadNameLength() llvm::StringRef HostInfoBase::GetVendorString() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName(); - g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end()); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str()); + }); return g_fields->m_vendor_string; } llvm::StringRef HostInfoBase::GetOSString() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName(); - g_fields->m_os_string.assign(str_ref.begin(), str_ref.end()); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); + }); return g_fields->m_os_string; } llvm::StringRef HostInfoBase::GetTargetTriple() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - g_fields->m_host_triple = host_arch.GetTriple().getTriple(); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple(); + }); return g_fields->m_host_triple; } const ArchSpec & HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { - static bool is_initialized = false; - if (!is_initialized) - { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); - is_initialized = true; - } + }); // If an explicit 32 or 64-bit architecture was requested, return that. if (arch_kind == eArchKind32) @@ -174,52 +154,123 @@ HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) return false; #endif - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); FileSpec *result = nullptr; switch (type) { case lldb::ePathTypeLLDBShlibDir: - COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_so_dir; + } break; case lldb::ePathTypeSupportExecutableDir: - COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", - g_fields->m_lldb_support_exe_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", + g_fields->m_lldb_support_exe_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_support_exe_dir; + } break; case lldb::ePathTypeHeaderDir: - COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_headers_dir; + } break; case lldb::ePathTypePythonDir: - COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_python_dir; + } break; case lldb::ePathTypeClangDir: - COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_clang_resource_dir; + } break; case lldb::ePathTypeLLDBSystemPlugins: - COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", - g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", + g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_system_plugin_dir; + } break; case lldb::ePathTypeLLDBUserPlugins: - COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", - g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", + g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_user_plugin_dir; + } break; case lldb::ePathTypeLLDBTempSystemDir: - COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_tmp_dir; + } break; } @@ -327,6 +378,7 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6 arch_32.SetTriple(triple); break; + case llvm::Triple::ppc64: case llvm::Triple::x86_64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); @@ -335,7 +387,6 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6 case llvm::Triple::aarch64: case llvm::Triple::mips64: case llvm::Triple::sparcv9: - case llvm::Triple::ppc64: arch_64.SetTriple(triple); break; } diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp index 284d7d11d6ce..622b4eab1726 100644 --- a/source/Host/common/NativeBreakpoint.cpp +++ b/source/Host/common/NativeBreakpoint.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "NativeBreakpoint.h" +#include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/lldb-defines.h" #include "lldb/Core/Error.h" diff --git a/source/Host/common/NativeBreakpoint.h b/source/Host/common/NativeBreakpoint.h deleted file mode 100644 index 367003b94e35..000000000000 --- a/source/Host/common/NativeBreakpoint.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- NativeBreakpoint.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeBreakpoint_h_ -#define liblldb_NativeBreakpoint_h_ - -#include "lldb/lldb-types.h" - -namespace lldb_private -{ - class NativeBreakpointList; - - class NativeBreakpoint - { - friend class NativeBreakpointList; - - public: - // The assumption is that derived breakpoints are enabled when created. - NativeBreakpoint (lldb::addr_t addr); - - virtual - ~NativeBreakpoint (); - - Error - Enable (); - - Error - Disable (); - - lldb::addr_t - GetAddress () const { return m_addr; } - - bool - IsEnabled () const { return m_enabled; } - - virtual bool - IsSoftwareBreakpoint () const = 0; - - protected: - const lldb::addr_t m_addr; - int32_t m_ref_count; - - virtual Error - DoEnable () = 0; - - virtual Error - DoDisable () = 0; - - private: - bool m_enabled; - - // ----------------------------------------------------------- - // interface for NativeBreakpointList - // ----------------------------------------------------------- - void AddRef (); - int32_t DecRef (); - }; -} - -#endif // ifndef liblldb_NativeBreakpoint_h_ diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp index ecd0624bde09..94d0b3756da4 100644 --- a/source/Host/common/NativeBreakpointList.cpp +++ b/source/Host/common/NativeBreakpointList.cpp @@ -1,4 +1,4 @@ -//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===// +//===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "NativeBreakpointList.h" +#include "lldb/Host/common/NativeBreakpointList.h" #include "lldb/Core/Log.h" -#include "NativeBreakpoint.h" +#include "lldb/Host/common/NativeBreakpoint.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Host/common/NativeBreakpointList.h b/source/Host/common/NativeBreakpointList.h deleted file mode 100644 index 51617330d075..000000000000 --- a/source/Host/common/NativeBreakpointList.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeBreakpointList_h_ -#define liblldb_NativeBreakpointList_h_ - -#include "lldb/lldb-private-forward.h" -#include "lldb/Core/Error.h" -#include "lldb/Host/Mutex.h" -// #include "lldb/Host/NativeBreakpoint.h" - -#include <functional> -#include <map> - -namespace lldb_private -{ - class NativeBreakpointList - { - public: - typedef std::function<Error (lldb::addr_t addr, size_t size_hint, bool hardware, NativeBreakpointSP &breakpoint_sp)> CreateBreakpointFunc; - - NativeBreakpointList (); - - Error - AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func); - - Error - DecRef (lldb::addr_t addr); - - Error - EnableBreakpoint (lldb::addr_t addr); - - Error - DisableBreakpoint (lldb::addr_t addr); - - Error - GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp); - - private: - typedef std::map<lldb::addr_t, NativeBreakpointSP> BreakpointMap; - - Mutex m_mutex; - BreakpointMap m_breakpoints; - }; -} - -#endif // ifndef liblldb_NativeBreakpointList_h_ diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index e192f19a8896..ff7310d2d45a 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -7,17 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" -#include "lldb/Target/NativeRegisterContext.h" +#include "lldb/Host/common/NativeRegisterContext.h" -#include "NativeThreadProtocol.h" -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; @@ -39,6 +39,7 @@ NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) : m_delegates_mutex (Mutex::eMutexTypeRecursive), m_delegates (), m_breakpoint_list (), + m_watchpoint_list (), m_terminal_fd (-1), m_stop_id (0) { @@ -159,6 +160,12 @@ NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const return true; } +const NativeWatchpointList::WatchpointMap& +NativeProcessProtocol::GetWatchpointMap () const +{ + return m_watchpoint_list.GetWatchpointMap(); +} + uint32_t NativeProcessProtocol::GetMaxWatchpoints () const { @@ -199,9 +206,6 @@ NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t w Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - // FIXME save the watchpoint on the set of process watchpoint vars - // so we can add them to a thread each time a new thread is registered. - // Update the thread list UpdateThreads (); @@ -261,15 +265,12 @@ NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t w return thread_error; } } - return Error (); + return m_watchpoint_list.Add (addr, size, watch_flags, hardware); } Error NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) { - // FIXME remove the watchpoint on the set of process watchpoint vars - // so we can add them to a thread each time a new thread is registered. - // Update the thread list UpdateThreads (); @@ -292,7 +293,8 @@ NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) overall_error = thread_error; } } - return overall_error; + const Error error = m_watchpoint_list.Remove(addr); + return overall_error.Fail() ? overall_error : error; } bool @@ -400,6 +402,10 @@ void NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates) { Mutex::Locker locker (m_state_mutex); + + if (state == m_state) + return; + m_state = state; if (StateIsStoppedState (state, false)) diff --git a/source/Host/common/NativeProcessProtocol.h b/source/Host/common/NativeProcessProtocol.h deleted file mode 100644 index 19d8f353b26f..000000000000 --- a/source/Host/common/NativeProcessProtocol.h +++ /dev/null @@ -1,344 +0,0 @@ -//===-- NativeProcessProtocol.h ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeProcessProtocol_h_ -#define liblldb_NativeProcessProtocol_h_ - -#include <vector> - -#include "lldb/lldb-private-forward.h" -#include "lldb/lldb-types.h" -#include "lldb/Core/Error.h" -#include "lldb/Host/Mutex.h" - -#include "NativeBreakpointList.h" - -namespace lldb_private -{ - class MemoryRegionInfo; - class ResumeActionList; - - //------------------------------------------------------------------ - // NativeProcessProtocol - //------------------------------------------------------------------ - class NativeProcessProtocol : - public std::enable_shared_from_this<NativeProcessProtocol> - { - friend class SoftwareBreakpoint; - - public: - static NativeProcessProtocol * - CreateInstance (lldb::pid_t pid); - - // lldb_private::Host calls should be used to launch a process for debugging, and - // then the process should be attached to. When attaching to a process - // lldb_private::Host calls should be used to locate the process to attach to, - // and then this function should be called. - NativeProcessProtocol (lldb::pid_t pid); - - public: - virtual ~NativeProcessProtocol () - { - } - - virtual Error - Resume (const ResumeActionList &resume_actions) = 0; - - virtual Error - Halt () = 0; - - virtual Error - Detach () = 0; - - //------------------------------------------------------------------ - /// Sends a process a UNIX signal \a signal. - /// - /// @return - /// Returns an error object. - //------------------------------------------------------------------ - virtual Error - Signal (int signo) = 0; - - //------------------------------------------------------------------ - /// Tells a process to interrupt all operations as if by a Ctrl-C. - /// - /// The default implementation will send a local host's equivalent of - /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() - /// operation. - /// - /// @return - /// Returns an error object. - //------------------------------------------------------------------ - virtual Error - Interrupt (); - - virtual Error - Kill () = 0; - - //---------------------------------------------------------------------- - // Memory and memory region functions - //---------------------------------------------------------------------- - - virtual Error - GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info); - - virtual Error - ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0; - - virtual Error - WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0; - - virtual Error - AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0; - - virtual Error - DeallocateMemory (lldb::addr_t addr) = 0; - - virtual lldb::addr_t - GetSharedLibraryInfoAddress () = 0; - - virtual bool - IsAlive () const; - - virtual size_t - UpdateThreads () = 0; - - virtual bool - GetArchitecture (ArchSpec &arch) const = 0; - - //---------------------------------------------------------------------- - // Breakpoint functions - //---------------------------------------------------------------------- - virtual Error - SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) = 0; - - virtual Error - RemoveBreakpoint (lldb::addr_t addr); - - virtual Error - EnableBreakpoint (lldb::addr_t addr); - - virtual Error - DisableBreakpoint (lldb::addr_t addr); - - //---------------------------------------------------------------------- - // Watchpoint functions - //---------------------------------------------------------------------- - virtual uint32_t - GetMaxWatchpoints () const; - - virtual Error - SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware); - - virtual Error - RemoveWatchpoint (lldb::addr_t addr); - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - lldb::pid_t - GetID() const - { - return m_pid; - } - - lldb::StateType - GetState () const; - - bool - IsRunning () const - { - return m_state == lldb::eStateRunning || IsStepping(); - } - - bool - IsStepping () const - { - return m_state == lldb::eStateStepping; - } - - bool - CanResume () const - { - return m_state == lldb::eStateStopped; - } - - bool - GetByteOrder (lldb::ByteOrder &byte_order) const; - - //---------------------------------------------------------------------- - // Exit Status - //---------------------------------------------------------------------- - virtual bool - GetExitStatus (lldb_private::ExitType *exit_type, int *status, std::string &exit_description); - - virtual bool - SetExitStatus (lldb_private::ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange); - - //---------------------------------------------------------------------- - // Access to threads - //---------------------------------------------------------------------- - NativeThreadProtocolSP - GetThreadAtIndex (uint32_t idx); - - NativeThreadProtocolSP - GetThreadByID (lldb::tid_t tid); - - void - SetCurrentThreadID (lldb::tid_t tid) - { - m_current_thread_id = tid; - } - - lldb::tid_t - GetCurrentThreadID () - { - return m_current_thread_id; - } - - NativeThreadProtocolSP - GetCurrentThread () - { - return GetThreadByID (m_current_thread_id); - } - - //---------------------------------------------------------------------- - // Access to inferior stdio - //---------------------------------------------------------------------- - virtual - int GetTerminalFileDescriptor () - { - return m_terminal_fd; - } - - //---------------------------------------------------------------------- - // Stop id interface - //---------------------------------------------------------------------- - - uint32_t - GetStopID () const; - - // --------------------------------------------------------------------- - // Callbacks for low-level process state changes - // --------------------------------------------------------------------- - class NativeDelegate - { - public: - virtual - ~NativeDelegate () {} - - virtual void - InitializeDelegate (NativeProcessProtocol *process) = 0; - - virtual void - ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) = 0; - - virtual void - DidExec (NativeProcessProtocol *process) = 0; - }; - - //------------------------------------------------------------------ - /// Register a native delegate. - /// - /// Clients can register nofication callbacks by passing in a - /// NativeDelegate impl and passing it into this function. - /// - /// Note: it is required that the lifetime of the - /// native_delegate outlive the NativeProcessProtocol. - /// - /// @param[in] native_delegate - /// A NativeDelegate impl to be called when certain events - /// happen within the NativeProcessProtocol or related threads. - /// - /// @return - /// true if the delegate was registered successfully; - /// false if the delegate was already registered. - /// - /// @see NativeProcessProtocol::NativeDelegate. - //------------------------------------------------------------------ - bool - RegisterNativeDelegate (NativeDelegate &native_delegate); - - //------------------------------------------------------------------ - /// Unregister a native delegate previously registered. - /// - /// @param[in] native_delegate - /// A NativeDelegate impl previously registered with this process. - /// - /// @return Returns \b true if the NativeDelegate was - /// successfully removed from the process, \b false otherwise. - /// - /// @see NativeProcessProtocol::NativeDelegate - //------------------------------------------------------------------ - bool - UnregisterNativeDelegate (NativeDelegate &native_delegate); - - protected: - lldb::pid_t m_pid; - - std::vector<NativeThreadProtocolSP> m_threads; - lldb::tid_t m_current_thread_id; - mutable Mutex m_threads_mutex; - - lldb::StateType m_state; - mutable Mutex m_state_mutex; - - lldb_private::ExitType m_exit_type; - int m_exit_status; - std::string m_exit_description; - Mutex m_delegates_mutex; - std::vector<NativeDelegate*> m_delegates; - NativeBreakpointList m_breakpoint_list; - int m_terminal_fd; - uint32_t m_stop_id; - - // ----------------------------------------------------------- - // Internal interface for state handling - // ----------------------------------------------------------- - void - SetState (lldb::StateType state, bool notify_delegates = true); - - // Derived classes need not implement this. It can be used as a - // hook to clear internal caches that should be invalidated when - // stop ids change. - // - // Note this function is called with the state mutex obtained - // by the caller. - virtual void - DoStopIDBumped (uint32_t newBumpId); - - // ----------------------------------------------------------- - // Internal interface for software breakpoints - // ----------------------------------------------------------- - Error - SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint); - - virtual Error - GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0; - - // ----------------------------------------------------------- - /// Notify the delegate that an exec occurred. - /// - /// Provide a mechanism for a delegate to clear out any exec- - /// sensitive data. - // ----------------------------------------------------------- - void - NotifyDidExec (); - - NativeThreadProtocolSP - GetThreadByIDUnlocked (lldb::tid_t tid); - - private: - - void - SynchronouslyNotifyProcessStateChanged (lldb::StateType state); - }; -} - -#endif // #ifndef liblldb_NativeProcessProtocol_h_ diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp new file mode 100644 index 000000000000..42a9c91a63a0 --- /dev/null +++ b/source/Host/common/NativeRegisterContext.cpp @@ -0,0 +1,476 @@ +//===-- NativeRegisterContext.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/NativeRegisterContext.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/RegisterValue.h" + +#include "lldb/lldb-private-log.h" + +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" + +using namespace lldb; +using namespace lldb_private; + +NativeRegisterContext::NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx) : + m_thread (thread), + m_concrete_frame_idx (concrete_frame_idx) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +NativeRegisterContext::~NativeRegisterContext() +{ +} + +// FIXME revisit invalidation, process stop ids, etc. Right now we don't +// support caching in NativeRegisterContext. We can do this later by +// utilizing NativeProcessProtocol::GetStopID () and adding a stop id to +// NativeRegisterContext. + +// void +// NativeRegisterContext::InvalidateIfNeeded (bool force) +// { +// ProcessSP process_sp (m_thread.GetProcess()); +// bool invalidate = force; +// uint32_t process_stop_id = UINT32_MAX; + +// if (process_sp) +// process_stop_id = process_sp->GetStopID(); +// else +// invalidate = true; + +// if (!invalidate) +// invalidate = process_stop_id != GetStopID(); + +// if (invalidate) +// { +// InvalidateAllRegisters (); +// SetStopID (process_stop_id); +// } +// } + + +const RegisterInfo * +NativeRegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx) +{ + if (reg_name && reg_name[0]) + { + const uint32_t num_registers = GetRegisterCount(); + for (uint32_t reg = start_idx; reg < num_registers; ++reg) + { + const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); + + if ((reg_info->name != nullptr && ::strcasecmp (reg_info->name, reg_name) == 0) || + (reg_info->alt_name != nullptr && ::strcasecmp (reg_info->alt_name, reg_name) == 0)) + { + return reg_info; + } + } + } + return nullptr; +} + +const RegisterInfo * +NativeRegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num) +{ + const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); + if (reg_num == LLDB_INVALID_REGNUM) + return nullptr; + return GetRegisterInfoAtIndex (reg_num); +} + +const char * +NativeRegisterContext::GetRegisterName (uint32_t reg) +{ + const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info) + return reg_info->name; + return nullptr; +} + +const char* +NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const +{ + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) + return nullptr; + + for (uint32_t set_index = 0; set_index < GetRegisterSetCount (); ++set_index) + { + const RegisterSet *const reg_set = GetRegisterSet (set_index); + if (!reg_set) + continue; + + for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; ++reg_num_index) + { + const uint32_t reg_num = reg_set->registers[reg_num_index]; + // FIXME double check we're checking the right register kind here. + if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) + { + // The given register is a member of this register set. Return the register set name. + return reg_set->name; + } + } + } + + // Didn't find it. + return nullptr; +} + +lldb::addr_t +NativeRegisterContext::GetPC (lldb::addr_t fail_value) +{ + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (log) + log->Printf ("NativeRegisterContext::%s using reg index %" PRIu32 " (default %" PRIu64 ")", __FUNCTION__, reg, fail_value); + + const uint64_t retval = ReadRegisterAsUnsigned (reg, fail_value); + + if (log) + log->Printf ("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, __FUNCTION__, retval); + + return retval; +} + +Error +NativeRegisterContext::SetPC (lldb::addr_t pc) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + return WriteRegisterFromUnsigned (reg, pc); +} + +lldb::addr_t +NativeRegisterContext::GetSP (lldb::addr_t fail_value) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + return ReadRegisterAsUnsigned (reg, fail_value); +} + +Error +NativeRegisterContext::SetSP (lldb::addr_t sp) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + return WriteRegisterFromUnsigned (reg, sp); +} + +lldb::addr_t +NativeRegisterContext::GetFP (lldb::addr_t fail_value) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); + return ReadRegisterAsUnsigned (reg, fail_value); +} + +Error +NativeRegisterContext::SetFP (lldb::addr_t fp) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); + return WriteRegisterFromUnsigned (reg, fp); +} + +lldb::addr_t +NativeRegisterContext::GetReturnAddress (lldb::addr_t fail_value) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + return ReadRegisterAsUnsigned (reg, fail_value); +} + +lldb::addr_t +NativeRegisterContext::GetFlags (lldb::addr_t fail_value) +{ + uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + return ReadRegisterAsUnsigned (reg, fail_value); +} + + +lldb::addr_t +NativeRegisterContext::ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value) +{ + if (reg != LLDB_INVALID_REGNUM) + return ReadRegisterAsUnsigned (GetRegisterInfoAtIndex (reg), fail_value); + return fail_value; +} + +uint64_t +NativeRegisterContext::ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value) +{ + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + + if (reg_info) + { + RegisterValue value; + Error error = ReadRegister (reg_info, value); + if (error.Success ()) + { + if (log) + log->Printf ("NativeRegisterContext::%s ReadRegister() succeeded, value %" PRIu64, __FUNCTION__, value.GetAsUInt64()); + return value.GetAsUInt64(); + } + else + { + if (log) + log->Printf ("NativeRegisterContext::%s ReadRegister() failed, error %s", __FUNCTION__, error.AsCString ()); + } + } + else + { + if (log) + log->Printf ("NativeRegisterContext::%s ReadRegister() null reg_info", __FUNCTION__); + } + return fail_value; +} + +Error +NativeRegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval) +{ + if (reg == LLDB_INVALID_REGNUM) + return Error ("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__); + return WriteRegisterFromUnsigned (GetRegisterInfoAtIndex (reg), uval); +} + +Error +NativeRegisterContext::WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval) +{ + assert (reg_info); + if (!reg_info) + return Error ("reg_info is nullptr"); + + RegisterValue value; + if (!value.SetUInt(uval, reg_info->byte_size)) + return Error ("RegisterValue::SetUInt () failed"); + + return WriteRegister (reg_info, value); +} + +lldb::tid_t +NativeRegisterContext::GetThreadID() const +{ + return m_thread.GetID(); +} + +uint32_t +NativeRegisterContext::NumSupportedHardwareBreakpoints () +{ + return 0; +} + +uint32_t +NativeRegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) +{ + return LLDB_INVALID_INDEX32; +} + +bool +NativeRegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx) +{ + return false; +} + + +uint32_t +NativeRegisterContext::NumSupportedHardwareWatchpoints () +{ + return 0; +} + +uint32_t +NativeRegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) +{ + return LLDB_INVALID_INDEX32; +} + +bool +NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index) +{ + return false; +} + +Error +NativeRegisterContext::ClearAllHardwareWatchpoints () +{ + return Error ("not implemented"); +} + +bool +NativeRegisterContext::HardwareSingleStep (bool enable) +{ + return false; +} + +Error +NativeRegisterContext::ReadRegisterValueFromMemory ( + const RegisterInfo *reg_info, + lldb::addr_t src_addr, + lldb::addr_t src_len, + RegisterValue ®_value) +{ + Error error; + if (reg_info == nullptr) + { + error.SetErrorString ("invalid register info argument."); + return error; + } + + + // Moving from addr into a register + // + // Case 1: src_len == dst_len + // + // |AABBCCDD| Address contents + // |AABBCCDD| Register contents + // + // Case 2: src_len > dst_len + // + // Error! (The register should always be big enough to hold the data) + // + // Case 3: src_len < dst_len + // + // |AABB| Address contents + // |AABB0000| Register contents [on little-endian hardware] + // |0000AABB| Register contents [on big-endian hardware] + if (src_len > RegisterValue::kMaxRegisterByteSize) + { + error.SetErrorString ("register too small to receive memory data"); + return error; + } + + const lldb::addr_t dst_len = reg_info->byte_size; + + if (src_len > dst_len) + { + error.SetErrorStringWithFormat("%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 " bytes)", src_len, reg_info->name, dst_len); + return error; + } + + NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); + if (!process_sp) + { + error.SetErrorString("invalid process"); + return error; + } + + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Read the memory + lldb::addr_t bytes_read; + error = process_sp->ReadMemory (src_addr, src, src_len, bytes_read); + if (error.Fail ()) + return error; + + // Make sure the memory read succeeded... + if (bytes_read != src_len) + { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", bytes_read, src_len); + return error; + } + + // We now have a memory buffer that contains the part or all of the register + // value. Set the register value using this memory data. + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder (byte_order)) + { + error.SetErrorString ( "NativeProcessProtocol::GetByteOrder () failed"); + return error; + } + + reg_value.SetFromMemoryData ( + reg_info, + src, + src_len, + byte_order, + error); + + return error; +} + +Error +NativeRegisterContext::WriteRegisterValueToMemory ( + const RegisterInfo *reg_info, + lldb::addr_t dst_addr, + lldb::addr_t dst_len, + const RegisterValue ®_value) +{ + + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + Error error; + + NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); + if (process_sp) + { + + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are assuming + // they are the same. + lldb::ByteOrder byte_order; + if (!process_sp->GetByteOrder (byte_order)) + return Error ("NativeProcessProtocol::GetByteOrder () failed"); + + const lldb::addr_t bytes_copied = reg_value.GetAsMemoryData ( + reg_info, + dst, + dst_len, + byte_order, + error); + + if (error.Success()) + { + if (bytes_copied == 0) + { + error.SetErrorString("byte copy failed."); + } + else + { + lldb::addr_t bytes_written; + error = process_sp->WriteMemory (dst_addr, dst, bytes_copied, bytes_written); + if (error.Fail ()) + return error; + + if (bytes_written != bytes_copied) + { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 " bytes", bytes_written, bytes_copied); + } + } + } + } + else + error.SetErrorString("invalid process"); + + return error; +} + +uint32_t +NativeRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const +{ + 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/source/Host/common/NativeRegisterContextRegisterInfo.cpp b/source/Host/common/NativeRegisterContextRegisterInfo.cpp new file mode 100644 index 000000000000..0d7c6eced757 --- /dev/null +++ b/source/Host/common/NativeRegisterContextRegisterInfo.cpp @@ -0,0 +1,50 @@ +//===-- NativeRegisterContex.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-types.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" + +using namespace lldb_private; + +NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface) : + NativeRegisterContext (thread, concrete_frame_idx), + m_register_info_interface_up (register_info_interface) +{ + assert (register_info_interface && "null register_info_interface"); +} + +uint32_t +NativeRegisterContextRegisterInfo::GetRegisterCount () const +{ + return m_register_info_interface_up->GetRegisterCount (); +} + +uint32_t +NativeRegisterContextRegisterInfo::GetUserRegisterCount () const +{ + return m_register_info_interface_up->GetUserRegisterCount (); +} + +const RegisterInfo * +NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const +{ + if (reg_index <= GetRegisterCount ()) + return m_register_info_interface_up->GetRegisterInfo () + reg_index; + else + return nullptr; +} + +const RegisterInfoInterface& +NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const +{ + return *m_register_info_interface_up; +} diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 6cef5b1fa2d2..ea406e9ef2c6 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "NativeThreadProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" -#include "NativeProcessProtocol.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; @@ -73,25 +73,3 @@ NativeThreadProtocol::GetProcess () { return m_process_wp.lock (); } - -uint32_t -NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const -{ - // Default: no translation. Do the real translation where there - // is access to the host signal numbers. - switch (stop_info.reason) - { - case eStopReasonSignal: - return stop_info.details.signal.signo; - break; - - case eStopReasonException: - // FIXME verify the way to specify pass-thru here. - return static_cast<uint32_t> (stop_info.details.exception.type); - break; - - default: - assert (0 && "unexpected stop_info.reason found"); - return 0; - } -} diff --git a/source/Host/common/NativeThreadProtocol.h b/source/Host/common/NativeThreadProtocol.h deleted file mode 100644 index 15ecffe8b82d..000000000000 --- a/source/Host/common/NativeThreadProtocol.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- NativeThreadProtocol.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeThreadProtocol_h_ -#define liblldb_NativeThreadProtocol_h_ - -#include <memory> - -#include "lldb/lldb-private-forward.h" -#include "lldb/lldb-types.h" -#include "lldb/Host/Debug.h" - -namespace lldb_private -{ - //------------------------------------------------------------------ - // NativeThreadProtocol - //------------------------------------------------------------------ - class NativeThreadProtocol: - public std::enable_shared_from_this<NativeThreadProtocol> - { - public: - NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid); - - virtual ~NativeThreadProtocol() - { - } - - virtual std::string - GetName() = 0; - - virtual lldb::StateType - GetState () = 0; - - virtual NativeRegisterContextSP - GetRegisterContext () = 0; - - virtual Error - ReadRegister (uint32_t reg, RegisterValue ®_value); - - virtual Error - WriteRegister (uint32_t reg, const RegisterValue ®_value); - - virtual Error - SaveAllRegisters (lldb::DataBufferSP &data_sp); - - virtual Error - RestoreAllRegisters (lldb::DataBufferSP &data_sp); - - virtual bool - GetStopReason (ThreadStopInfo &stop_info) = 0; - - virtual uint32_t - TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const; - - lldb::tid_t - GetID() const - { - return m_tid; - } - - NativeProcessProtocolSP - GetProcess (); - - // --------------------------------------------------------------------- - // Thread-specific watchpoints - // --------------------------------------------------------------------- - virtual Error - SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0; - - virtual Error - RemoveWatchpoint (lldb::addr_t addr) = 0; - - protected: - NativeProcessProtocolWP m_process_wp; - lldb::tid_t m_tid; - }; -} - -#endif // #ifndef liblldb_NativeThreadProtocol_h_ diff --git a/source/Host/common/NativeWatchpointList.cpp b/source/Host/common/NativeWatchpointList.cpp new file mode 100644 index 000000000000..209d213b8e50 --- /dev/null +++ b/source/Host/common/NativeWatchpointList.cpp @@ -0,0 +1,35 @@ +//===-- NativeWatchpointList.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/NativeWatchpointList.h" + +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +Error +NativeWatchpointList::Add (addr_t addr, size_t size, uint32_t watch_flags, bool hardware) +{ + m_watchpoints[addr] = {addr, size, watch_flags, hardware}; + return Error (); +} + +Error +NativeWatchpointList::Remove (addr_t addr) +{ + m_watchpoints.erase(addr); + return Error (); +} + +const NativeWatchpointList::WatchpointMap& +NativeWatchpointList::GetWatchpointMap () const +{ + return m_watchpoints; +} diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index a6118eef7b79..b5559fffb45d 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -15,8 +15,8 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/SocketAddress.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" -#include "lldb/Interpreter/Args.h" #ifdef __ANDROID_NDK__ #include <linux/tcp.h> @@ -190,7 +190,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("ConnectionFileDescriptor::SocketListen (%s)", host_and_port.data()); + log->Printf ("Socket::TcpListen (%s)", host_and_port.data()); std::string host_str; std::string port_str; @@ -222,7 +222,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe // as port zero is a special code for "find an open port // for me". if (port == 0) - port = listen_socket->GetPortNumber(); + port = listen_socket->GetLocalPortNumber(); // Set the port predicate since when doing a listen://<host>:<port> // it often needs to accept the incoming connection which is a blocking @@ -230,7 +230,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe // us to wait for the port predicate to be set to a non-zero value from // another thread in an efficient manor. if (predicate) - predicate->SetValue(port, eBroadcastAlways); + predicate->SetValue (port, eBroadcastAlways); socket = listen_socket.release(); } @@ -533,13 +533,18 @@ Socket::DecodeHostAndPort(llvm::StringRef host_and_port, if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str)) { - port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { if (error_ptr) error_ptr->Clear(); return true; } + // port is too large + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); + return false; } } @@ -547,10 +552,13 @@ Socket::DecodeHostAndPort(llvm::StringRef host_and_port, // a port with an empty host. host_str.clear(); port_str.clear(); - port = Args::StringToSInt32(host_and_port.data(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { port_str = host_and_port; + if (error_ptr) + error_ptr->Clear(); return true; } @@ -688,7 +696,7 @@ int Socket::SetOption(int level, int option_name, int option_value) return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetPortNumber(const NativeSocket& socket) +uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) { // We bound to port zero, so we need to figure out which port we actually bound to if (socket >= 0) @@ -702,7 +710,47 @@ uint16_t Socket::GetPortNumber(const NativeSocket& socket) } // Return the port number that is being used by the socket. -uint16_t Socket::GetPortNumber() const +uint16_t Socket::GetLocalPortNumber() const { - return GetPortNumber(m_socket); + return GetLocalPortNumber (m_socket); } + +std::string Socket::GetLocalIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + +uint16_t Socket::GetRemotePortNumber () const +{ + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort (); + } + return 0; +} + +std::string Socket::GetRemoteIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + + diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 6231631934df..fd7fbac952e3 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -21,6 +21,58 @@ // Other libraries and framework includes // Project includes +// WindowsXP needs an inet_ntop implementation +#ifdef _WIN32 + +#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs +#define INET6_ADDRSTRLEN 46 +#endif + +// TODO: implement shortened form "::" for runs of zeros +const char* inet_ntop(int af, const void * src, + char * dst, socklen_t size) +{ + if (size==0) + { + return nullptr; + } + + switch (af) + { + case AF_INET: + { + { + const char* formatted = inet_ntoa(*static_cast<const in_addr*>(src)); + if (formatted && strlen(formatted) < size) + { + strncpy(dst, formatted, size); + return dst; + } + } + return nullptr; + case AF_INET6: + { + char tmp[INET6_ADDRSTRLEN] = {0}; + const uint16_t* src16 = static_cast<const uint16_t*>(src); + int full_size = _snprintf(tmp, sizeof(tmp), + "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), + ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]) + ); + if (full_size < static_cast<int>(size)) + { + strncpy(dst,tmp,size); + return dst; + } + return nullptr; + } + } + } + return nullptr; +} +#endif + + using namespace lldb_private; //---------------------------------------------------------------------- @@ -124,6 +176,26 @@ SocketAddress::SetFamily (sa_family_t family) #endif } +std::string +SocketAddress::GetIPAddress () const +{ + char str[INET6_ADDRSTRLEN] = {0}; + switch (GetFamily()) + { + case AF_INET: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str))) + { + return str; + } + case AF_INET6: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str))) + { + return str; + } + } + return ""; +} + uint16_t SocketAddress::GetPort () const { diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp index d9d1fa67156f..67f472b88f5c 100644 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ b/source/Host/common/SoftwareBreakpoint.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/Debug.h" #include "lldb/Host/Mutex.h" -#include "NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" using namespace lldb_private; diff --git a/source/Host/common/SoftwareBreakpoint.h b/source/Host/common/SoftwareBreakpoint.h deleted file mode 100644 index 1fed19eca612..000000000000 --- a/source/Host/common/SoftwareBreakpoint.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- SoftwareBreakpoint.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_SoftwareBreakpoint_h_ -#define liblldb_SoftwareBreakpoint_h_ - -#include "lldb/lldb-private-forward.h" -#include "NativeBreakpoint.h" - -namespace lldb_private -{ - class SoftwareBreakpoint : public NativeBreakpoint - { - public: - static Error - CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_spn); - - SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size); - - protected: - Error - DoEnable () override; - - Error - DoDisable () override; - - bool - IsSoftwareBreakpoint () const override; - - private: - /// Max number of bytes that a software trap opcode sequence can occupy. - static const size_t MAX_TRAP_OPCODE_SIZE = 8; - - NativeProcessProtocol &m_process; - uint8_t m_saved_opcodes [MAX_TRAP_OPCODE_SIZE]; - uint8_t m_trap_opcodes [MAX_TRAP_OPCODE_SIZE]; - const size_t m_opcode_size; - - static Error - EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes); - - }; -} - -#endif // #ifndef liblldb_SoftwareBreakpoint_h_ diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp new file mode 100644 index 000000000000..0a8e75f4b877 --- /dev/null +++ b/source/Host/common/StringConvert.cpp @@ -0,0 +1,93 @@ +//===-- StringConvert.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include <stdlib.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/StringConvert.h" + +namespace lldb_private { + +namespace StringConvert { + +int32_t +ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + const long sval = ::strtol (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); + return (int32_t)sval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +uint32_t +ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + const unsigned long uval = ::strtoul (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = (uval <= UINT32_MAX); + return (uint32_t)uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +int64_t +ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + int64_t uval = ::strtoll (s, &end, base); + if (*end == '\0') + { + if (success_ptr) *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +uint64_t +ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + uint64_t uval = ::strtoull (s, &end, base); + if (*end == '\0') + { + if (success_ptr) *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +} +} diff --git a/source/Host/common/ThreadLauncher.cpp b/source/Host/common/ThreadLauncher.cpp index ec7da325bf92..c19a23361d81 100644 --- a/source/Host/common/ThreadLauncher.cpp +++ b/source/Host/common/ThreadLauncher.cpp @@ -38,6 +38,16 @@ ThreadLauncher::LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_fu error.SetError(::GetLastError(), eErrorTypeWin32); #else + + // ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. +#if __has_feature(address_sanitizer) + const size_t eight_megabytes = 8 * 1024 * 1024; + if (min_stack_byte_size < eight_megabytes) + { + min_stack_byte_size += eight_megabytes; + } +#endif + pthread_attr_t *thread_attr_ptr = NULL; pthread_attr_t thread_attr; bool destroy_attr = false; diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 38ddc0a49220..fe70c33bf5ae 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -19,6 +19,7 @@ #include "lldb/Host/IOObject.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" // C Includes #include <errno.h> @@ -41,6 +42,7 @@ #include "lldb/lldb-private-log.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" @@ -142,7 +144,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) if (strstr(s, "listen://") == s) { // listen://HOST:PORT - return SocketListen(s + strlen("listen://"), error_ptr); + return SocketListenAndAccept(s + strlen("listen://"), error_ptr); } else if (strstr(s, "accept://") == s) { @@ -173,7 +175,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) // that is already opened (possibly from a service or other source). s += strlen("fd://"); bool success = false; - int fd = Args::StringToSInt32(s, -1, 0, &success); + int fd = StringConvert::ToSInt32(s, -1, 0, &success); if (success) { @@ -219,6 +221,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); } + m_uri.assign(s); return eConnectionStatusSuccess; } } @@ -351,6 +354,7 @@ ConnectionFileDescriptor::Disconnect(Error *error_ptr) if (error_ptr) *error_ptr = error.Fail() ? error : error2; + m_uri.clear(); m_shutting_down = false; return status; } @@ -510,6 +514,12 @@ ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatu return bytes_sent; } +std::string +ConnectionFileDescriptor::GetURI() +{ + return m_uri; +} + // This ConnectionFileDescriptor::BytesAvailable() uses select(). // // PROS: @@ -700,7 +710,12 @@ ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *erro *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus @@ -712,11 +727,16 @@ ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *err *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) +ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) { m_port_predicate.SetValue(0, eBroadcastNever); @@ -741,7 +761,14 @@ ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + StreamString strm; + strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); + m_uri.swap(strm.GetString()); + return eConnectionStatusSuccess; } ConnectionStatus @@ -753,7 +780,12 @@ ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } ConnectionStatus @@ -766,7 +798,12 @@ ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) *error_ptr = error; m_write_sp.reset(send_socket); m_read_sp.reset(recv_socket); - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } uint16_t diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index 02838ec5124e..1650f1e7979b 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -9,12 +9,16 @@ #include "lldb/Host/posix/PipePosix.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" #include <functional> #include <thread> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> @@ -183,6 +187,37 @@ PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) } Error +PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name) +{ + llvm::SmallString<PATH_MAX> named_pipe_path; + llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); + FileSpec tmpdir_file_spec; + tmpdir_file_spec.Clear(); + if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + else + { + tmpdir_file_spec.AppendPathComponent("/tmp"); + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + + // It's possible that another process creates the target path after we've + // verified it's available but before we create it, in which case we + // should try again. + Error error; + do { + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), named_pipe_path); + error = CreateNew(named_pipe_path, child_process_inherit); + } while (error.GetError() == EEXIST); + + if (error.Success()) + name = named_pipe_path; + return error; +} + +Error PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) { if (CanRead() || CanWrite()) |