diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
commit | 5f29bb8a675e8f96452b632e7129113f7dec850e (patch) | |
tree | 3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /source/Host | |
parent | 88c643b6fec27eec436c8d138fee6346e92337d6 (diff) | |
download | src-5f29bb8a675e8f96452b632e7129113f7dec850e.tar.gz src-5f29bb8a675e8f96452b632e7129113f7dec850e.zip |
Vendor import of stripped lldb trunk r366426 (just before the release_90
branch point):
https://llvm.org/svn/llvm-project/lldb/trunk@366426
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=351290
Diffstat (limited to 'source/Host')
48 files changed, 1016 insertions, 912 deletions
diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index f7ba4b5822ff..d3a70aeaa326 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -1,9 +1,8 @@ //===-- Editline.cpp --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -164,7 +163,7 @@ private: // Use static GetHistory() function to get a EditlineHistorySP to one of // these objects EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) - : m_history(NULL), m_event(), m_prefix(prefix), m_path() { + : m_history(nullptr), m_event(), m_prefix(prefix), m_path() { m_history = history_winit(); history_w(m_history, &m_event, H_SETSIZE, size); if (unique_entries) @@ -172,23 +171,28 @@ private: } const char *GetHistoryFilePath() { + // Compute the history path lazily. if (m_path.empty() && m_history && !m_prefix.empty()) { - FileSpec parent_path("~/.lldb"); - FileSystem::Instance().Resolve(parent_path); - char history_path[PATH_MAX]; - if (!llvm::sys::fs::create_directory(parent_path.GetPath())) { - snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history", - m_prefix.c_str()); - } else { - snprintf(history_path, sizeof(history_path), "~/%s-widehistory", - m_prefix.c_str()); + llvm::SmallString<128> lldb_history_file; + llvm::sys::path::home_directory(lldb_history_file); + llvm::sys::path::append(lldb_history_file, ".lldb"); + + // LLDB stores its history in ~/.lldb/. If for some reason this directory + // isn't writable or cannot be created, history won't be available. + if (!llvm::sys::fs::create_directory(lldb_history_file)) { +#if LLDB_EDITLINE_USE_WCHAR + std::string filename = m_prefix + "-widehistory"; +#else + std::string filename = m_prefix + "-history"; +#endif + llvm::sys::path::append(lldb_history_file, filename); + m_path = lldb_history_file.str(); } - auto file_spec = FileSpec(history_path); - FileSystem::Instance().Resolve(file_spec); - m_path = file_spec.GetPath(); } + if (m_path.empty()) - return NULL; + return nullptr; + return m_path.c_str(); } @@ -198,7 +202,7 @@ public: if (m_history) { history_wend(m_history); - m_history = NULL; + m_history = nullptr; } } @@ -220,7 +224,7 @@ public: return history_sp; } - bool IsValid() const { return m_history != NULL; } + bool IsValid() const { return m_history != nullptr; } HistoryW *GetHistoryPtr() { return m_history; } @@ -261,9 +265,7 @@ protected: } } -//------------------------------------------------------------------ // Editline private methods -//------------------------------------------------------------------ void Editline::SetBaseLineNumber(int line_number) { std::stringstream line_number_stream; @@ -512,11 +514,13 @@ int Editline::GetCharacter(EditLineGetCharType *c) { // Read returns, immediately lock the mutex again and check if we were // interrupted. m_output_mutex.unlock(); - int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); + int read_count = + m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); m_output_mutex.lock(); if (m_editor_status == EditorStatus::Interrupted) { while (read_count > 0 && status == lldb::eConnectionStatusSuccess) - read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); + read_count = + m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); lldbassert(status == lldb::eConnectionStatusInterrupted); return 0; } @@ -857,10 +861,8 @@ unsigned char Editline::BufferEndCommand(int ch) { return CC_NEWLINE; } -//------------------------------------------------------------------------------ /// Prints completions and their descriptions to the given file. Only the /// completions in the interval [start, end) are printed. -//------------------------------------------------------------------------------ static void PrintCompletion(FILE *output_file, size_t start, size_t end, StringList &completions, StringList &descriptions) { // This is an 'int' because of printf. @@ -875,10 +877,11 @@ static void PrintCompletion(FILE *output_file, size_t start, size_t end, const char *completion_str = completions.GetStringAtIndex(i); const char *description_str = descriptions.GetStringAtIndex(i); - fprintf(output_file, "\n\t%-*s", max_len, completion_str); + if (completion_str) + fprintf(output_file, "\n\t%-*s", max_len, completion_str); // Print the description if we got one. - if (strlen(description_str)) + if (description_str && strlen(description_str)) fprintf(output_file, " -- %s", description_str); } } @@ -977,7 +980,9 @@ void Editline::ConfigureEditor(bool multiline) { TerminalSizeChanged(); if (m_history_sp && m_history_sp->IsValid()) { - m_history_sp->Load(); + if (!m_history_sp->Load()) { + fputs("Could not load history file\n.", m_output_file); + } el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); } el_set(m_editline, EL_CLIENTDATA, this); @@ -1078,7 +1083,7 @@ void Editline::ConfigureEditor(bool multiline) { // Allow user-specific customization prior to registering bindings we // absolutely require - el_source(m_editline, NULL); + el_source(m_editline, nullptr); // Register an internal binding that external developers shouldn't use el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), @@ -1145,9 +1150,7 @@ void Editline::ConfigureEditor(bool multiline) { } } -//------------------------------------------------------------------ // Editline public methods -//------------------------------------------------------------------ Editline *Editline::InstanceFor(EditLine *editline) { Editline *editor; @@ -1222,9 +1225,13 @@ void Editline::TerminalSizeChanged() { if (m_editline != nullptr) { el_resize(m_editline); int columns; - // Despite the man page claiming non-zero indicates success, it's actually - // zero - if (el_get(m_editline, EL_GETTC, "co", &columns) == 0) { + // This function is documenting as taking (const char *, void *) for the + // vararg part, but in reality in was consuming arguments until the first + // null pointer. This was fixed in libedit in April 2019 + // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>, + // but we're keeping the workaround until a version with that fix is more + // widely available. + if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) { m_terminal_width = columns; if (m_current_line_rows != -1) { const LineInfoW *info = el_wline(m_editline); diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 810c15588402..c8c8d7a0d496 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -1,9 +1,8 @@ //===-- File.cpp ------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -66,11 +65,11 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) { } else if (options & File::eOpenOptionWrite) { return "w"; } - return NULL; + return nullptr; } int File::kInvalidDescriptor = -1; -FILE *File::kInvalidStream = NULL; +FILE *File::kInvalidStream = nullptr; File::~File() { Close(); } @@ -179,7 +178,7 @@ Status File::Close() { void File::Clear() { m_stream = nullptr; - m_descriptor = -1; + m_descriptor = kInvalidDescriptor; m_options = 0; m_own_stream = false; m_is_interactive = m_supports_colors = m_is_real_terminal = @@ -504,6 +503,7 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { error.SetErrorString("invalid file handle"); } #else + std::lock_guard<std::mutex> guard(offset_access_mutex); long cur = ::lseek(m_descriptor, 0, SEEK_CUR); SeekFromStart(offset); error = Read(buf, num_bytes); @@ -528,18 +528,18 @@ Status File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, 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()); - data_heap_ap->SetByteSize(num_bytes_plus_nul_char); + std::unique_ptr<DataBufferHeap> data_heap_up; + data_heap_up.reset(new DataBufferHeap()); + data_heap_up->SetByteSize(num_bytes_plus_nul_char); - if (data_heap_ap.get()) { - error = Read(data_heap_ap->GetBytes(), num_bytes, offset); + if (data_heap_up) { + error = Read(data_heap_up->GetBytes(), num_bytes, offset); if (error.Success()) { // Make sure we read exactly what we asked for and if we got // less, adjust the array - 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()); + if (num_bytes_plus_nul_char < data_heap_up->GetByteSize()) + data_heap_up->SetByteSize(num_bytes_plus_nul_char); + data_buffer_sp.reset(data_heap_up.release()); return error; } } @@ -603,7 +603,9 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { num_bytes = bytes_written; } #else + std::lock_guard<std::mutex> guard(offset_access_mutex); long cur = ::lseek(m_descriptor, 0, SEEK_CUR); + SeekFromStart(offset); error = Write(buf, num_bytes); long after = ::lseek(m_descriptor, 0, SEEK_CUR); @@ -619,9 +621,7 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { return error; } -//------------------------------------------------------------------ // Print some formatted output to the stream. -//------------------------------------------------------------------ size_t File::Printf(const char *format, ...) { va_list args; va_start(args, format); @@ -630,15 +630,13 @@ size_t File::Printf(const char *format, ...) { return result; } -//------------------------------------------------------------------ // Print some formatted output to the stream. -//------------------------------------------------------------------ size_t File::PrintfVarArg(const char *format, va_list args) { size_t result = 0; if (DescriptorIsValid()) { - char *s = NULL; + char *s = nullptr; result = vasprintf(&s, format, args); - if (s != NULL) { + if (s != nullptr) { if (result > 0) { size_t s_len = result; Write(s, s_len); diff --git a/source/Host/common/FileAction.cpp b/source/Host/common/FileAction.cpp new file mode 100644 index 000000000000..3268d952bcc9 --- /dev/null +++ b/source/Host/common/FileAction.cpp @@ -0,0 +1,88 @@ +//===-- FileAction.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 <fcntl.h> + +#include "lldb/Host/FileAction.h" +#include "lldb/Host/PosixApi.h" +#include "lldb/Utility/Stream.h" + +using namespace lldb_private; + +// FileAction member functions + +FileAction::FileAction() + : m_action(eFileActionNone), m_fd(-1), m_arg(-1), m_file_spec() {} + +void FileAction::Clear() { + m_action = eFileActionNone; + m_fd = -1; + m_arg = -1; + m_file_spec.Clear(); +} + +llvm::StringRef FileAction::GetPath() const { return m_file_spec.GetCString(); } + +const FileSpec &FileAction::GetFileSpec() const { return m_file_spec; } + +bool FileAction::Open(int fd, const FileSpec &file_spec, bool read, + bool write) { + if ((read || write) && fd >= 0 && file_spec) { + m_action = eFileActionOpen; + m_fd = fd; + if (read && write) + m_arg = O_NOCTTY | O_CREAT | O_RDWR; + else if (read) + m_arg = O_NOCTTY | O_RDONLY; + else + m_arg = O_NOCTTY | O_CREAT | O_WRONLY; + m_file_spec = file_spec; + return true; + } else { + Clear(); + } + return false; +} + +bool FileAction::Close(int fd) { + Clear(); + if (fd >= 0) { + m_action = eFileActionClose; + m_fd = fd; + } + return m_fd >= 0; +} + +bool FileAction::Duplicate(int fd, int dup_fd) { + Clear(); + if (fd >= 0 && dup_fd >= 0) { + m_action = eFileActionDuplicate; + m_fd = fd; + m_arg = dup_fd; + } + return m_fd >= 0; +} + +void FileAction::Dump(Stream &stream) const { + stream.PutCString("file action: "); + switch (m_action) { + case eFileActionClose: + stream.Printf("close fd %d", m_fd); + break; + case eFileActionDuplicate: + stream.Printf("duplicate fd %d to %d", m_fd, m_arg); + break; + case eFileActionNone: + stream.PutCString("no action"); + break; + case eFileActionOpen: + stream.Printf("open fd %d with '%s', OFLAGS = 0x%x", m_fd, + m_file_spec.GetCString(), m_arg); + break; + } +} diff --git a/source/Host/common/FileCache.cpp b/source/Host/common/FileCache.cpp index 17833ef2cbb3..4bd3efda7fb0 100644 --- a/source/Host/common/FileCache.cpp +++ b/source/Host/common/FileCache.cpp @@ -1,9 +1,8 @@ //===-- FileCache.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/FileSystem.cpp b/source/Host/common/FileSystem.cpp index 7191c9db9b2e..d5ac05bd447c 100644 --- a/source/Host/common/FileSystem.cpp +++ b/source/Host/common/FileSystem.cpp @@ -1,9 +1,8 @@ //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,7 +11,9 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/TildeExpressionResolver.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Errno.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" @@ -48,6 +49,27 @@ void FileSystem::Initialize() { InstanceImpl().emplace(); } +void FileSystem::Initialize(FileCollector &collector) { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(collector); +} + +llvm::Error FileSystem::Initialize(const FileSpec &mapping) { + lldbassert(!InstanceImpl() && "Already initialized."); + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = + llvm::vfs::getRealFileSystem()->getBufferForFile(mapping.GetPath()); + + if (!buffer) + return llvm::errorCodeToError(buffer.getError()); + + InstanceImpl().emplace(llvm::vfs::getVFSFromYAML(std::move(buffer.get()), + nullptr, mapping.GetPath()), + true); + + return llvm::Error::success(); +} + void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) { lldbassert(!InstanceImpl() && "Already initialized."); InstanceImpl().emplace(fs); @@ -220,17 +242,21 @@ void FileSystem::Resolve(SmallVectorImpl<char> &path) { if (path.empty()) return; - // Resolve tilde. - SmallString<128> original_path(path.begin(), path.end()); + // Resolve tilde in path. + SmallString<128> resolved(path.begin(), path.end()); StandardTildeExpressionResolver Resolver; - Resolver.ResolveFullPath(original_path, path); + Resolver.ResolveFullPath(llvm::StringRef(path.begin(), path.size()), + resolved); // Try making the path absolute if it exists. - SmallString<128> absolute_path(path.begin(), path.end()); - MakeAbsolute(path); - if (!Exists(path)) { - path.clear(); - path.append(original_path.begin(), original_path.end()); + SmallString<128> absolute(resolved.begin(), resolved.end()); + MakeAbsolute(absolute); + + path.clear(); + if (Exists(absolute)) { + path.append(absolute.begin(), absolute.end()); + } else { + path.append(resolved.begin(), resolved.end()); } } @@ -243,25 +269,35 @@ void FileSystem::Resolve(FileSpec &file_spec) { Resolve(path); // Update the FileSpec with the resolved path. - file_spec.SetPath(path); + if (file_spec.GetFilename().IsEmpty()) + file_spec.GetDirectory().SetString(path); + else + file_spec.SetPath(path); file_spec.SetIsResolved(true); } std::shared_ptr<DataBufferLLVM> FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size, uint64_t offset) { + if (m_collector) + m_collector->AddFile(path); + const bool is_volatile = !IsLocal(path); + const ErrorOr<std::string> external_path = GetExternalPath(path); + + if (!external_path) + return nullptr; std::unique_ptr<llvm::WritableMemoryBuffer> buffer; if (size == 0) { auto buffer_or_error = - llvm::WritableMemoryBuffer::getFile(path, -1, is_volatile); + llvm::WritableMemoryBuffer::getFile(*external_path, -1, is_volatile); if (!buffer_or_error) return nullptr; buffer = std::move(*buffer_or_error); } else { auto buffer_or_error = llvm::WritableMemoryBuffer::getFileSlice( - path, size, offset, is_volatile); + *external_path, size, offset, is_volatile); if (!buffer_or_error) return nullptr; buffer = std::move(*buffer_or_error); @@ -277,12 +313,12 @@ FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size, bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) { // If the directory is set there's nothing to do. - const ConstString &directory = file_spec.GetDirectory(); + ConstString directory = file_spec.GetDirectory(); if (directory) return false; // We cannot look for a file if there's no file name. - const ConstString &filename = file_spec.GetFilename(); + ConstString filename = file_spec.GetFilename(); if (!filename) return false; @@ -380,25 +416,56 @@ static mode_t GetOpenMode(uint32_t permissions) { } Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options, - uint32_t permissions) { + uint32_t permissions, bool should_close_fd) { + if (m_collector) + m_collector->AddFile(file_spec); + if (File.IsValid()) File.Close(); const int open_flags = GetOpenFlags(options); const mode_t open_mode = (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0; - const std::string path = file_spec.GetPath(); + + auto path = GetExternalPath(file_spec); + if (!path) + return Status(path.getError()); int descriptor = llvm::sys::RetryAfterSignal( - -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode); + -1, OpenWithFS, *this, path->c_str(), open_flags, open_mode); Status error; if (!File::DescriptorIsValid(descriptor)) { File.SetDescriptor(descriptor, false); error.SetErrorToErrno(); } else { - File.SetDescriptor(descriptor, true); + File.SetDescriptor(descriptor, should_close_fd); File.SetOptions(options); } return error; } + +ErrorOr<std::string> FileSystem::GetExternalPath(const llvm::Twine &path) { + if (!m_mapped) + return path.str(); + + // If VFS mapped we know the underlying FS is a RedirectingFileSystem. + ErrorOr<vfs::RedirectingFileSystem::Entry *> E = + static_cast<vfs::RedirectingFileSystem &>(*m_fs).lookupPath(path); + if (!E) { + if (E.getError() == llvm::errc::no_such_file_or_directory) { + return path.str(); + } + return E.getError(); + } + + auto *F = dyn_cast<vfs::RedirectingFileSystem::RedirectingFileEntry>(*E); + if (!F) + return make_error_code(llvm::errc::not_supported); + + return F->getExternalContentsPath().str(); +} + +ErrorOr<std::string> FileSystem::GetExternalPath(const FileSpec &file_spec) { + return GetExternalPath(file_spec.GetPath()); +} diff --git a/source/Host/common/GetOptInc.cpp b/source/Host/common/GetOptInc.cpp index 1d9b31743736..95a68c5d3c76 100644 --- a/source/Host/common/GetOptInc.cpp +++ b/source/Host/common/GetOptInc.cpp @@ -1,9 +1,8 @@ //===-- GetOptInc.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -98,9 +97,9 @@ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, pos += nopts; swap = nargv[pos]; /* LINTED const cast */ - ((char **)nargv)[pos] = nargv[cstart]; + const_cast<char **>(nargv)[pos] = nargv[cstart]; /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; + const_cast<char **>(nargv)[cstart] = swap; } } } diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 62b936aadef1..3ba9ab7f21f3 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -1,9 +1,8 @@ //===-- Host.cpp ------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -47,17 +46,16 @@ #include <csignal> +#include "lldb/Host/FileAction.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" -#include "lldb/Target/FileAction.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Target/UnixSignals.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -101,7 +99,7 @@ struct MonitorInfo { static thread_result_t MonitorChildProcessThreadFunction(void *arg); -HostThread Host::StartMonitoringChildProcess( +llvm::Expected<HostThread> Host::StartMonitoringChildProcess( const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, bool monitor_signals) { MonitorInfo *info_ptr = new MonitorInfo(); @@ -114,14 +112,12 @@ HostThread Host::StartMonitoringChildProcess( ::snprintf(thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); return ThreadLauncher::LaunchThread( - thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); + thread_name, MonitorChildProcessThreadFunction, info_ptr, 0); } #ifndef __linux__ -//------------------------------------------------------------------ // Scoped class that will disable thread canceling when it is constructed, and // exception safely restore the previous value it when it goes out of scope. -//------------------------------------------------------------------ class ScopedPThreadCancelDisabler { public: ScopedPThreadCancelDisabler() { @@ -223,7 +219,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { bool exited = false; int signal = 0; int exit_status = 0; - const char *status_cstr = NULL; + const char *status_cstr = nullptr; if (WIFSTOPPED(status)) { signal = WSTOPSIG(status); status_cstr = "STOPPED"; @@ -286,7 +282,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { if (log) log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg); - return NULL; + return nullptr; } #endif // #if !defined (__APPLE__) && !defined (_WIN32) @@ -397,7 +393,7 @@ const char *Host::GetSignalAsCString(int signo) { default: break; } - return NULL; + return nullptr; } #endif @@ -466,16 +462,19 @@ Status Host::RunShellCommand(const char *command, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, const Timeout<std::micro> &timeout, - bool run_in_default_shell) { + bool run_in_default_shell, + bool hide_stderr) { return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, - command_output_ptr, timeout, run_in_default_shell); + command_output_ptr, timeout, run_in_default_shell, + hide_stderr); } Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, const Timeout<std::micro> &timeout, - bool run_in_default_shell) { + bool run_in_default_shell, + bool hide_stderr) { Status error; ProcessLaunchInfo launch_info; launch_info.SetArchitecture(HostInfo::GetArchitecture()); @@ -513,16 +512,18 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, } FileSpec output_file_spec(output_file_path.c_str()); - + // Set up file descriptors. launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); - if (output_file_spec) { + if (output_file_spec) launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true); - launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); - } else { + else launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); + + if (output_file_spec && !hide_stderr) + launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); + else launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); - } std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); const bool monitor_signals = false; @@ -614,12 +615,6 @@ bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, #endif -const UnixSignalsSP &Host::GetUnixSignals() { - static const auto s_unix_signals_sp = - UnixSignals::Create(HostInfo::GetArchitecture()); - return s_unix_signals_sp; -} - std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) { #if defined(_WIN32) if (url.startswith("file://")) diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index 34c362efc9e0..130f0eb8ac8d 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -1,9 +1,8 @@ //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -32,13 +31,11 @@ using namespace lldb; using namespace lldb_private; namespace { -//---------------------------------------------------------------------- // 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. -//---------------------------------------------------------------------- struct HostInfoBaseFields { ~HostInfoBaseFields() { @@ -215,6 +212,38 @@ ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { return ArchSpec(normalized_triple); } +bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, + llvm::StringRef dir) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + + FileSpec lldb_file_spec = GetShlibDir(); + if (!lldb_file_spec) + return false; + + std::string raw_path = lldb_file_spec.GetPath(); + if (log) + log->Printf("HostInfo::%s() attempting to " + "derive the path %s relative to liblldb install path: %s", + __FUNCTION__, dir.data(), raw_path.c_str()); + + // Drop bin (windows) or lib + llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); + if (parent_path.empty()) { + if (log) + log->Printf("HostInfo::%s() failed to find liblldb within the shared " + "lib path", + __FUNCTION__); + return false; + } + + raw_path = (parent_path + dir).str(); + if (log) + log->Printf("HostInfo::%s() derived the path as: %s", __FUNCTION__, + raw_path.c_str()); + file_spec.GetDirectory().SetString(raw_path); + return (bool)file_spec.GetDirectory(); +} + bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { // To get paths related to LLDB we get the path to the executable that // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp index 25c8066bb1a3..a5f876a7232a 100644 --- a/source/Host/common/HostNativeThreadBase.cpp +++ b/source/Host/common/HostNativeThreadBase.cpp @@ -1,9 +1,8 @@ //===-- HostNativeThreadBase.cpp --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/HostProcess.cpp b/source/Host/common/HostProcess.cpp index 154033321514..e180687551f8 100644 --- a/source/Host/common/HostProcess.cpp +++ b/source/Host/common/HostProcess.cpp @@ -1,9 +1,8 @@ //===-- HostProcess.cpp -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,7 +32,7 @@ lldb::pid_t HostProcess::GetProcessId() const { bool HostProcess::IsRunning() const { return m_native_process->IsRunning(); } -HostThread +llvm::Expected<HostThread> HostProcess::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { return m_native_process->StartMonitoring(callback, monitor_signals); diff --git a/source/Host/common/HostThread.cpp b/source/Host/common/HostThread.cpp index 2bf6f0a933d8..89cadce5b206 100644 --- a/source/Host/common/HostThread.cpp +++ b/source/Host/common/HostThread.cpp @@ -1,9 +1,8 @@ //===-- HostThread.cpp ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/LockFileBase.cpp b/source/Host/common/LockFileBase.cpp index a8d7881ab896..744b1eaabb4e 100644 --- a/source/Host/common/LockFileBase.cpp +++ b/source/Host/common/LockFileBase.cpp @@ -1,9 +1,8 @@ //===-- LockFileBase.cpp ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 39c353e6717e..1ce09a84671c 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -1,9 +1,8 @@ //===-- MainLoop.cpp --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -62,10 +61,12 @@ using namespace lldb_private; static sig_atomic_t g_signal_flags[NSIG]; +#ifndef SIGNAL_POLLING_UNSUPPORTED static void SignalHandler(int signo, siginfo_t *info, void *) { assert(signo < NSIG); g_signal_flags[signo] = 1; } +#endif class MainLoop::RunImpl { public: @@ -108,8 +109,14 @@ Status MainLoop::RunImpl::Poll() { num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, llvm::array_lengthof(out_events), nullptr); - if (num_events < 0) - return Status("kevent() failed with error %d\n", num_events); + if (num_events < 0) { + if (errno == EINTR) { + // in case of EINTR, let the main loop run one iteration + // we need to zero num_events to avoid assertions failing + num_events = 0; + } else + return Status(errno, eErrorTypePOSIX); + } return Status(); } @@ -138,18 +145,20 @@ MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { } sigset_t MainLoop::RunImpl::get_sigmask() { -#if SIGNAL_POLLING_UNSUPPORTED - return 0; -#else sigset_t sigmask; +#if defined(_WIN32) + sigmask = 0; +#elif SIGNAL_POLLING_UNSUPPORTED + sigemptyset(&sigmask); +#else int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask); assert(ret == 0); (void) ret; for (const auto &sig : loop.m_signals) sigdelset(&sigmask, sig.first); - return sigmask; #endif + return sigmask; } #ifdef __ANDROID__ @@ -381,9 +390,6 @@ Status MainLoop::Run() { return error; impl.ProcessEvents(); - - if (m_terminate_request) - return Status(); } return Status(); } diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp index f6f772cb3679..55e9f69a089a 100644 --- a/source/Host/common/MonitoringProcessLauncher.cpp +++ b/source/Host/common/MonitoringProcessLauncher.cpp @@ -1,16 +1,15 @@ //===-- MonitoringProcessLauncher.cpp ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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/Host/MonitoringProcessLauncher.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Utility/Log.h" #include "llvm/Support/FileSystem.h" @@ -54,8 +53,12 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); assert(launch_info.GetMonitorProcessCallback()); - process.StartMonitoring(launch_info.GetMonitorProcessCallback(), - launch_info.GetMonitorSignals()); + llvm::Expected<HostThread> maybe_thread = + process.StartMonitoring(launch_info.GetMonitorProcessCallback(), + launch_info.GetMonitorSignals()); + if (!maybe_thread) + error.SetErrorStringWithFormatv("failed to launch host thread: {}", + llvm::toString(maybe_thread.takeError())); if (log) log->PutCString("started monitoring child process."); } else { diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index e3c81f6c147b..90272cb8d0bc 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -1,9 +1,8 @@ //===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,9 +19,7 @@ using namespace lldb; using namespace lldb_private; -// ----------------------------------------------------------------------------- // NativeProcessProtocol Members -// ----------------------------------------------------------------------------- NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, NativeDelegate &delegate) diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 6e6632aa710f..2f30d52aea63 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -1,9 +1,8 @@ //===-- NativeRegisterContext.cpp -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -22,9 +21,7 @@ using namespace lldb_private; NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) : m_thread(thread) {} -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- NativeRegisterContext::~NativeRegisterContext() {} // FIXME revisit invalidation, process stop ids, etc. Right now we don't diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index af43683295b0..e62b1425c891 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -1,9 +1,8 @@ //===-- NativeThreadProtocol.cpp --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/NativeWatchpointList.cpp b/source/Host/common/NativeWatchpointList.cpp index e6ef7300eb22..c3db95fb252e 100644 --- a/source/Host/common/NativeWatchpointList.cpp +++ b/source/Host/common/NativeWatchpointList.cpp @@ -1,9 +1,8 @@ //===-- NativeWatchpointList.cpp --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp index d78bf335b408..1e76f9b8f9f1 100644 --- a/source/Host/common/OptionParser.cpp +++ b/source/Host/common/OptionParser.cpp @@ -1,9 +1,8 @@ //===-- source/Host/common/OptionParser.cpp ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -28,8 +27,9 @@ void OptionParser::Prepare(std::unique_lock<std::mutex> &lock) { void OptionParser::EnableError(bool error) { opterr = error ? 1 : 0; } -int OptionParser::Parse(int argc, char *const argv[], llvm::StringRef optstring, - const Option *longopts, int *longindex) { +int OptionParser::Parse(llvm::MutableArrayRef<char *> argv, + llvm::StringRef optstring, const Option *longopts, + int *longindex) { std::vector<option> opts; while (longopts->definition != nullptr) { option opt; @@ -42,7 +42,8 @@ int OptionParser::Parse(int argc, char *const argv[], llvm::StringRef optstring, } opts.push_back(option()); std::string opt_cstr = optstring; - return getopt_long_only(argc, argv, opt_cstr.c_str(), &opts[0], longindex); + return getopt_long_only(argv.size() - 1, argv.data(), opt_cstr.c_str(), + &opts[0], longindex); } char *OptionParser::GetOptionArgument() { return optarg; } @@ -56,11 +57,11 @@ std::string OptionParser::GetShortOptionString(struct option *long_options) { int i = 0; bool done = false; while (!done) { - if (long_options[i].name == 0 && long_options[i].has_arg == 0 && - long_options[i].flag == 0 && long_options[i].val == 0) { + if (long_options[i].name == nullptr && long_options[i].has_arg == 0 && + long_options[i].flag == nullptr && long_options[i].val == 0) { done = true; } else { - if (long_options[i].flag == NULL && isalpha(long_options[i].val)) { + if (long_options[i].flag == nullptr && isalpha(long_options[i].val)) { s.append(1, (char)long_options[i].val); switch (long_options[i].has_arg) { default: diff --git a/source/Host/common/PipeBase.cpp b/source/Host/common/PipeBase.cpp index 632bfcb3a2e0..2cbadf0c85f6 100644 --- a/source/Host/common/PipeBase.cpp +++ b/source/Host/common/PipeBase.cpp @@ -1,9 +1,8 @@ //===-- source/Host/common/PipeBase.cpp -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/ProcessLaunchInfo.cpp b/source/Host/common/ProcessLaunchInfo.cpp new file mode 100644 index 000000000000..266b46763996 --- /dev/null +++ b/source/Host/common/ProcessLaunchInfo.cpp @@ -0,0 +1,350 @@ +//===-- ProcessLaunchInfo.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 <climits> + +#include "lldb/Host/Config.h" +#include "lldb/Host/FileAction.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/FileSystem.h" + +#if !defined(_WIN32) +#include <limits.h> +#endif + +using namespace lldb; +using namespace lldb_private; + +// ProcessLaunchInfo member functions + +ProcessLaunchInfo::ProcessLaunchInfo() + : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0), + m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), + m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {} + +ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, + const FileSpec &stdout_file_spec, + const FileSpec &stderr_file_spec, + const FileSpec &working_directory, + uint32_t launch_flags) + : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags), + m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), + m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() { + if (stdin_file_spec) { + FileAction file_action; + const bool read = true; + const bool write = false; + if (file_action.Open(STDIN_FILENO, stdin_file_spec, read, write)) + AppendFileAction(file_action); + } + if (stdout_file_spec) { + FileAction file_action; + const bool read = false; + const bool write = true; + if (file_action.Open(STDOUT_FILENO, stdout_file_spec, read, write)) + AppendFileAction(file_action); + } + if (stderr_file_spec) { + FileAction file_action; + const bool read = false; + const bool write = true; + if (file_action.Open(STDERR_FILENO, stderr_file_spec, read, write)) + AppendFileAction(file_action); + } + if (working_directory) + SetWorkingDirectory(working_directory); +} + +bool ProcessLaunchInfo::AppendCloseFileAction(int fd) { + FileAction file_action; + if (file_action.Close(fd)) { + AppendFileAction(file_action); + return true; + } + return false; +} + +bool ProcessLaunchInfo::AppendDuplicateFileAction(int fd, int dup_fd) { + FileAction file_action; + if (file_action.Duplicate(fd, dup_fd)) { + AppendFileAction(file_action); + return true; + } + return false; +} + +bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec, + bool read, bool write) { + FileAction file_action; + if (file_action.Open(fd, file_spec, read, write)) { + AppendFileAction(file_action); + return true; + } + return false; +} + +bool ProcessLaunchInfo::AppendSuppressFileAction(int fd, bool read, + bool write) { + FileAction file_action; + if (file_action.Open(fd, FileSpec(FileSystem::DEV_NULL), read, write)) { + AppendFileAction(file_action); + return true; + } + return false; +} + +const FileAction *ProcessLaunchInfo::GetFileActionAtIndex(size_t idx) const { + if (idx < m_file_actions.size()) + return &m_file_actions[idx]; + return nullptr; +} + +const FileAction *ProcessLaunchInfo::GetFileActionForFD(int fd) const { + for (size_t idx = 0, count = m_file_actions.size(); idx < count; ++idx) { + if (m_file_actions[idx].GetFD() == fd) + return &m_file_actions[idx]; + } + return nullptr; +} + +const FileSpec &ProcessLaunchInfo::GetWorkingDirectory() const { + return m_working_dir; +} + +void ProcessLaunchInfo::SetWorkingDirectory(const FileSpec &working_dir) { + m_working_dir = working_dir; +} + +const char *ProcessLaunchInfo::GetProcessPluginName() const { + return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str()); +} + +void ProcessLaunchInfo::SetProcessPluginName(llvm::StringRef plugin) { + m_plugin_name = plugin; +} + +const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; } + +void ProcessLaunchInfo::SetShell(const FileSpec &shell) { + m_shell = shell; + if (m_shell) { + FileSystem::Instance().ResolveExecutableLocation(m_shell); + m_flags.Set(lldb::eLaunchFlagLaunchInShell); + } else + m_flags.Clear(lldb::eLaunchFlagLaunchInShell); +} + +void ProcessLaunchInfo::SetLaunchInSeparateProcessGroup(bool separate) { + if (separate) + m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup); + else + m_flags.Clear(lldb::eLaunchFlagLaunchInSeparateProcessGroup); +} + +void ProcessLaunchInfo::SetShellExpandArguments(bool expand) { + if (expand) + m_flags.Set(lldb::eLaunchFlagShellExpandArguments); + else + m_flags.Clear(lldb::eLaunchFlagShellExpandArguments); +} + +void ProcessLaunchInfo::Clear() { + ProcessInfo::Clear(); + m_working_dir.Clear(); + m_plugin_name.clear(); + m_shell.Clear(); + m_flags.Clear(); + m_file_actions.clear(); + m_resume_count = 0; + m_listener_sp.reset(); + m_hijack_listener_sp.reset(); +} + +void ProcessLaunchInfo::SetMonitorProcessCallback( + const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { + m_monitor_callback = callback; + m_monitor_signals = monitor_signals; +} + +bool ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, int status) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + LLDB_LOG(log, "pid = {0}, exited = {1}, signal = {2}, status = {3}", pid, + exited, signal, status); + return true; +} + +bool ProcessLaunchInfo::MonitorProcess() const { + if (m_monitor_callback && ProcessIDIsValid()) { + llvm::Expected<HostThread> maybe_thread = + Host::StartMonitoringChildProcess(m_monitor_callback, GetProcessID(), + m_monitor_signals); + if (!maybe_thread) + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(maybe_thread.takeError())); + return true; + } + return false; +} + +void ProcessLaunchInfo::SetDetachOnError(bool enable) { + if (enable) + m_flags.Set(lldb::eLaunchFlagDetachOnError); + else + m_flags.Clear(lldb::eLaunchFlagDetachOnError); +} + +llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + LLDB_LOG(log, "Generating a pty to use for stdin/out/err"); + + int open_flags = O_RDWR | O_NOCTTY; +#if !defined(_WIN32) + // We really shouldn't be specifying platform specific flags that are + // intended for a system call in generic code. But this will have to + // do for now. + open_flags |= O_CLOEXEC; +#endif + if (!m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "PTY::OpenFirstAvailableMaster failed"); + } + const FileSpec slave_file_spec(m_pty->GetSlaveName(nullptr, 0)); + + // Only use the slave tty if we don't have anything specified for + // input and don't have an action for stdin + if (GetFileActionForFD(STDIN_FILENO) == nullptr) + AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false); + + // Only use the slave tty if we don't have anything specified for + // output and don't have an action for stdout + if (GetFileActionForFD(STDOUT_FILENO) == nullptr) + AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true); + + // Only use the slave tty if we don't have anything specified for + // error and don't have an action for stderr + if (GetFileActionForFD(STDERR_FILENO) == nullptr) + AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true); + return llvm::Error::success(); +} + +bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell( + Status &error, bool localhost, bool will_debug, + bool first_arg_is_full_shell_command, int32_t num_resumes) { + error.Clear(); + + if (GetFlags().Test(eLaunchFlagLaunchInShell)) { + if (m_shell) { + std::string shell_executable = m_shell.GetPath(); + + const char **argv = GetArguments().GetConstArgumentVector(); + if (argv == nullptr || argv[0] == nullptr) + return false; + Args shell_arguments; + std::string safe_arg; + shell_arguments.AppendArgument(shell_executable); + const llvm::Triple &triple = GetArchitecture().GetTriple(); + if (triple.getOS() == llvm::Triple::Win32 && + !triple.isWindowsCygwinEnvironment()) + shell_arguments.AppendArgument(llvm::StringRef("/C")); + else + shell_arguments.AppendArgument(llvm::StringRef("-c")); + + StreamString shell_command; + if (will_debug) { + // Add a modified PATH environment variable in case argv[0] is a + // relative path. + const char *argv0 = argv[0]; + FileSpec arg_spec(argv0); + if (arg_spec.IsRelative()) { + // We have a relative path to our executable which may not work if we + // just try to run "a.out" (without it being converted to "./a.out") + FileSpec working_dir = GetWorkingDirectory(); + // Be sure to put quotes around PATH's value in case any paths have + // spaces... + std::string new_path("PATH=\""); + const size_t empty_path_len = new_path.size(); + + if (working_dir) { + new_path += working_dir.GetPath(); + } else { + llvm::SmallString<64> cwd; + if (! llvm::sys::fs::current_path(cwd)) + new_path += cwd; + } + std::string curr_path; + if (HostInfo::GetEnvironmentVar("PATH", curr_path)) { + if (new_path.size() > empty_path_len) + new_path += ':'; + new_path += curr_path; + } + new_path += "\" "; + shell_command.PutCString(new_path); + } + + if (triple.getOS() != llvm::Triple::Win32 || + triple.isWindowsCygwinEnvironment()) + shell_command.PutCString("exec"); + + // Only Apple supports /usr/bin/arch being able to specify the + // architecture + if (GetArchitecture().IsValid() && // Valid architecture + GetArchitecture().GetTriple().getVendor() == + llvm::Triple::Apple && // Apple only + GetArchitecture().GetCore() != + ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h + { + shell_command.Printf(" /usr/bin/arch -arch %s", + GetArchitecture().GetArchitectureName()); + // Set the resume count to 2: + // 1 - stop in shell + // 2 - stop in /usr/bin/arch + // 3 - then we will stop in our program + SetResumeCount(num_resumes + 1); + } else { + // Set the resume count to 1: + // 1 - stop in shell + // 2 - then we will stop in our program + SetResumeCount(num_resumes); + } + } + + if (first_arg_is_full_shell_command) { + // There should only be one argument that is the shell command itself + // to be used as is + if (argv[0] && !argv[1]) + shell_command.Printf("%s", argv[0]); + else + return false; + } else { + for (size_t i = 0; argv[i] != nullptr; ++i) { + const char *arg = + Args::GetShellSafeArgument(m_shell, argv[i], safe_arg); + shell_command.Printf(" %s", arg); + } + } + shell_arguments.AppendArgument(shell_command.GetString()); + m_executable = m_shell; + m_arguments = shell_arguments; + return true; + } else { + error.SetErrorString("invalid shell path"); + } + } else { + error.SetErrorString("not launching in shell"); + } + return false; +} diff --git a/source/Host/common/ProcessRunLock.cpp b/source/Host/common/ProcessRunLock.cpp index e0ba2ecfd3e9..a931da718766 100644 --- a/source/Host/common/ProcessRunLock.cpp +++ b/source/Host/common/ProcessRunLock.cpp @@ -1,9 +1,8 @@ //===-- ProcessRunLock.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,19 +12,13 @@ namespace lldb_private { ProcessRunLock::ProcessRunLock() : m_running(false) { - int err = ::pthread_rwlock_init(&m_rwlock, NULL); + int err = ::pthread_rwlock_init(&m_rwlock, nullptr); (void)err; - //#if LLDB_CONFIGURATION_DEBUG - // assert(err == 0); - //#endif } ProcessRunLock::~ProcessRunLock() { int err = ::pthread_rwlock_destroy(&m_rwlock); (void)err; - //#if LLDB_CONFIGURATION_DEBUG - // assert(err == 0); - //#endif } bool ProcessRunLock::ReadTryLock() { diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp index 08d4fa218968..85e54f4d3d6a 100644 --- a/source/Host/common/PseudoTerminal.cpp +++ b/source/Host/common/PseudoTerminal.cpp @@ -1,9 +1,8 @@ //===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -27,36 +26,28 @@ int posix_openpt(int flags); using namespace lldb_private; -//---------------------------------------------------------------------- // Write string describing error number -//---------------------------------------------------------------------- static void ErrnoToStr(char *error_str, size_t error_len) { std::string strerror = llvm::sys::StrError(); ::snprintf(error_str, error_len, "%s", strerror.c_str()); } -//---------------------------------------------------------------------- // PseudoTerminal constructor -//---------------------------------------------------------------------- PseudoTerminal::PseudoTerminal() : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {} -//---------------------------------------------------------------------- // Destructor // // The destructor will close the master and slave file descriptors if they are // valid and ownership has not been released using the // ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() member // functions. -//---------------------------------------------------------------------- PseudoTerminal::~PseudoTerminal() { CloseMasterFileDescriptor(); CloseSlaveFileDescriptor(); } -//---------------------------------------------------------------------- // Close the master file descriptor if it is valid. -//---------------------------------------------------------------------- void PseudoTerminal::CloseMasterFileDescriptor() { if (m_master_fd >= 0) { ::close(m_master_fd); @@ -64,9 +55,7 @@ void PseudoTerminal::CloseMasterFileDescriptor() { } } -//---------------------------------------------------------------------- // Close the slave file descriptor if it is valid. -//---------------------------------------------------------------------- void PseudoTerminal::CloseSlaveFileDescriptor() { if (m_slave_fd >= 0) { ::close(m_slave_fd); @@ -74,7 +63,6 @@ void PseudoTerminal::CloseSlaveFileDescriptor() { } } -//---------------------------------------------------------------------- // Open the first available pseudo terminal with OFLAG as the permissions. The // file descriptor is stored in this object and can be accessed with the // MasterFileDescriptor() accessor. The ownership of the master file descriptor @@ -86,7 +74,6 @@ void PseudoTerminal::CloseSlaveFileDescriptor() { // // RETURNS: // True when successful, false indicating an error occurred. -//---------------------------------------------------------------------- bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len) { if (error_str) @@ -125,7 +112,6 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, #endif } -//---------------------------------------------------------------------- // Open the slave pseudo terminal for the current master pseudo terminal. A // master pseudo terminal should already be valid prior to calling this // function (see OpenFirstAvailableMaster()). The file descriptor is stored @@ -135,7 +121,6 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, // // RETURNS: // True when successful, false indicating an error occurred. -//---------------------------------------------------------------------- bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { if (error_str) error_str[0] = '\0'; @@ -148,7 +133,7 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { if (slave_name == nullptr) return false; - m_slave_fd = ::open(slave_name, oflag); + m_slave_fd = llvm::sys::RetryAfterSignal(-1, ::open, slave_name, oflag); if (m_slave_fd < 0) { if (error_str) @@ -159,7 +144,6 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { return true; } -//---------------------------------------------------------------------- // Get the name of the slave pseudo terminal. A master pseudo terminal should // already be valid prior to calling this function (see // OpenFirstAvailableMaster()). @@ -169,7 +153,6 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { // The name of the slave pseudo terminal as a NULL terminated C string // that comes from static memory, so a copy of the string should be // made as subsequent calls can change this value. -//---------------------------------------------------------------------- const char *PseudoTerminal::GetSlaveName(char *error_str, size_t error_len) const { if (error_str) @@ -189,7 +172,6 @@ const char *PseudoTerminal::GetSlaveName(char *error_str, return slave_name; } -//---------------------------------------------------------------------- // Fork a child process and have its stdio routed to a pseudo terminal. // // In the parent process when a valid pid is returned, the master file @@ -207,7 +189,6 @@ const char *PseudoTerminal::GetSlaveName(char *error_str, // RETURNS: // in the parent process: the pid of the child, or -1 if fork fails // in the child process: zero -//---------------------------------------------------------------------- lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { if (error_str) error_str[0] = '\0'; @@ -266,7 +247,6 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { return pid; } -//---------------------------------------------------------------------- // The master file descriptor accessor. This object retains ownership of the // master file descriptor when this accessor is used. Use // ReleaseMasterFileDescriptor() if you wish this object to release ownership @@ -274,23 +254,18 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { // // Returns the master file descriptor, or -1 if the master file descriptor is // not currently valid. -//---------------------------------------------------------------------- int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; } -//---------------------------------------------------------------------- // The slave file descriptor accessor. // // Returns the slave file descriptor, or -1 if the slave file descriptor is not // currently valid. -//---------------------------------------------------------------------- int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; } -//---------------------------------------------------------------------- // Release ownership of the master pseudo terminal file descriptor without // closing it. The destructor for this class will close the master file // descriptor if the ownership isn't released using this call and the master // file descriptor has been opened. -//---------------------------------------------------------------------- int PseudoTerminal::ReleaseMasterFileDescriptor() { // Release ownership of the master pseudo terminal file descriptor without // closing it. (the destructor for this class will close it otherwise!) @@ -299,12 +274,10 @@ int PseudoTerminal::ReleaseMasterFileDescriptor() { return fd; } -//---------------------------------------------------------------------- // Release ownership of the slave pseudo terminal file descriptor without // closing it. The destructor for this class will close the slave file // descriptor if the ownership isn't released using this call and the slave // file descriptor has been opened. -//---------------------------------------------------------------------- int PseudoTerminal::ReleaseSlaveFileDescriptor() { // Release ownership of the slave pseudo terminal file descriptor without // closing it (the destructor for this class will close it otherwise!) diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 875291bc115f..a89f1178e96c 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -1,9 +1,8 @@ //===-- Socket.cpp ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -19,6 +18,9 @@ #include "lldb/Utility/RegularExpression.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/WindowsError.h" #ifndef LLDB_DISABLE_POSIX #include "lldb/Host/posix/DomainSocket.h" @@ -78,6 +80,31 @@ Socket::Socket(SocketProtocol protocol, bool should_close, Socket::~Socket() { Close(); } +llvm::Error Socket::Initialize() { +#if defined(_WIN32) + auto wVersion = WINSOCK_VERSION; + WSADATA wsaData; + int err = ::WSAStartup(wVersion, &wsaData); + if (err == 0) { + if (wsaData.wVersion < wVersion) { + WSACleanup(); + return llvm::make_error<llvm::StringError>( + "WSASock version is not expected.", llvm::inconvertibleErrorCode()); + } + } else { + return llvm::errorCodeToError(llvm::mapWindowsError(::WSAGetLastError())); + } +#endif + + return llvm::Error::success(); +} + +void Socket::Terminate() { +#if defined(_WIN32) + ::WSACleanup(); +#endif +} + std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Status &error) { @@ -124,7 +151,7 @@ Status Socket::TcpConnect(llvm::StringRef host_and_port, Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); if (log) log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, - host_and_port.data()); + host_and_port.str().c_str()); Status error; std::unique_ptr<Socket> connect_socket( @@ -144,7 +171,7 @@ Status Socket::TcpListen(llvm::StringRef host_and_port, Predicate<uint16_t> *predicate, int backlog) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf("Socket::%s (%s)", __FUNCTION__, host_and_port.data()); + log->Printf("Socket::%s (%s)", __FUNCTION__, host_and_port.str().c_str()); Status error; std::string host_str; @@ -184,7 +211,7 @@ Status Socket::UdpConnect(llvm::StringRef host_and_port, Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, - host_and_port.data()); + host_and_port.str().c_str()); return UDPSocket::Connect(host_and_port, child_processes_inherit, socket); } @@ -260,8 +287,8 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)")); RegularExpression::Match regex_match(2); if (g_regex.Execute(host_and_port, ®ex_match)) { - if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) && - regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) { + if (regex_match.GetMatchAtIndex(host_and_port, 1, host_str) && + regex_match.GetMatchAtIndex(host_and_port, 2, port_str)) { // IPv6 addresses are wrapped in [] when specified with ports if (host_str.front() == '[' && host_str.back() == ']') host_str = host_str.substr(1, host_str.size() - 2); @@ -275,7 +302,8 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, // port is too large if (error_ptr) error_ptr->SetErrorStringWithFormat( - "invalid host:port specification: '%s'", host_and_port.data()); + "invalid host:port specification: '%s'", + host_and_port.str().c_str()); return false; } } @@ -284,9 +312,7 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, // integer, representing a port with an empty host. host_str.clear(); port_str.clear(); - bool ok = false; - port = StringConvert::ToUInt32(host_and_port.data(), UINT32_MAX, 10, &ok); - if (ok && port < UINT16_MAX) { + if (to_integer(host_and_port, port, 10) && port < UINT16_MAX) { port_str = host_and_port; if (error_ptr) error_ptr->Clear(); @@ -295,7 +321,7 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", - host_and_port.data()); + host_and_port.str().c_str()); return false; } @@ -368,8 +394,8 @@ Status Socket::Close() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf("%p Socket::Close (fd = %i)", static_cast<void *>(this), - m_socket); + log->Printf("%p Socket::Close (fd = %" PRIu64 ")", + static_cast<void *>(this), static_cast<uint64_t>(m_socket)); #if defined(_WIN32) bool success = !!closesocket(m_socket); @@ -453,9 +479,11 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, if (!child_processes_inherit) { flags |= SOCK_CLOEXEC; } - NativeSocket fd = ::accept4(sockfd, addr, addrlen, flags); + NativeSocket fd = llvm::sys::RetryAfterSignal(-1, ::accept4, + sockfd, addr, addrlen, flags); #else - NativeSocket fd = ::accept(sockfd, addr, addrlen); + NativeSocket fd = llvm::sys::RetryAfterSignal(-1, ::accept, + sockfd, addr, addrlen); #endif if (fd == kInvalidSocketValue) SetLastError(error); diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 172cb06a5819..882fd24558f7 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -1,9 +1,8 @@ //===-- SocketAddress.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -72,9 +71,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { using namespace lldb_private; -//---------------------------------------------------------------------- // SocketAddress constructor -//---------------------------------------------------------------------- SocketAddress::SocketAddress() { Clear(); } SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } @@ -95,15 +92,7 @@ SocketAddress::SocketAddress(const struct addrinfo *addr_info) { *this = addr_info; } -//---------------------------------------------------------------------- -// SocketAddress copy constructor -//---------------------------------------------------------------------- -SocketAddress::SocketAddress(const SocketAddress &rhs) - : m_socket_addr(rhs.m_socket_addr) {} - -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- SocketAddress::~SocketAddress() {} void SocketAddress::Clear() { @@ -184,9 +173,7 @@ bool SocketAddress::SetPort(uint16_t port) { return false; } -//---------------------------------------------------------------------- // SocketAddress assignment operator -//---------------------------------------------------------------------- const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) { if (this != &rhs) m_socket_addr = rhs.m_socket_addr; @@ -249,11 +236,11 @@ SocketAddress::GetAddressInfo(const char *hostname, const char *servname, hints.ai_protocol = ai_protocol; hints.ai_flags = ai_flags; - struct addrinfo *service_info_list = NULL; + struct addrinfo *service_info_list = nullptr; int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); if (err == 0 && service_info_list) { - for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL; - service_ptr = service_ptr->ai_next) { + for (struct addrinfo *service_ptr = service_info_list; + service_ptr != nullptr; service_ptr = service_ptr->ai_next) { addr_list.emplace_back(SocketAddress(service_ptr)); } } diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp index 8f4e1956fc28..8bf04f0a9ca3 100644 --- a/source/Host/common/StringConvert.cpp +++ b/source/Host/common/StringConvert.cpp @@ -1,9 +1,8 @@ //===-- StringConvert.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp deleted file mode 100644 index ed1677cbcb58..000000000000 --- a/source/Host/common/Symbols.cpp +++ /dev/null @@ -1,384 +0,0 @@ -//===-- Symbols.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/Symbols.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timer.h" -#include "lldb/Utility/UUID.h" - -#include "llvm/Support/FileSystem.h" - -// From MacOSX system header "mach/machine.h" -typedef int cpu_type_t; -typedef int cpu_subtype_t; - -using namespace lldb; -using namespace lldb_private; - -#if defined(__APPLE__) - -// Forward declaration of method defined in source/Host/macosx/Symbols.cpp -int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, - ModuleSpec &return_module_spec); - -#else - -int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, - ModuleSpec &return_module_spec) { - // Cannot find MacOSX files using debug symbols on non MacOSX. - return 0; -} - -#endif - -static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, - const ArchSpec *arch, - const lldb_private::UUID *uuid) { - ModuleSpecList module_specs; - if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { - ModuleSpec spec; - for (size_t i = 0; i < module_specs.GetSize(); ++i) { - bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); - UNUSED_IF_ASSERT_DISABLED(got_spec); - assert(got_spec); - if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && - (arch == NULL || (spec.GetArchitecturePtr() && - spec.GetArchitecture().IsCompatibleMatch(*arch)))) { - return true; - } - } - } - return false; -} - -// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid, -// return true if there is a matching dSYM bundle next to the exec_fspec, -// and return that value in dsym_fspec. -// If there is a .dSYM.yaa compressed archive next to the exec_fspec, -// call through Symbols::DownloadObjectAndSymbolFile to download the -// expanded/uncompressed dSYM and return that filepath in dsym_fspec. - -static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec, - const FileSpec &exec_fspec, - FileSpec &dsym_fspec) { - ConstString filename = exec_fspec.GetFilename(); - FileSpec dsym_directory = exec_fspec; - dsym_directory.RemoveLastPathComponent(); - - std::string dsym_filename = filename.AsCString(); - dsym_filename += ".dSYM"; - dsym_directory.AppendPathComponent(dsym_filename); - dsym_directory.AppendPathComponent("Contents"); - dsym_directory.AppendPathComponent("Resources"); - dsym_directory.AppendPathComponent("DWARF"); - - if (FileSystem::Instance().Exists(dsym_directory)) { - - // See if the binary name exists in the dSYM DWARF - // subdir. - dsym_fspec = dsym_directory; - dsym_fspec.AppendPathComponent(filename.AsCString()); - if (FileSystem::Instance().Exists(dsym_fspec) && - FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(), - mod_spec.GetUUIDPtr())) { - return true; - } - - // See if we have "../CF.framework" - so we'll look for - // CF.framework.dSYM/Contents/Resources/DWARF/CF - // We need to drop the last suffix after '.' to match - // 'CF' in the DWARF subdir. - std::string binary_name (filename.AsCString()); - auto last_dot = binary_name.find_last_of('.'); - if (last_dot != std::string::npos) { - binary_name.erase(last_dot); - dsym_fspec = dsym_directory; - dsym_fspec.AppendPathComponent(binary_name); - if (FileSystem::Instance().Exists(dsym_fspec) && - FileAtPathContainsArchAndUUID(dsym_fspec, - mod_spec.GetArchitecturePtr(), - mod_spec.GetUUIDPtr())) { - return true; - } - } - } - - // See if we have a .dSYM.yaa next to this executable path. - FileSpec dsym_yaa_fspec = exec_fspec; - dsym_yaa_fspec.RemoveLastPathComponent(); - std::string dsym_yaa_filename = filename.AsCString(); - dsym_yaa_filename += ".dSYM.yaa"; - dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename); - - if (FileSystem::Instance().Exists(dsym_yaa_fspec)) { - ModuleSpec mutable_mod_spec = mod_spec; - if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, true) && - FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) { - dsym_fspec = mutable_mod_spec.GetSymbolFileSpec(); - return true; - } - } - - return false; -} - -// Given a ModuleSpec with a FileSpec and optionally uuid/architecture -// filled in, look for a .dSYM bundle next to that binary. Returns true -// if a .dSYM bundle is found, and that path is returned in the dsym_fspec -// FileSpec. -// -// This routine looks a few directory layers above the given exec_path - -// exec_path might be /System/Library/Frameworks/CF.framework/CF and the -// dSYM might be /System/Library/Frameworks/CF.framework.dSYM. -// -// If there is a .dSYM.yaa compressed archive found next to the binary, -// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM - -static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, - FileSpec &dsym_fspec) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - const FileSpec &exec_fspec = module_spec.GetFileSpec(); - if (exec_fspec) { - if (::LookForDsymNextToExecutablePath (module_spec, exec_fspec, dsym_fspec)) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", dsym_fspec.GetPath().c_str()); - } - return true; - } else { - FileSpec parent_dirs = exec_fspec; - - // Remove the binary name from the FileSpec - parent_dirs.RemoveLastPathComponent(); - - // Add a ".dSYM" name to each directory component of the path, - // stripping off components. e.g. we may have a binary like - // /S/L/F/Foundation.framework/Versions/A/Foundation and - // /S/L/F/Foundation.framework.dSYM - // - // so we'll need to start with - // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the - // "A", and if that doesn't exist, strip off the "A" and try it again - // with "Versions", etc., until we find a dSYM bundle or we've - // stripped off enough path components that there's no need to - // continue. - - for (int i = 0; i < 4; i++) { - // Does this part of the path have a "." character - could it be a - // bundle's top level directory? - const char *fn = parent_dirs.GetFilename().AsCString(); - if (fn == nullptr) - break; - if (::strchr(fn, '.') != nullptr) { - if (::LookForDsymNextToExecutablePath (module_spec, parent_dirs, dsym_fspec)) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; - } - } - parent_dirs.RemoveLastPathComponent(); - } - } - } - dsym_fspec.Clear(); - return false; -} - -static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, - "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); - - FileSpec symbol_fspec; - ModuleSpec dsym_module_spec; - // First try and find the dSYM in the same directory as the executable or in - // an appropriate parent directory - if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) { - // We failed to easily find the dSYM above, so use DebugSymbols - LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec); - } else { - dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; - } - return dsym_module_spec.GetSymbolFileSpec(); -} - -ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) { - ModuleSpec result; - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (exec_fspec && - ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { - result.GetFileSpec() = exec_fspec; - } else { - LocateMacOSXFilesUsingDebugSymbols(module_spec, result); - } - return result; -} - -// Keep "symbols.enable-external-lookup" description in sync with this function. - -FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { - FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); - if (symbol_file_spec.IsAbsolute() && - FileSystem::Instance().Exists(symbol_file_spec)) - return symbol_file_spec; - - const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); - if (symbol_filename && symbol_filename[0]) { - FileSpecList debug_file_search_paths( - Target::GetDefaultDebugFileSearchPaths()); - - // Add module directory. - FileSpec module_file_spec = module_spec.GetFileSpec(); - // We keep the unresolved pathname if it fails. - FileSystem::Instance().ResolveSymbolicLink(module_file_spec, module_file_spec); - - const ConstString &file_dir = module_file_spec.GetDirectory(); - { - FileSpec file_spec(file_dir.AsCString(".")); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } - - if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { - - // Add current working directory. - { - FileSpec file_spec("."); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } - -#ifndef _WIN32 -#if defined(__NetBSD__) - // Add /usr/libdata/debug directory. - { - FileSpec file_spec("/usr/libdata/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } -#else - // Add /usr/lib/debug directory. - { - FileSpec file_spec("/usr/lib/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } -#endif -#endif // _WIN32 - } - - std::string uuid_str; - const UUID &module_uuid = module_spec.GetUUID(); - if (module_uuid.IsValid()) { - // Some debug files are stored in the .build-id directory like this: - // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug - uuid_str = module_uuid.GetAsString(""); - std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), - ::tolower); - uuid_str.insert(2, 1, '/'); - uuid_str = uuid_str + ".debug"; - } - - size_t num_directories = debug_file_search_paths.GetSize(); - for (size_t idx = 0; idx < num_directories; ++idx) { - FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); - FileSystem::Instance().Resolve(dirspec); - if (!FileSystem::Instance().IsDirectory(dirspec)) - continue; - - std::vector<std::string> files; - std::string dirname = dirspec.GetPath(); - - files.push_back(dirname + "/" + symbol_filename); - files.push_back(dirname + "/.debug/" + symbol_filename); - files.push_back(dirname + "/.build-id/" + uuid_str); - - // Some debug files may stored in the module directory like this: - // /usr/lib/debug/usr/lib/library.so.debug - if (!file_dir.IsEmpty()) - files.push_back(dirname + file_dir.AsCString() + "/" + symbol_filename); - - const uint32_t num_files = files.size(); - for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { - const std::string &filename = files[idx_file]; - FileSpec file_spec(filename); - FileSystem::Instance().Resolve(file_spec); - - if (llvm::sys::fs::equivalent(file_spec.GetPath(), - module_file_spec.GetPath())) - continue; - - if (FileSystem::Instance().Exists(file_spec)) { - lldb_private::ModuleSpecList specs; - const size_t num_specs = - ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); - assert(num_specs <= 1 && - "Symbol Vendor supports only a single architecture"); - if (num_specs == 1) { - ModuleSpec mspec; - if (specs.GetModuleSpecAtIndex(0, mspec)) { - // Skip the uuids check if module_uuid is invalid. For example, - // this happens for *.dwp files since at the moment llvm-dwp - // doesn't output build ids, nor does binutils dwp. - if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) - return file_spec; - } - } - } - } - } - } - - return LocateExecutableSymbolFileDsym(module_spec); -} - -#if !defined(__APPLE__) - -FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle, - const lldb_private::UUID *uuid, - const ArchSpec *arch) { - // FIXME - return FileSpec(); -} - -bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - bool force_lookup) { - // Fill in the module_spec.GetFileSpec() for the object file and/or the - // module_spec.GetSymbolFileSpec() for the debug symbols file. - return false; -} - -#endif diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp index 1a10336f1dfc..58f99f7832fe 100644 --- a/source/Host/common/TCPSocket.cpp +++ b/source/Host/common/TCPSocket.cpp @@ -1,9 +1,8 @@ //===-- TCPSocket.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -18,6 +17,7 @@ #include "lldb/Utility/Log.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/raw_ostream.h" #ifndef LLDB_DISABLE_POSIX @@ -118,6 +118,14 @@ std::string TCPSocket::GetRemoteIPAddress() const { return ""; } +std::string TCPSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("connect://[{0}]:{1}", GetRemoteIPAddress(), + GetRemotePortNumber()); + } + return ""; +} + Status TCPSocket::CreateSocket(int domain) { Status error; if (IsValid()) @@ -143,7 +151,7 @@ Status TCPSocket::Connect(llvm::StringRef name) { return error; auto addresses = lldb_private::SocketAddress::GetAddressInfo( - host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); for (auto address : addresses) { error = CreateSocket(address.GetFamily()); if (error.Fail()) @@ -151,8 +159,8 @@ Status TCPSocket::Connect(llvm::StringRef name) { address.SetPort(port); - if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(), - address.GetLength())) { + if (-1 == llvm::sys::RetryAfterSignal(-1, ::connect, + GetNativeSocket(), &address.sockaddr(), address.GetLength())) { CLOSE_SOCKET(GetNativeSocket()); continue; } @@ -182,7 +190,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) { if (host_str == "*") host_str = "0.0.0.0"; auto addresses = lldb_private::SocketAddress::GetAddressInfo( - host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); for (auto address : addresses) { int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, m_child_processes_inherit, error); diff --git a/source/Host/common/TaskPool.cpp b/source/Host/common/TaskPool.cpp index ba1362a46f33..73f761b5cf63 100644 --- a/source/Host/common/TaskPool.cpp +++ b/source/Host/common/TaskPool.cpp @@ -1,14 +1,14 @@ //===--------------------- TaskPool.cpp -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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/Host/TaskPool.h" #include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/Log.h" #include <cstdint> #include <queue> @@ -66,15 +66,22 @@ void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { // Note that this detach call needs to happen with the m_tasks_mutex held. // This prevents the thread from exiting prematurely and triggering a linux // libc bug (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). - lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, - this, nullptr, min_stack_size) - .Release(); + llvm::Expected<HostThread> host_thread = + lldb_private::ThreadLauncher::LaunchThread( + "task-pool.worker", WorkerPtr, this, min_stack_size); + if (host_thread) { + host_thread->Release(); + } else { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(host_thread.takeError())); + } } } lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { Worker((TaskPoolImpl *)pool); - return 0; + return {}; } void TaskPoolImpl::Worker(TaskPoolImpl *pool) { diff --git a/source/Host/common/Terminal.cpp b/source/Host/common/Terminal.cpp index be912fbe6155..4b536b03d852 100644 --- a/source/Host/common/Terminal.cpp +++ b/source/Host/common/Terminal.cpp @@ -1,9 +1,8 @@ //===-- Terminal.cpp --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -82,36 +81,30 @@ bool Terminal::SetCanonical(bool enabled) { return false; } -//---------------------------------------------------------------------- // Default constructor -//---------------------------------------------------------------------- TerminalState::TerminalState() : m_tty(), m_tflags(-1), #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap(), + m_termios_up(), #endif m_process_group(-1) { } -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- TerminalState::~TerminalState() {} void TerminalState::Clear() { m_tty.Clear(); m_tflags = -1; #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap.reset(); + m_termios_up.reset(); #endif m_process_group = -1; } -//---------------------------------------------------------------------- // Save the current state of the TTY for the file descriptor "fd" and if // "save_process_group" is true, attempt to save the process group info for the // TTY. -//---------------------------------------------------------------------- bool TerminalState::Save(int fd, bool save_process_group) { m_tty.SetFileDescriptor(fd); if (m_tty.IsATerminal()) { @@ -119,11 +112,11 @@ bool TerminalState::Save(int fd, bool save_process_group) { m_tflags = ::fcntl(fd, F_GETFL, 0); #endif #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (m_termios_ap.get() == NULL) - m_termios_ap.reset(new struct termios); - int err = ::tcgetattr(fd, m_termios_ap.get()); + if (m_termios_up == nullptr) + m_termios_up.reset(new struct termios); + int err = ::tcgetattr(fd, m_termios_up.get()); if (err != 0) - m_termios_ap.reset(); + m_termios_up.reset(); #endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED #ifndef LLDB_DISABLE_POSIX if (save_process_group) @@ -135,17 +128,15 @@ bool TerminalState::Save(int fd, bool save_process_group) { m_tty.Clear(); m_tflags = -1; #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - m_termios_ap.reset(); + m_termios_up.reset(); #endif m_process_group = -1; } return IsValid(); } -//---------------------------------------------------------------------- // Restore the state of the TTY using the cached values from a previous call to // Save(). -//---------------------------------------------------------------------- bool TerminalState::Restore() const { #ifndef LLDB_DISABLE_POSIX if (IsValid()) { @@ -155,12 +146,12 @@ bool TerminalState::Restore() const { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (TTYStateIsValid()) - tcsetattr(fd, TCSANOW, m_termios_ap.get()); + tcsetattr(fd, TCSANOW, m_termios_up.get()); #endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (ProcessGroupIsValid()) { // Save the original signal handler. - void (*saved_sigttou_callback)(int) = NULL; + void (*saved_sigttou_callback)(int) = nullptr; saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); // Set the process group tcsetpgrp(fd, m_process_group); @@ -173,60 +164,44 @@ bool TerminalState::Restore() const { return false; } -//---------------------------------------------------------------------- // Returns true if this object has valid saved TTY state settings that can be // used to restore a previous state. -//---------------------------------------------------------------------- bool TerminalState::IsValid() const { return m_tty.FileDescriptorIsValid() && (TFlagsIsValid() || TTYStateIsValid()); } -//---------------------------------------------------------------------- // Returns true if m_tflags is valid -//---------------------------------------------------------------------- bool TerminalState::TFlagsIsValid() const { return m_tflags != -1; } -//---------------------------------------------------------------------- // Returns true if m_ttystate is valid -//---------------------------------------------------------------------- bool TerminalState::TTYStateIsValid() const { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - return m_termios_ap.get() != 0; + return m_termios_up != nullptr; #else return false; #endif } -//---------------------------------------------------------------------- // Returns true if m_process_group is valid -//---------------------------------------------------------------------- bool TerminalState::ProcessGroupIsValid() const { return static_cast<int32_t>(m_process_group) != -1; } -//------------------------------------------------------------------ // Constructor -//------------------------------------------------------------------ TerminalStateSwitcher::TerminalStateSwitcher() : m_currentState(UINT32_MAX) {} -//------------------------------------------------------------------ // Destructor -//------------------------------------------------------------------ TerminalStateSwitcher::~TerminalStateSwitcher() {} -//------------------------------------------------------------------ // Returns the number of states that this switcher contains -//------------------------------------------------------------------ uint32_t TerminalStateSwitcher::GetNumberOfStates() const { return llvm::array_lengthof(m_ttystates); } -//------------------------------------------------------------------ // Restore the state at index "idx". // // Returns true if the restore was successful, false otherwise. -//------------------------------------------------------------------ bool TerminalStateSwitcher::Restore(uint32_t idx) const { const uint32_t num_states = GetNumberOfStates(); if (idx >= num_states) @@ -248,12 +223,10 @@ bool TerminalStateSwitcher::Restore(uint32_t idx) const { return false; } -//------------------------------------------------------------------ // Save the state at index "idx" for file descriptor "fd" and save the process // group if requested. // // Returns true if the restore was successful, false otherwise. -//------------------------------------------------------------------ bool TerminalStateSwitcher::Save(uint32_t idx, int fd, bool save_process_group) { const uint32_t num_states = GetNumberOfStates(); diff --git a/source/Host/common/ThreadLauncher.cpp b/source/Host/common/ThreadLauncher.cpp index f3401016393f..6e3c8b6a13a4 100644 --- a/source/Host/common/ThreadLauncher.cpp +++ b/source/Host/common/ThreadLauncher.cpp @@ -1,10 +1,8 @@ -//===-- ThreadLauncher.cpp ---------------------------------------*- C++ -//-*-===// +//===-- ThreadLauncher.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -18,18 +16,14 @@ #include "lldb/Host/windows/windows.h" #endif +#include "llvm/Support/WindowsError.h" + using namespace lldb; using namespace lldb_private; -HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, - lldb::thread_func_t thread_function, - lldb::thread_arg_t thread_arg, - Status *error_ptr, - size_t min_stack_byte_size) { - Status error; - if (error_ptr) - error_ptr->Clear(); - +llvm::Expected<HostThread> ThreadLauncher::LaunchThread( + llvm::StringRef name, lldb::thread_func_t thread_function, + lldb::thread_arg_t thread_arg, size_t min_stack_byte_size) { // Host::ThreadCreateTrampoline will delete this pointer for us. HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo(name.data(), thread_function, thread_arg); @@ -38,8 +32,8 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, thread = (lldb::thread_t)::_beginthreadex( 0, (unsigned)min_stack_byte_size, HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); - if (thread == (lldb::thread_t)(-1L)) - error.SetError(::GetLastError(), eErrorTypeWin32); + if (thread == LLDB_INVALID_HOST_THREAD) + return llvm::errorCodeToError(llvm::mapWindowsError(GetLastError())); #else // ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. @@ -50,7 +44,7 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, } #endif - pthread_attr_t *thread_attr_ptr = NULL; + pthread_attr_t *thread_attr_ptr = nullptr; pthread_attr_t thread_attr; bool destroy_attr = false; if (min_stack_byte_size > 0) { @@ -74,12 +68,10 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, if (destroy_attr) ::pthread_attr_destroy(&thread_attr); - error.SetError(err, eErrorTypePOSIX); + if (err) + return llvm::errorCodeToError( + std::error_code(err, std::generic_category())); #endif - if (error_ptr) - *error_ptr = error; - if (!error.Success()) - thread = LLDB_INVALID_HOST_THREAD; return HostThread(thread); } diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp index 96bcc6a150a9..8dbf57d6fe4e 100644 --- a/source/Host/common/UDPSocket.cpp +++ b/source/Host/common/UDPSocket.cpp @@ -1,9 +1,8 @@ //===-- UDPSocket.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -135,3 +134,11 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, error.Clear(); return error; } + +std::string UDPSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("udp://[{0}]:{1}", m_sockaddr.GetIPAddress(), + m_sockaddr.GetPort()); + } + return ""; +} diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index 967a294cbf72..cb23ac17ef53 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -1,9 +1,8 @@ //===-- XML.cpp -------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -135,7 +134,7 @@ XMLNode XMLNode::GetChild() const { llvm::StringRef XMLNode::GetAttributeValue(const char *name, const char *fail_value) const { - const char *attr_value = NULL; + const char *attr_value = nullptr; #if defined(LIBXML2_DEFINED) if (IsValid()) diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 7bf959aee982..99d728d63bc0 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -1,10 +1,9 @@ //===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -24,12 +23,12 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" @@ -39,6 +38,10 @@ extern "C" { extern char **environ; } +namespace lldb_private { +class ProcessLaunchInfo; +} + using namespace lldb; using namespace lldb_private; diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index d123936b3668..e28cf4aa420f 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -1,9 +1,8 @@ //===-- HostInfoFreeBSD.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp index 4d50363c72e0..08fec099bf49 100644 --- a/source/Host/netbsd/Host.cpp +++ b/source/Host/netbsd/Host.cpp @@ -1,9 +1,8 @@ //===-- source/Host/netbsd/Host.cpp -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -23,12 +22,12 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" @@ -41,6 +40,10 @@ extern char **environ; using namespace lldb; using namespace lldb_private; +namespace lldb_private { +class ProcessLaunchInfo; +} + Environment Host::GetEnvironment() { return Environment(environ); } static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp index a54483fcc55b..99d413922327 100644 --- a/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/source/Host/netbsd/HostInfoNetBSD.cpp @@ -1,9 +1,8 @@ //===-- HostInfoNetBSD.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/source/Host/openbsd/Host.cpp b/source/Host/openbsd/Host.cpp index cba1f4ee6b7c..ba6cf057ca17 100644 --- a/source/Host/openbsd/Host.cpp +++ b/source/Host/openbsd/Host.cpp @@ -1,9 +1,8 @@ //===-- source/Host/openbsd/Host.cpp ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,12 +19,12 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" @@ -38,6 +37,10 @@ extern char **environ; using namespace lldb; using namespace lldb_private; +namespace lldb_private { +class ProcessLaunchInfo; +} + Environment Host::GetEnvironment() { Environment env; char *v; @@ -68,8 +71,7 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches( diff --git a/source/Host/openbsd/HostInfoOpenBSD.cpp b/source/Host/openbsd/HostInfoOpenBSD.cpp index 548958899322..950f2ebb86b8 100644 --- a/source/Host/openbsd/HostInfoOpenBSD.cpp +++ b/source/Host/openbsd/HostInfoOpenBSD.cpp @@ -1,9 +1,8 @@ //===-- HostInfoOpenBSD.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -17,16 +16,17 @@ using namespace lldb_private; -bool HostInfoOpenBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoOpenBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(utsname)); if (uname(&un) < 0) - return false; + return llvm::VersionTuple(); - int status = sscanf(un.release, "%u.%u", &major, &minor); - return status == 2; + unsigned major, minor; + if (2 == sscanf(un.release, "%u.%u", &major, &minor)) + return llvm::VersionTuple(major, minor); + return llvm::VersionTuple(); } bool HostInfoOpenBSD::GetOSBuildString(std::string &s) { diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index deac3844d4a2..067e85972eca 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -1,9 +1,8 @@ //===-- ConnectionFileDescriptorPosix.cpp -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -32,6 +31,7 @@ #include <unistd.h> #endif +#include <memory> #include <sstream> #include "llvm/Support/Errno.h" @@ -87,8 +87,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(false) { - m_write_sp.reset(new File(fd, owns_fd)); - m_read_sp.reset(new File(fd, false)); + m_write_sp = std::make_shared<File>(fd, owns_fd); + m_read_sp = std::make_shared<File>(fd, false); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); @@ -111,7 +111,7 @@ ConnectionFileDescriptor::~ConnectionFileDescriptor() { if (log) log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this)); - Disconnect(NULL); + Disconnect(nullptr); CloseCommandPipe(); } @@ -222,8 +222,8 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, m_read_sp = std::move(tcp_socket); m_write_sp = m_read_sp; } else { - m_read_sp.reset(new File(fd, false)); - m_write_sp.reset(new File(fd, false)); + m_read_sp = std::make_shared<File>(fd, false); + m_write_sp = std::make_shared<File>(fd, false); } m_uri = *addr; return eConnectionStatusSuccess; @@ -262,7 +262,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 0; - ::tcsetattr(fd, TCSANOW, &options); + llvm::sys::RetryAfterSignal(-1, ::tcsetattr, fd, TCSANOW, &options); } int flags = ::fcntl(fd, F_GETFL, 0); @@ -272,8 +272,8 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, ::fcntl(fd, F_SETFL, flags); } } - m_read_sp.reset(new File(fd, true)); - m_write_sp.reset(new File(fd, false)); + m_read_sp = std::make_shared<File>(fd, true); + m_write_sp = std::make_shared<File>(fd, false); return eConnectionStatusSuccess; } #endif @@ -758,13 +758,7 @@ void ConnectionFileDescriptor::SetChildProcessesInherit( } void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { - assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); - TCPSocket *tcp_socket = static_cast<TCPSocket *>(socket); - m_write_sp.reset(socket); m_read_sp = m_write_sp; - StreamString strm; - strm.Printf("connect://%s:%u", tcp_socket->GetRemoteIPAddress().c_str(), - tcp_socket->GetRemotePortNumber()); - m_uri = strm.GetString(); + m_uri = socket->GetRemoteConnectionURI(); } diff --git a/source/Host/posix/DomainSocket.cpp b/source/Host/posix/DomainSocket.cpp index 3e3abadc2e5a..27872f48129c 100644 --- a/source/Host/posix/DomainSocket.cpp +++ b/source/Host/posix/DomainSocket.cpp @@ -1,14 +1,14 @@ //===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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/Host/posix/DomainSocket.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include <stddef.h> @@ -82,8 +82,8 @@ Status DomainSocket::Connect(llvm::StringRef name) { m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error); if (error.Fail()) return error; - if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < - 0) + if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(), + (struct sockaddr *)&saddr_un, saddr_un_len) < 0) SetLastError(error); return error; @@ -125,3 +125,31 @@ size_t DomainSocket::GetNameOffset() const { return 0; } void DomainSocket::DeleteSocketFile(llvm::StringRef name) { llvm::sys::fs::remove(name); } + +std::string DomainSocket::GetSocketName() const { + if (m_socket != kInvalidSocketValue) { + struct sockaddr_un saddr_un; + saddr_un.sun_family = AF_UNIX; + socklen_t sock_addr_len = sizeof(struct sockaddr_un); + if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) == + 0) { + std::string name(saddr_un.sun_path + GetNameOffset(), + sock_addr_len - + offsetof(struct sockaddr_un, sun_path) - + GetNameOffset()); + if (name.back() == '\0') name.pop_back(); + return name; + } + } + return ""; +} + +std::string DomainSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("{0}://{1}", + GetNameOffset() == 0 ? "unix-connect" + : "unix-abstract-connect", + GetSocketName()); + } + return ""; +} diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp index d7045ff99919..32fae68abb4d 100644 --- a/source/Host/posix/FileSystem.cpp +++ b/source/Host/posix/FileSystem.cpp @@ -1,9 +1,8 @@ //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -26,6 +25,7 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" using namespace lldb; @@ -72,9 +72,9 @@ Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { } FILE *FileSystem::Fopen(const char *path, const char *mode) { - return ::fopen(path, mode); + return llvm::sys::RetryAfterSignal(nullptr, ::fopen, path, mode); } int FileSystem::Open(const char *path, int flags, int mode) { - return ::open(path, flags, mode); + return llvm::sys::RetryAfterSignal(-1, ::open, path, flags, mode); } diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index 4763ebc9b9d4..f300e22e9e5c 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -1,13 +1,13 @@ //===-- HostInfoPosix.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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/Host/posix/HostInfoPosix.h" +#include "lldb/Utility/UserIDResolver.h" #include "lldb/Utility/Log.h" #include "llvm/ADT/SmallString.h" @@ -49,40 +49,38 @@ bool HostInfoPosix::GetHostname(std::string &s) { #define USE_GETPWUID #endif -#ifdef USE_GETPWUID -static std::mutex s_getpwuid_lock; -#endif +namespace { +class PosixUserIDResolver : public UserIDResolver { +protected: + llvm::Optional<std::string> DoGetUserName(id_t uid) override; + llvm::Optional<std::string> DoGetGroupName(id_t gid) override; +}; +} // namespace -const char *HostInfoPosix::LookupUserName(uint32_t uid, - std::string &user_name) { +llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { #ifdef USE_GETPWUID // getpwuid_r is missing from android-9 - // make getpwuid thread safe with a mutex - std::lock_guard<std::mutex> lock(s_getpwuid_lock); + // UserIDResolver provides some thread safety by making sure noone calls this + // function concurrently, but using getpwuid is ultimately not thread-safe as + // we don't know who else might be calling it. struct passwd *user_info_ptr = ::getpwuid(uid); - if (user_info_ptr) { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + if (user_info_ptr) + return std::string(user_info_ptr->pw_name); #else struct passwd user_info; struct passwd *user_info_ptr = &user_info; char user_buffer[PATH_MAX]; size_t user_buffer_size = sizeof(user_buffer); if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, - &user_info_ptr) == 0) { - if (user_info_ptr) { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + &user_info_ptr) == 0 && + user_info_ptr) { + return std::string(user_info_ptr->pw_name); } #endif - user_name.clear(); - return nullptr; + return llvm::None; } -const char *HostInfoPosix::LookupGroupName(uint32_t gid, - std::string &group_name) { +llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { #ifndef __ANDROID__ char group_buffer[PATH_MAX]; size_t group_buffer_size = sizeof(group_buffer); @@ -91,24 +89,25 @@ const char *HostInfoPosix::LookupGroupName(uint32_t gid, // Try the threadsafe version first if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0) { - if (group_info_ptr) { - group_name.assign(group_info_ptr->gr_name); - return group_name.c_str(); - } + if (group_info_ptr) + return std::string(group_info_ptr->gr_name); } else { // The threadsafe version isn't currently working for me on darwin, but the // non-threadsafe version is, so I am calling it below. group_info_ptr = ::getgrgid(gid); - if (group_info_ptr) { - group_name.assign(group_info_ptr->gr_name); - return group_name.c_str(); - } + if (group_info_ptr) + return std::string(group_info_ptr->gr_name); } - group_name.clear(); #else assert(false && "getgrgid_r() not supported on Android"); #endif - return NULL; + return llvm::None; +} + +static llvm::ManagedStatic<PosixUserIDResolver> g_user_id_resolver; + +UserIDResolver &HostInfoPosix::GetUserIDResolver() { + return *g_user_id_resolver; } uint32_t HostInfoPosix::GetUserID() { return getuid(); } @@ -121,43 +120,6 @@ uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh"); } -bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec, - llvm::StringRef dir) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - - FileSpec lldb_file_spec = GetShlibDir(); - if (!lldb_file_spec) - return false; - - std::string raw_path = lldb_file_spec.GetPath(); - // drop library directory - llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); - - // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with - // */bin as the base directory for helper exe programs. This will fail if - // the /lib and /bin directories are rooted in entirely different trees. - if (log) - log->Printf("HostInfoPosix::ComputePathRelativeToLibrary() attempting to " - "derive the %s path from this path: %s", - dir.data(), raw_path.c_str()); - - if (!parent_path.empty()) { - // Now write in bin in place of lib. - raw_path = (parent_path + dir).str(); - - if (log) - log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, - raw_path.c_str()); - } else { - if (log) - log->Printf("Host::%s() failed to find /lib/liblldb within the shared " - "lib path, bailing on bin path construction", - __FUNCTION__); - } - file_spec.GetDirectory().SetString(raw_path); - return (bool)file_spec.GetDirectory(); -} - bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { return ComputePathRelativeToLibrary(file_spec, "/bin"); } diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp index f431e0c72de1..cc187d442468 100644 --- a/source/Host/posix/HostProcessPosix.cpp +++ b/source/Host/posix/HostProcessPosix.cpp @@ -1,9 +1,8 @@ //===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -88,7 +87,7 @@ bool HostProcessPosix::IsRunning() const { return error.Success(); } -HostThread HostProcessPosix::StartMonitoring( +llvm::Expected<HostThread> HostProcessPosix::StartMonitoring( const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { return Host::StartMonitoringChildProcess(callback, m_process, monitor_signals); diff --git a/source/Host/posix/HostThreadPosix.cpp b/source/Host/posix/HostThreadPosix.cpp index 13de42f763ec..d78bba517f69 100644 --- a/source/Host/posix/HostThreadPosix.cpp +++ b/source/Host/posix/HostThreadPosix.cpp @@ -1,9 +1,8 @@ //===-- HostThreadPosix.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -30,7 +29,7 @@ Status HostThreadPosix::Join(lldb::thread_result_t *result) { error.SetError(err, lldb::eErrorTypePOSIX); } else { if (result) - *result = NULL; + *result = nullptr; error.SetError(EINVAL, eErrorTypePOSIX); } diff --git a/source/Host/posix/LockFilePosix.cpp b/source/Host/posix/LockFilePosix.cpp index 05423062bd44..a6eae95c333b 100644 --- a/source/Host/posix/LockFilePosix.cpp +++ b/source/Host/posix/LockFilePosix.cpp @@ -1,14 +1,15 @@ //===-- LockFilePosix.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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/Host/posix/LockFilePosix.h" +#include "llvm/Support/Errno.h" + #include <fcntl.h> #include <unistd.h> @@ -28,7 +29,7 @@ Status fileLock(int fd, int cmd, int lock_type, const uint64_t start, fl.l_pid = ::getpid(); Status error; - if (::fcntl(fd, cmd, &fl) == -1) + if (llvm::sys::RetryAfterSignal(-1, ::fcntl, fd, cmd, &fl) == -1) error.SetErrorToErrno(); return error; diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index 866a9897ee43..efdc151e3763 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -1,9 +1,8 @@ //===-- PipePosix.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Utility/SelectHelper.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) @@ -158,7 +158,7 @@ Status PipePosix::OpenAsReader(llvm::StringRef name, flags |= O_CLOEXEC; Status error; - int fd = ::open(name.data(), flags); + int fd = llvm::sys::RetryAfterSignal(-1, ::open, name.data(), flags); if (fd != -1) m_fds[READ] = fd; else @@ -193,7 +193,7 @@ PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, if (fd == -1) { const auto errno_copy = errno; // We may get ENXIO if a reader side of the pipe hasn't opened yet. - if (errno_copy != ENXIO) + if (errno_copy != ENXIO && errno_copy != EINTR) return Status(errno_copy, eErrorTypePOSIX); std::this_thread::sleep_for( @@ -276,6 +276,8 @@ Status PipePosix::ReadWithTimeout(void *buf, size_t size, bytes_read += result; if (bytes_read == size || result == 0) break; + } else if (errno == EINTR) { + continue; } else { error.SetErrorToErrno(); break; @@ -306,6 +308,8 @@ Status PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) { bytes_written += result; if (bytes_written == size) break; + } else if (errno == EINTR) { + continue; } else { error.SetErrorToErrno(); } diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index 6bf78463d060..185c7f0fe248 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -1,9 +1,8 @@ -//===-- ProcessLauncherLinux.cpp --------------------------------*- C++ -*-===// +//===-- ProcessLauncherPosixFork.cpp ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,7 +10,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/Pipe.h" -#include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "llvm/Support/Errno.h" @@ -73,7 +72,8 @@ static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info) static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, int flags) { - int target_fd = ::open(file_spec.GetCString(), flags, 0666); + int target_fd = llvm::sys::RetryAfterSignal(-1, ::open, + file_spec.GetCString(), flags, 0666); if (target_fd == -1) ExitWithError(error_fd, "DupDescriptor-open"); @@ -212,7 +212,7 @@ ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, error.SetErrorString(buf); - waitpid(pid, nullptr, 0); + llvm::sys::RetryAfterSignal(-1, waitpid, pid, nullptr, 0); return HostProcess(); } |