diff options
Diffstat (limited to 'source')
42 files changed, 590 insertions, 765 deletions
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 687187b26ccd..6a933df43e14 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -161,9 +161,9 @@ public: // List the common thread ID's const std::vector<uint32_t> &thread_index_ids = stack.GetUniqueThreadIndexIDs(); - strm.Printf("%lu thread(s) ", thread_index_ids.size()); + strm.Format("{0} thread(s) ", thread_index_ids.size()); for (const uint32_t &thread_index_id : thread_index_ids) { - strm.Printf("#%u ", thread_index_id); + strm.Format("#{0} ", thread_index_id); } strm.EOL(); @@ -209,7 +209,7 @@ protected: Process *process = m_exe_ctx.GetProcessPtr(); Thread *thread = process->GetThreadList().FindThreadByID(tid).get(); if (thread == nullptr) { - result.AppendErrorWithFormat("Failed to process thread# %llu.\n", tid); + result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp index 2b7abd60f8bc..c2a9115c3068 100644 --- a/source/Core/DumpDataExtractor.cpp +++ b/source/Core/DumpDataExtractor.cpp @@ -154,7 +154,8 @@ lldb::offset_t lldb_private::DumpDataExtractor( target_sp = exe_scope->CalculateTarget(); if (target_sp) { DisassemblerSP disassembler_sp(Disassembler::FindPlugin( - target_sp->GetArchitecture(), nullptr, nullptr)); + target_sp->GetArchitecture(), + target_sp->GetDisassemblyFlavor(), nullptr)); if (disassembler_sp) { lldb::addr_t addr = base_addr + start_offset; lldb_private::Address so_addr; diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 3de93ebc220b..90a4462c6ca9 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -24,10 +24,12 @@ #endif #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() #include "lldb/Host/Config.h" +#include "lldb/Host/Host.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -133,9 +135,8 @@ FILE *File::GetStream() { m_should_close_fd = true; } - do { - m_stream = ::fdopen(m_descriptor, mode); - } while (m_stream == NULL && errno == EINTR); + m_stream = + llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); // If we got a stream, then we own the stream and should no // longer own the descriptor because fclose() will close it for us @@ -157,6 +158,19 @@ void File::SetStream(FILE *fh, bool transfer_ownership) { m_own_stream = transfer_ownership; } +static int DoOpen(const char *path, int flags, int mode) { +#ifdef _MSC_VER + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return -1; + int result; + ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode); + return result; +#else + return ::open(path, flags, mode); +#endif +} + Status File::Open(const char *path, uint32_t options, uint32_t permissions) { Status error; if (IsValid()) @@ -222,20 +236,7 @@ Status File::Open(const char *path, uint32_t options, uint32_t permissions) { mode |= S_IXOTH; } - do { -#ifdef _MSC_VER - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) { - m_descriptor = -1; - error.SetErrorString("Error converting path to UTF-16"); - return error; - } - ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); -#else - m_descriptor = ::open(path, oflag, mode); -#endif - } while (m_descriptor < 0 && errno == EINTR); - + m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode); if (!DescriptorIsValid()) error.SetErrorToErrno(); else { @@ -421,12 +422,7 @@ off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { Status File::Flush() { Status error; if (StreamIsValid()) { - int err = 0; - do { - err = ::fflush(m_stream); - } while (err == EOF && errno == EINTR); - - if (err == EOF) + if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) error.SetErrorToErrno(); } else if (!DescriptorIsValid()) { error.SetErrorString("invalid file handle"); @@ -442,12 +438,7 @@ Status File::Sync() { if (err == 0) error.SetErrorToGenericError(); #else - int err = 0; - do { - err = ::fsync(m_descriptor); - } while (err == -1 && errno == EINTR); - - if (err == -1) + if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1) error.SetErrorToErrno(); #endif } else { @@ -497,10 +488,7 @@ Status File::Read(void *buf, size_t &num_bytes) { ssize_t bytes_read = -1; if (DescriptorIsValid()) { - do { - bytes_read = ::read(m_descriptor, buf, num_bytes); - } while (bytes_read < 0 && errno == EINTR); - + bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); if (bytes_read == -1) { error.SetErrorToErrno(); num_bytes = 0; @@ -559,10 +547,8 @@ Status File::Write(const void *buf, size_t &num_bytes) { ssize_t bytes_written = -1; if (DescriptorIsValid()) { - do { - bytes_written = ::write(m_descriptor, buf, num_bytes); - } while (bytes_written < 0 && errno == EINTR); - + bytes_written = + llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes); if (bytes_written == -1) { error.SetErrorToErrno(); num_bytes = 0; @@ -624,11 +610,8 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { #ifndef _WIN32 int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { - ssize_t bytes_read = -1; - do { - bytes_read = ::pread(fd, buf, num_bytes, offset); - } while (bytes_read < 0 && errno == EINTR); - + ssize_t bytes_read = + llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset); if (bytes_read < 0) { num_bytes = 0; error.SetErrorToErrno(); @@ -730,11 +713,8 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { #ifndef _WIN32 - ssize_t bytes_written = -1; - do { - bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); - } while (bytes_written < 0 && errno == EINTR); - + ssize_t bytes_written = + llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset); if (bytes_written < 0) { num_bytes = 0; error.SetErrorToErrno(); diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 7de6f7fa865d..c0c4471e735f 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -193,10 +193,16 @@ Status MainLoop::RunImpl::Poll() { void MainLoop::RunImpl::ProcessEvents() { #ifdef FORCE_PSELECT - for (const auto &fd : loop.m_read_fds) { - if (!FD_ISSET(fd.first, &read_fd_set)) - continue; - IOObject::WaitableHandle handle = fd.first; + // Collect first all readable file descriptors into a separate vector and then + // iterate over it to invoke callbacks. Iterating directly over + // loop.m_read_fds is not possible because the callbacks can modify the + // container which could invalidate the iterator. + std::vector<IOObject::WaitableHandle> fds; + for (const auto &fd : loop.m_read_fds) + if (FD_ISSET(fd.first, &read_fd_set)) + fds.push_back(fd.first); + + for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { if ((fd.revents & POLLIN) == 0) @@ -209,13 +215,16 @@ void MainLoop::RunImpl::ProcessEvents() { loop.ProcessReadObject(handle); } - for (const auto &entry : loop.m_signals) { + std::vector<int> signals; + for (const auto &entry : loop.m_signals) + if (g_signal_flags[entry.first] != 0) + signals.push_back(entry.first); + + for (const auto &signal : signals) { if (loop.m_terminate_request) return; - if (g_signal_flags[entry.first] == 0) - continue; // No signal - g_signal_flags[entry.first] = 0; - loop.ProcessSignal(entry.first); + g_signal_flags[signal] = 0; + loop.ProcessSignal(signal); } } #endif diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 341c301dc9c5..b5b6e9d8b923 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -29,11 +29,13 @@ using namespace lldb_private; // NativeProcessProtocol Members // ----------------------------------------------------------------------------- -NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) - : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), - m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), - m_delegates_mutex(), m_delegates(), m_breakpoint_list(), - m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} +NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, + NativeDelegate &delegate) + : m_pid(pid), m_terminal_fd(terminal_fd) { + bool registered = RegisterNativeDelegate(delegate); + assert(registered); + (void)registered; +} lldb_private::Status NativeProcessProtocol::Interrupt() { Status error; @@ -488,23 +490,4 @@ Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, "failed to retrieve a valid architecture from the exe module"); } -#if !defined(__linux__) && !defined(__NetBSD__) -// These need to be implemented to support lldb-gdb-server on a given platform. -// Stubs are -// provided to make the rest of the code link on non-supported platforms. - -Status NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -Status NativeProcessProtocol::Attach(lldb::pid_t pid, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -#endif +NativeProcessProtocol::Factory::~Factory() = default; diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 440ae5d9027f..41150fa7fd74 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -201,7 +201,7 @@ const SocketAddress &SocketAddress:: operator=(const struct addrinfo *addr_info) { Clear(); if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && - addr_info->ai_addrlen <= sizeof m_socket_addr) { + size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); } return *this; diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm index bbf70cd4c4b3..75624ef21f43 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/Host.mm @@ -74,6 +74,7 @@ #include "lldb/Utility/StructuredData.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Errno.h" #include "cfcpp/CFCBundle.h" #include "cfcpp/CFCMutableArray.h" @@ -1663,10 +1664,7 @@ HostThread Host::StartMonitoringChildProcess( int wait_pid = 0; bool cancel = false; bool exited = false; - do { - wait_pid = ::waitpid(pid, &status, 0); - } while (wait_pid < 0 && errno == EINTR); - + wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, 0); if (wait_pid >= 0) { int signal = 0; int exit_status = 0; diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 6b0f069c35a9..105ef0f23d46 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -245,11 +245,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, } else if ((addr = GetURLAddress(path, FILE_SCHEME))) { std::string addr_str = addr->str(); // file:///PATH - int fd = -1; - do { - fd = ::open(addr_str.c_str(), O_RDWR); - } while (fd == -1 && errno == EINTR); - + int fd = llvm::sys::RetryAfterSignal(-1, ::open, addr_str.c_str(), O_RDWR); if (fd == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); @@ -620,20 +616,17 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, if (select_helper.FDIsSetRead(pipe_fd)) { // There is an interrupt or exit command in the command pipe // Read the data from that pipe: - char buffer[1]; - - ssize_t bytes_read; - - do { - bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); + char c; - switch (buffer[0]) { + ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); + assert(bytes_read == 1); + (void)bytes_read; + switch (c) { case 'q': if (log) log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " "got data: %c from the command channel.", - static_cast<void *>(this), buffer[0]); + static_cast<void *>(this), c); return eConnectionStatusEndOfFile; case 'i': // Interrupt the current read diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp index d385b78e0ec4..5dbb3bb4ef7e 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp @@ -63,10 +63,10 @@ void AuxVector::ParseAuxv(DataExtractor &data) { if (!ParseAuxvEntry(data, entry, &offset, byte_size)) break; - if (entry.type == AT_NULL) + if (entry.type == AUXV_AT_NULL) break; - if (entry.type == AT_IGNORE) + if (entry.type == AUXV_AT_IGNORE) continue; m_auxv.push_back(entry); @@ -110,43 +110,43 @@ void AuxVector::DumpToLog(Log *log) const { const char *AuxVector::GetEntryName(EntryType type) { const char *name = "AT_???"; -#define ENTRY_NAME(_type) \ - _type: \ - name = #_type +#define ENTRY_NAME(_type) \ + _type: \ + name = #_type + 5 switch (type) { - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - case ENTRY_NAME(AT_PLATFORM); break; - case ENTRY_NAME(AT_HWCAP); break; - case ENTRY_NAME(AT_FPUCW); break; - case ENTRY_NAME(AT_DCACHEBSIZE); break; - case ENTRY_NAME(AT_ICACHEBSIZE); break; - case ENTRY_NAME(AT_UCACHEBSIZE); break; - case ENTRY_NAME(AT_IGNOREPPC); break; - case ENTRY_NAME(AT_SECURE); break; - case ENTRY_NAME(AT_BASE_PLATFORM); break; - case ENTRY_NAME(AT_RANDOM); break; - case ENTRY_NAME(AT_EXECFN); break; - case ENTRY_NAME(AT_SYSINFO); break; - case ENTRY_NAME(AT_SYSINFO_EHDR); break; - case ENTRY_NAME(AT_L1I_CACHESHAPE); break; - case ENTRY_NAME(AT_L1D_CACHESHAPE); break; - case ENTRY_NAME(AT_L2_CACHESHAPE); break; - case ENTRY_NAME(AT_L3_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_NULL); break; + case ENTRY_NAME(AUXV_AT_IGNORE); break; + case ENTRY_NAME(AUXV_AT_EXECFD); break; + case ENTRY_NAME(AUXV_AT_PHDR); break; + case ENTRY_NAME(AUXV_AT_PHENT); break; + case ENTRY_NAME(AUXV_AT_PHNUM); break; + case ENTRY_NAME(AUXV_AT_PAGESZ); break; + case ENTRY_NAME(AUXV_AT_BASE); break; + case ENTRY_NAME(AUXV_AT_FLAGS); break; + case ENTRY_NAME(AUXV_AT_ENTRY); break; + case ENTRY_NAME(AUXV_AT_NOTELF); break; + case ENTRY_NAME(AUXV_AT_UID); break; + case ENTRY_NAME(AUXV_AT_EUID); break; + case ENTRY_NAME(AUXV_AT_GID); break; + case ENTRY_NAME(AUXV_AT_EGID); break; + case ENTRY_NAME(AUXV_AT_CLKTCK); break; + case ENTRY_NAME(AUXV_AT_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_HWCAP); break; + case ENTRY_NAME(AUXV_AT_FPUCW); break; + case ENTRY_NAME(AUXV_AT_DCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_ICACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_UCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_IGNOREPPC); break; + case ENTRY_NAME(AUXV_AT_SECURE); break; + case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_RANDOM); break; + case ENTRY_NAME(AUXV_AT_EXECFN); break; + case ENTRY_NAME(AUXV_AT_SYSINFO); break; + case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break; + case ENTRY_NAME(AUXV_AT_L1I_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break; } #undef ENTRY_NAME diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h index 9c3e1b002a24..cf9da0808357 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h @@ -42,41 +42,42 @@ public: /// Constants describing the type of entry. /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information. + /// Added AUXV prefix to avoid potential conflicts with system-defined macros enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). - AT_PLATFORM = 15, ///< String identifying platform. - AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. - AT_FPUCW = 18, ///< Used FPU control word. - AT_DCACHEBSIZE = 19, ///< Data cache block size. - AT_ICACHEBSIZE = 20, ///< Instruction cache block size. - AT_UCACHEBSIZE = 21, ///< Unified cache block size. - AT_IGNOREPPC = 22, ///< Entry should be ignored. - AT_SECURE = 23, ///< Boolean, was exec setuid-like? - AT_BASE_PLATFORM = 24, ///< String identifying real platforms. - AT_RANDOM = 25, ///< Address of 16 random bytes. - AT_EXECFN = 31, ///< Filename of executable. - AT_SYSINFO = 32, ///< Pointer to the global system page used for system - ///calls and other nice things. - AT_SYSINFO_EHDR = 33, - AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. - AT_L1D_CACHESHAPE = 35, - AT_L2_CACHESHAPE = 36, - AT_L3_CACHESHAPE = 37, + AUXV_AT_NULL = 0, ///< End of auxv. + AUXV_AT_IGNORE = 1, ///< Ignore entry. + AUXV_AT_EXECFD = 2, ///< File descriptor of program. + AUXV_AT_PHDR = 3, ///< Program headers. + AUXV_AT_PHENT = 4, ///< Size of program header. + AUXV_AT_PHNUM = 5, ///< Number of program headers. + AUXV_AT_PAGESZ = 6, ///< Page size. + AUXV_AT_BASE = 7, ///< Interpreter base address. + AUXV_AT_FLAGS = 8, ///< Flags. + AUXV_AT_ENTRY = 9, ///< Program entry point. + AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF. + AUXV_AT_UID = 11, ///< UID. + AUXV_AT_EUID = 12, ///< Effective UID. + AUXV_AT_GID = 13, ///< GID. + AUXV_AT_EGID = 14, ///< Effective GID. + AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). + AUXV_AT_PLATFORM = 15, ///< String identifying platform. + AUXV_AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. + AUXV_AT_FPUCW = 18, ///< Used FPU control word. + AUXV_AT_DCACHEBSIZE = 19, ///< Data cache block size. + AUXV_AT_ICACHEBSIZE = 20, ///< Instruction cache block size. + AUXV_AT_UCACHEBSIZE = 21, ///< Unified cache block size. + AUXV_AT_IGNOREPPC = 22, ///< Entry should be ignored. + AUXV_AT_SECURE = 23, ///< Boolean, was exec setuid-like? + AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms. + AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes. + AUXV_AT_EXECFN = 31, ///< Filename of executable. + AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system + ///calls and other nice things. + AUXV_AT_SYSINFO_EHDR = 33, + AUXV_AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. + AUXV_AT_L1D_CACHESHAPE = 35, + AUXV_AT_L2_CACHESHAPE = 36, + AUXV_AT_L3_CACHESHAPE = 37, }; private: diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 0092535648bd..a7afeb6d68c3 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -576,7 +576,7 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { } void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() { - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR); if (I != m_auxv->end()) m_vdso_base = I->value; @@ -589,7 +589,7 @@ addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { if (m_auxv.get() == NULL) return LLDB_INVALID_ADDRESS; - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY); if (I == m_auxv->end()) return LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp index af242d786a5f..9a6e39be0bfd 100644 --- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp @@ -247,12 +247,16 @@ bool AddressSanitizerRuntime::NotifyBreakpointHit( AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime *>(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(); std::string description; if (report) { description = instance->FormatDescription(report); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp index 3c22b81df7a4..eb238419ab18 100644 --- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp @@ -141,7 +141,7 @@ MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { d->AddStringItem("class_name", className); d->AddStringItem("selector", selector); d->AddStringItem("description", - apiName + " must be called from main thread only"); + apiName + " must be used from main thread only"); d->AddIntegerItem("tid", thread_sp->GetIndexID()); d->AddItem("trace", trace_sp); return dict_sp; @@ -163,6 +163,9 @@ bool MainThreadCheckerRuntime::NotifyBreakpointHit( process_sp != context->exe_ctx_ref.GetProcessSP()) return false; + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index f60df0463346..cf9ba60c7b60 100644 --- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -803,6 +803,11 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( ThreadSanitizerRuntime *const instance = static_cast<ThreadSanitizerRuntime *>(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); std::string stop_reason_description; @@ -851,7 +856,6 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( all_addresses_are_same); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp index 023af84179aa..28c28e41ef44 100644 --- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp @@ -217,6 +217,9 @@ bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit( process_sp != context->exe_ctx_ref.GetProcessSP()) return false; + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp index 2ba005e02ad4..8f4997533212 100644 --- a/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/source/Plugins/Language/ObjC/Cocoa.cpp @@ -543,6 +543,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( } uint64_t value = 0; + bool success = false; switch (type_code) { case TypeCodes::sint8: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, @@ -550,6 +551,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint16: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, @@ -558,6 +560,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return false; NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint32: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, @@ -565,6 +568,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint64: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, @@ -572,6 +576,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); + success = true; break; case TypeCodes::f32: { @@ -582,6 +587,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( float flt_value = 0.0f; memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int)); NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); + success = true; break; } case TypeCodes::f64: @@ -593,6 +599,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( double dbl_value = 0.0; memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng)); NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); + success = true; break; } case TypeCodes::sint128: // internally, this is the same @@ -608,12 +615,11 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return false; llvm::APInt i128_value(128, words); NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage()); + success = true; break; } - default: - return false; } - return true; + return success; } } diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index d896a9f99e63..0f37da60d5d6 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -366,13 +366,17 @@ bool PlatformAndroid::GetRemoteOSVersion() { return m_major_os_version != 0; } -const char *PlatformAndroid::GetLibdlFunctionDeclarations() const { - return R"( +llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { + // Older platform versions have the dl function symbols mangled + if (GetSdkVersion() < 26) + return R"( extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); extern "C" int dlclose(void*) asm("__dl_dlclose"); extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(); } AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h index 8fb4cc71a69f..638dba973369 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/source/Plugins/Platform/Android/PlatformAndroid.h @@ -76,7 +76,7 @@ protected: Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override; - const char *GetLibdlFunctionDeclarations() const override; + llvm::StringRef GetLibdlFunctionDeclarations() override; private: AdbClient::SyncService *GetSyncService(Status &error); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index f4cf22ad7583..013c33def13b 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -884,7 +884,7 @@ void PlatformPOSIX::CalculateTrapHandlerSymbolNames() { Status PlatformPOSIX::EvaluateLibdlExpression( lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { DynamicLoader *loader = process->GetDynamicLoader(); if (loader) { Status error = loader->CanLoadImage(); @@ -944,7 +944,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, the_result; )", path); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -992,7 +992,7 @@ Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, StreamString expr; expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -1024,7 +1024,7 @@ lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url, error); } -const char *PlatformPOSIX::GetLibdlFunctionDeclarations() const { +llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() { return R"( extern "C" void* dlopen(const char*, int); extern "C" void* dlsym(void*, const char*); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 742702b07b88..ebc36c2461db 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -198,10 +198,10 @@ protected: lldb_private::Status EvaluateLibdlExpression(lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); - virtual const char *GetLibdlFunctionDeclarations() const; + virtual llvm::StringRef GetLibdlFunctionDeclarations(); private: DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 10dd14753914..a4f5f02dde62 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -746,15 +746,9 @@ ProcessMonitor::ProcessMonitor( if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the launch was a success. @@ -790,15 +784,9 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the attach was a success. diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 8e378802de9c..d988ee93a2bc 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -214,207 +214,122 @@ static Status EnsureFDFlags(int fd, int flags) { // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected<NativeProcessProtocolSP> +NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + MaybeLogLaunchInfo(launch_info); - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); } - // Create the NativeProcessLinux in launch mode. - native_process_sp.reset(new NativeProcessLinux()); - - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error<StringError>("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; - } + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); - launch_info.SetProcessID(native_process_sp->GetID()); + status = SetDefaultPtraceOpts(pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to set default ptrace options: {0}", status); + return status.ToError(); + } - return error; + std::shared_ptr<NativeProcessLinux> process_sp(new NativeProcessLinux( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); + process_sp->InitializeThreads({pid}); + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr<NativeProcessLinux> native_process_linux_sp( - new NativeProcessLinux()); + auto tids_or = NativeProcessLinux::Attach(pid); + if (!tids_or) + return tids_or.takeError(); - if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } - - native_process_linux_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; - - native_process_sp = native_process_linux_sp; - return error; + std::shared_ptr<NativeProcessLinux> process_sp( + new NativeProcessLinux(pid, -1, native_delegate, arch, mainloop)); + process_sp->InitializeThreads(*tids_or); + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessLinux::NativeProcessLinux() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(), - m_pending_notification_tid(LLDB_INVALID_THREAD_ID), - m_pt_proces_trace_id(LLDB_INVALID_UID) {} - -void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); +NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + Status status; m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); } -Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - MaybeLogLaunchInfo(launch_info); - - ::pid_t pid = - ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - - LLDB_LOG(log, "inferior started, now in stopped state"); - error = SetDefaultPtraceOpts(pid); - if (error.Fail()) { - LLDB_LOG(log, "failed to set default ptrace options: {0}", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - - // Release the master terminal descriptor and pass it off to the - // NativeProcessLinux instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } +void NativeProcessLinux::InitializeThreads(llvm::ArrayRef<::pid_t> tids) { + for (const auto &tid : tids) { + NativeThreadLinuxSP thread_sp = AddThread(tid); + assert(thread_sp && "AddThread() returned a nullptr thread"); + thread_sp->SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(*thread_sp); } - LLDB_LOG(log, "adding pid = {0}", pid); - ResolveProcessArchitecture(m_pid, m_arch); - NativeThreadLinuxSP thread_sp = AddThread(pid); - assert(thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - // Let our process instance know the thread has stopped. - SetCurrentThreadID(thread_sp->GetID()); - SetState(StateType::eStateStopped); + SetCurrentThreadID(tids[0]); + SetState(StateType::eStateStopped, false); - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; + // Proccess any signals we received before installing our handler + SigchldHandler(); } -::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Status &error) { +llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Status status; // Use a map to keep track of the threads which we have attached/need to // attach. Host::TidMap tids_to_attach; - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - while (Host::FindProcessThreads(pid, tids_to_attach)) { for (Host::TidMap::iterator it = tids_to_attach.begin(); it != tids_to_attach.end();) { @@ -423,48 +338,36 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PTRACE_ATTACH, tid); - if (error.Fail()) { + if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) { // No such thread. The thread may have exited. // More error handling may be needed. - if (error.GetError() == ESRCH) { + if (status.GetError() == ESRCH) { it = tids_to_attach.erase(it); continue; - } else - return -1; + } + return status.ToError(); } - int status; + int wpid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL); // Need to use __WALL otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(tid, NULL, __WALL)) < 0) { + if (wpid < 0) { // No such thread. The thread may have exited. // More error handling may be needed. if (errno == ESRCH) { it = tids_to_attach.erase(it); continue; - } else { - error.SetErrorToErrno(); - return -1; } + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); } - error = SetDefaultPtraceOpts(tid); - if (error.Fail()) - return -1; + if ((status = SetDefaultPtraceOpts(tid)).Fail()) + return status.ToError(); LLDB_LOG(log, "adding tid = {0}", tid); it->second = true; - - // Create the thread, mark it as stopped. - NativeThreadLinuxSP thread_sp(AddThread(static_cast<lldb::tid_t>(tid))); - assert(thread_sp && "AddThread() returned a nullptr"); - - // This will notify this is a new thread and tell the system it is - // stopped. - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - SetCurrentThreadID(thread_sp->GetID()); } // move the loop forward @@ -472,17 +375,16 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, } } - if (tids_to_attach.size() > 0) { - m_pid = pid; - // Let our process instance know the thread has stopped. - SetState(StateType::eStateStopped); - } else { - error.SetErrorToGenericError(); - error.SetErrorString("No such process."); - return -1; - } + size_t tid_count = tids_to_attach.size(); + if (tid_count == 0) + return llvm::make_error<StringError>("No such process", + llvm::inconvertibleErrorCode()); - return pid; + std::vector<::pid_t> tids; + tids.reserve(tid_count); + for (const auto &p : tids_to_attach) + tids.push_back(p.first); + return std::move(tids); } Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) { @@ -662,14 +564,11 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { // The thread is not tracked yet, let's wait for it to appear. int status = -1; - ::pid_t wait_pid; - do { - LLDB_LOG(log, - "received thread creation event for tid {0}. tid not tracked " - "yet, waiting for thread to appear...", - tid); - wait_pid = waitpid(tid, &status, __WALL); - } while (wait_pid == -1 && errno == EINTR); + LLDB_LOG(log, + "received thread creation event for tid {0}. tid not tracked " + "yet, waiting for thread to appear...", + tid); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL); // Since we are waiting on a specific tid, this must be the creation event. // But let's do some checks just in case. if (wait_pid != tid) { @@ -897,11 +796,9 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, break; default: - LLDB_LOG( - log, - "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", - info.si_code, GetID(), thread.GetID()); - llvm_unreachable("Unexpected SIGTRAP code!"); + LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}", + info.si_code, GetID(), thread.GetID()); + MonitorSignal(info, thread, false); break; } } @@ -2363,15 +2260,13 @@ void NativeProcessLinux::SigchldHandler() { // Process all pending waitpid notifications. while (true) { int status = -1; - ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, + __WALL | __WNOTHREAD | WNOHANG); if (wait_pid == 0) break; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - continue; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error); break; diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index 6bf093f6a39a..9584713d3654 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -39,15 +39,18 @@ namespace process_linux { /// /// Changes in the inferior process state are broadcasted. class NativeProcessLinux : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- @@ -144,10 +147,10 @@ private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; - lldb::tid_t m_pending_notification_tid; + lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID; // List of thread ids stepping with a breakpoint with the address of // the relevan breakpoint @@ -156,19 +159,15 @@ private: // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessLinux(); - - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - - /// Attaches to an existing process. Forms the - /// implementation of Process::DoAttach - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); + NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); - ::pid_t Attach(lldb::pid_t pid, Status &error); + // Returns a list of process threads that we have attached to. + static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid); static Status SetDefaultPtraceOpts(const lldb::pid_t); - static void *MonitorThread(void *baton); + void InitializeThreads(llvm::ArrayRef<::pid_t> tids); void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status); @@ -280,7 +279,7 @@ private: // same process user id. llvm::DenseSet<lldb::tid_t> m_pt_traced_thread_group; - lldb::user_id_t m_pt_proces_trace_id; + lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID; TraceOptions m_pt_process_trace_config; }; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index c3b58f16256a..1a5b304ac697 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -680,7 +680,7 @@ Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { return error; lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0, tempRefCount = 0; + uint32_t tempControl = 0; for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) { @@ -858,7 +858,7 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( RegisterValue &value) { Status error; if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; @@ -905,7 +905,7 @@ Status NativeRegisterContextLinux_arm64::DoWriteRegisterValue( Status error; ::pid_t tid = m_thread.GetID(); if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 59dc9e9f7d45..e44e03b46b5c 100755 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -646,13 +646,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( Status error; data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - error = ReadGPR(); if (error.Fail()) return error; @@ -662,13 +655,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( return error; uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) @@ -741,10 +727,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( } if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + error.SetErrorStringWithFormatv( + "data_sp contained mismatched data size, expected {0}, actual {1}", + REG_CONTEXT_SIZE, data_sp->GetByteSize()); return error; } diff --git a/source/Plugins/Process/Linux/ProcessorTrace.cpp b/source/Plugins/Process/Linux/ProcessorTrace.cpp index 7043d50256e6..505c526ab70d 100644 --- a/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ b/source/Plugins/Process/Linux/ProcessorTrace.cpp @@ -46,13 +46,11 @@ Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config) { - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - LLDB_LOG(log, "{0}", config.getThreadID()); - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Status error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); LLDB_LOG(log, "called thread id {0}", tid); uint64_t page_size = getpagesize(); @@ -61,12 +59,11 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, uint64_t numpages = static_cast<uint64_t>( llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size)); - numpages = std::max(1ul, numpages); + numpages = std::max<uint64_t>(1, numpages); bufsize = page_size * numpages; numpages = static_cast<uint64_t>( llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size)); - numpages = std::max(0ul, numpages); metabufsize = page_size * numpages; perf_event_attr attr; @@ -117,7 +114,7 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, return error; } - m_fd = std::move(std::unique_ptr<int, file_close>(new int(fd), file_close())); + m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close()); errno = 0; auto base = @@ -129,9 +126,9 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, return error; } - m_mmap_meta = std::move(std::unique_ptr<perf_event_mmap_page, munmap_delete>( + m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>( reinterpret_cast<perf_event_mmap_page *>(base), - munmap_delete(metabufsize + page_size))); + munmap_delete(metabufsize + page_size)); m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size; m_mmap_meta->aux_size = bufsize; @@ -145,10 +142,10 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, error.SetErrorString("Trace buffer allocation failed"); return error; } - m_mmap_aux = std::move(std::unique_ptr<uint8_t, munmap_delete>( - reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize))); -#endif + m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>( + reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize)); return error; +#endif } llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetDataBuffer() { @@ -251,14 +248,14 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, Status error; if (tid == LLDB_INVALID_THREAD_ID) { error.SetErrorString("thread not specified"); - return std::move(error.ToError()); + return error.ToError(); } ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor); error = pt_monitor_up->StartTrace(pid, tid, config); if (error.Fail()) - return std::move(error.ToError()); + return error.ToError(); pt_monitor_up->SetThreadID(tid); @@ -274,13 +271,11 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, Status ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Status error; uint64_t head = m_mmap_meta->aux_head; LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head); @@ -306,12 +301,12 @@ ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, Status ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - uint64_t bytes_remaining = buffer.size(); - Status error; #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + uint64_t bytes_remaining = buffer.size(); + Status error; uint64_t head = m_mmap_meta->data_head; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index a4d775860a65..b9ef02efa65d 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -21,6 +21,7 @@ #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Target/Process.h" +#include "llvm/Support/Errno.h" // System includes - They have to be included after framework includes because // they define some @@ -63,81 +64,101 @@ static Status EnsureFDFlags(int fd, int flags) { // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected<NativeProcessProtocolSP> +NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); + } - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error<StringError>("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - // Create the NativeProcessNetBSD in launch mode. - native_process_sp.reset(new NativeProcessNetBSD()); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); - error = std::static_pointer_cast<NativeProcessNetBSD>(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + std::shared_ptr<NativeProcessNetBSD> process_sp(new NativeProcessNetBSD( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; - } + status = process_sp->ReinitializeThreads(); + if (status.Fail()) + return status.ToError(); - launch_info.SetProcessID(native_process_sp->GetID()); + for (const auto &thread_sp : process_sp->m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + SIGSTOP); + } + process_sp->SetState(StateType::eStateStopped); - return error; + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected<NativeProcessProtocolSP> NativeProcessNetBSD::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr<NativeProcessNetBSD> native_process_netbsd_sp( - new NativeProcessNetBSD()); + std::shared_ptr<NativeProcessNetBSD> process_sp( + new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop)); - if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } - - native_process_netbsd_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; + status = process_sp->Attach(); + if (!status.Success()) + return status.ToError(); - native_process_sp = native_process_netbsd_sp; - return error; + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessNetBSD::NativeProcessNetBSD() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {} +NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, + MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + + Status status; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); +} // Handles all waitpid events from the inferior process. void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { @@ -709,126 +730,17 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, return Status(); } -Status NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - ::pid_t pid = ProcessLauncherPosixFork() - .LaunchProcess(launch_info, error) - .GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - - LLDB_LOG(log, "inferior started, now in stopped state"); - - // Release the master terminal descriptor and pass it off to the - // NativeProcessNetBSD instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - } - - LLDB_LOG(log, "adding pid = {0}", pid); - - ResolveProcessArchitecture(m_pid, m_arch); - - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return error; - } - - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } - - /* Set process stopped */ - SetState(StateType::eStateStopped); - - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; -} - -void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); - - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); -} - void NativeProcessNetBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. int status; - ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG); + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); if (wait_pid == 0) return; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - return; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); } @@ -880,33 +792,23 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { return thread_sp; } -::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) { - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - +Status NativeProcessNetBSD::Attach() { // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PT_ATTACH, pid); - if (error.Fail()) - return -1; + Status status = PtraceWrapper(PT_ATTACH, m_pid); + if (status.Fail()) + return status; - int status; + int wstatus; // Need to use WALLSIG otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(pid, NULL, WALLSIG)) < 0) - return -1; - - m_pid = pid; + if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0) + return Status(errno, eErrorTypePOSIX); /* Initialize threads */ - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return -1; - } + status = ReinitializeThreads(); + if (status.Fail()) + return status; for (const auto &thread_sp : m_threads) { static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( @@ -915,8 +817,7 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); - - return pid; + return Status(); } Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf, diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 7a1303faea68..34b892f1fc88 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -31,15 +31,18 @@ namespace process_netbsd { /// /// Changes in the inferior process state are broadcasted. class NativeProcessNetBSD : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- @@ -107,21 +110,19 @@ protected: private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessNetBSD(); + NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); bool HasThreadNoLock(lldb::tid_t thread_id); NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); - void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); void MonitorSIGSTOP(lldb::pid_t pid); @@ -133,8 +134,7 @@ private: Status PopulateMemoryRegionCache(); void SigchldHandler(); - ::pid_t Attach(lldb::pid_t pid, Status &error); - + Status Attach(); Status ReinitializeThreads(); }; diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index 3d008f42499d..5e51feef1d3f 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -7,14 +7,6 @@ set(LLDB_PLUGINS lldbPluginPlatformMacOSX ) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") - list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") - list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) -endif() - add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 33aed7a43c4a..e6fd386b903b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -86,6 +86,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), m_supports_QPassSignals(eLazyBoolCalculate), + m_supports_error_string_reply(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -596,6 +597,21 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { return m_supports_jThreadExtendedInfo; } +void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { + if (m_supports_error_string_reply == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + // We try to enable error strings in remote packets + // but if we fail, we just work in the older way. + m_supports_error_string_reply = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_error_string_reply = eLazyBoolYes; + } + } + } +} + bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; @@ -3181,8 +3197,8 @@ GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsNormalResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); - LLDB_LOG(log, "Target does not support Tracing"); + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support Tracing , error {0}", error); } else { ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); } @@ -3219,7 +3235,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsOKResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); LLDB_LOG(log, "stop tracing failed"); } } else { @@ -3234,6 +3250,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, Status GDBRemoteCommunicationClient::SendGetDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceBufferRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); @@ -3242,6 +3259,7 @@ Status GDBRemoteCommunicationClient::SendGetDataPacket( Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceMetaRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); @@ -3308,7 +3326,7 @@ GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, custom_params_sp)); } } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); } } else { LLDB_LOG(log, "failed to send packet"); @@ -3344,7 +3362,7 @@ Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( size_t filled_size = response.GetHexBytesAvail(buffer); buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size); } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); buffer = buffer.slice(buffer.size()); } } else { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index a38110faaec6..712d85eed082 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -340,6 +340,8 @@ public: bool GetQXferAuxvReadSupported(); + void EnableErrorStringInPacket(); + bool GetQXferLibrariesReadSupported(); bool GetQXferLibrariesSVR4ReadSupported(); @@ -549,6 +551,7 @@ protected: LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; LazyBool m_supports_QPassSignals; + LazyBool m_supports_error_string_reply; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index dac675ee9432..4be92b79fd1a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -20,6 +20,7 @@ // Project includes #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; @@ -27,7 +28,12 @@ using namespace lldb_private::process_gdb_remote; GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {} + : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { + RegisterPacketHandler( + StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, + [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, + bool &quit) { return this->Handle_QErrorStringEnable(packet); }); +} GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} @@ -100,6 +106,24 @@ GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { + if (m_send_error_strings) { + lldb_private::StreamString packet; + packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError())); + packet.PutCStringAsRawHex8(error.AsCString()); + return SendPacketNoLock(packet.GetString()); + } else + return SendErrorResponse(error.GetError()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_QErrorStringEnable( + StringExtractorGDBRemote &packet) { + m_send_error_strings = true; + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 6eb25f8b9f98..a35352480040 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -57,6 +57,13 @@ protected: bool m_exit_now; // use in asynchronous handling to indicate process should // exit. + bool m_send_error_strings; // If the client enables this then + // we will send error strings as well. + + PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet); + + PacketResult SendErrorResponse(const Status &error); + PacketResult SendUnimplementedResponse(const char *packet); PacketResult SendErrorResponse(uint8_t error); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index de2400c51ba3..f53db502be93 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -1046,14 +1046,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (success) { m_process_launch_error = LaunchProcess(); - if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { + if (m_process_launch_error.Success()) return SendOKResponse(); - } else { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", - __FUNCTION__, m_process_launch_error.AsCString()); - } + LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); } return SendErrorResponse(8); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 7523260c13e4..a7fe4ee3b147 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -73,15 +73,11 @@ enum GDBRemoteServerError { // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - MainLoop &mainloop) + MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID), - m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(), - m_debugged_process_sp(), m_stdio_communication("process.stdio"), - m_inferior_prev_state(StateType::eStateInvalid), - m_saved_registers_map(), m_next_saved_registers_id(1), - m_handshake_completed(false) { + m_mainloop(mainloop), m_process_factory(process_factory), + m_stdio_communication("process.stdio") { RegisterPacketHandlers(); } @@ -241,19 +237,20 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { const bool default_to_use_pty = true; m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); - Status error; { std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); assert(!m_debugged_process_sp && "lldb-server creating debugged " "process but one already exists"); - error = NativeProcessProtocol::Launch(m_process_launch_info, *this, - m_mainloop, m_debugged_process_sp); - } - - if (!error.Success()) { - fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, - m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); - return error; + auto process_or = + m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv( + "failed to launch executable `{0}`: {1}", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); + return status; + } + m_debugged_process_sp = *process_or; } // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol @@ -279,9 +276,9 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -298,14 +295,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { printf("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments().GetArgumentAtIndex(0), - m_process_launch_info.GetProcessID()); + m_debugged_process_sp->GetID()); - return error; + return Status(); } Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { - Status error; - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, @@ -321,13 +316,14 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { pid, m_debugged_process_sp->GetID()); // Try to attach. - error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, - m_debugged_process_sp); - if (!error.Success()) { - fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s", - __FUNCTION__, pid, error.AsCString()); - return error; + auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid, + status); + return status; } + m_debugged_process_sp = *process_or; // Setup stdout/stderr mapping from inferior. auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); @@ -336,9 +332,9 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -347,8 +343,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { } printf("Attached to process %" PRIu64 "...\n", pid); - - return error; + return Status(); } void GDBRemoteCommunicationServerLLGS::InitializeDelegate( @@ -1128,7 +1123,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( uid = m_debugged_process_sp->StartTrace(options, error); LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote response; response.Printf("%" PRIx64, uid); @@ -1165,7 +1160,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( Status error = m_debugged_process_sp->StopTrace(uid, tid); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); return SendOKResponse(); } @@ -1208,7 +1203,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( Status error = m_debugged_process_sp->GetTraceConfig(uid, options); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote escaped_response; StructuredData::Dictionary json_packet; @@ -1284,7 +1279,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); for (auto i : buf) response.PutHex8(i); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index a7d7850d454f..b065642d4aed 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -39,7 +39,9 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS( + MainLoop &mainloop, + const NativeProcessProtocol::Factory &process_factory); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. @@ -108,20 +110,21 @@ public: protected: MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; - lldb::tid_t m_current_tid; - lldb::tid_t m_continue_tid; + const NativeProcessProtocol::Factory &m_process_factory; + lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID; std::recursive_mutex m_debugged_process_mutex; NativeProcessProtocolSP m_debugged_process_sp; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state; + lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up; std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; - uint32_t m_next_saved_registers_id; - bool m_handshake_completed : 1; + uint32_t m_next_saved_registers_id = 1; + bool m_handshake_completed = false; PacketResult SendONotification(const char *buffer, uint32_t len); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 042c96111bb3..8a66f3865ebc 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1031,6 +1031,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { m_gdb_comm.GetHostInfo(); m_gdb_comm.GetVContSupported('c'); m_gdb_comm.GetVAttachOrWaitSupported(); + m_gdb_comm.EnableErrorStringInPacket(); // Ask the remote server for the default thread id if (GetTarget().GetNonStopModeEnabled()) diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index b7fbd7347d08..6c39690268c6 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1857,14 +1857,12 @@ StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings( return StructuredData::DictionarySP(); PythonObject reply_pyobj; - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)g_swig_plugin_get(generic->GetValue(), - setting_name, target_sp)); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + TargetSP target_sp(target->shared_from_this()); + reply_pyobj.Reset(PyRefType::Owned, + (PyObject *)g_swig_plugin_get(generic->GetValue(), + setting_name, target_sp)); PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); return py_dict.CreateStructuredDictionary(); diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 9d79a411faad..aa15063ac0dc 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -604,9 +604,10 @@ uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) { } bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p, - int &length) { + int &length, + uint32_t buffer_remaining_bytes) { - const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize(); + uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize()); llvm::SmallVector<uint8_t, 32> opcode_data; opcode_data.resize(max_op_byte_size); @@ -698,8 +699,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( bool row_updated = false; // The UnwindPlan::Row 'row' has been updated m_cur_insn = data + current_func_text_offset; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction break; } @@ -1002,8 +1004,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( while (offset < size) { m_cur_insn = data + offset; int insn_len; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction. break; } @@ -1214,8 +1217,9 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction( int scratch; m_cur_insn = data + offset; - if (!instruction_length(m_cur_insn, insn_len) || - insn_len > kMaxInstructionByteSize || insn_len == 0) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len > kMaxInstructionByteSize + || insn_len == 0) { // An error parsing the instruction, i.e. probably data/garbage - stop // scanning break; diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h index 2e7875966cb6..97441d362973 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h @@ -113,7 +113,7 @@ private: bool ret_pattern_p(); uint32_t extract_4(uint8_t *b); - bool instruction_length(uint8_t *insn, int &length); + bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes); bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno); diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 3473a9e96689..8e50c0106a48 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -19,8 +19,18 @@ StringExtractorGDBRemote::GetResponseType() const { switch (m_packet[0]) { case 'E': - if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2])) - return eError; + if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) { + if (m_packet.size() == 3) + return eError; + llvm::StringRef packet_ref(m_packet); + if (packet_ref[3] == ';') { + auto err_string = packet_ref.substr(4); + for (auto e : err_string) + if (!isxdigit(e)) + return eResponse; + return eError; + } + } break; case 'O': @@ -86,6 +96,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_QEnvironment; if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded; + if (PACKET_STARTS_WITH("QEnableErrorStrings")) + return eServerPacketType_QEnableErrorStrings; break; case 'P': @@ -438,8 +450,8 @@ bool StringExtractorGDBRemote::IsNormalResponse() const { } bool StringExtractorGDBRemote::IsErrorResponse() const { - return GetResponseType() == eError && m_packet.size() == 3 && - isxdigit(m_packet[1]) && isxdigit(m_packet[2]); + return GetResponseType() == eError && isxdigit(m_packet[1]) && + isxdigit(m_packet[2]); } uint8_t StringExtractorGDBRemote::GetError() { @@ -450,6 +462,23 @@ uint8_t StringExtractorGDBRemote::GetError() { return 0; } +lldb_private::Status StringExtractorGDBRemote::GetStatus() { + lldb_private::Status error; + if (GetResponseType() == eError) { + SetFilePos(1); + uint8_t errc = GetHexU8(255); + error.SetError(errc, lldb::eErrorTypeGeneric); + + error.SetErrorStringWithFormat("Error %u", errc); + std::string error_messg; + if (GetChar() == ';') { + GetHexByteString(error_messg); + error.SetErrorString(error_messg); + } + } + return error; +} + size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) { // Just get the data bytes in the string as // GDBRemoteCommunication::CheckForPacket() diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h index 473cab04f800..f4ed642a706e 100644 --- a/source/Utility/StringExtractorGDBRemote.h +++ b/source/Utility/StringExtractorGDBRemote.h @@ -10,6 +10,7 @@ #ifndef utility_StringExtractorGDBRemote_h_ #define utility_StringExtractorGDBRemote_h_ +#include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" #include "llvm/ADT/StringRef.h" // for StringRef @@ -72,6 +73,7 @@ public: eServerPacketType_qGetWorkingDir, eServerPacketType_qFileLoadAddress, eServerPacketType_QEnvironment, + eServerPacketType_QEnableErrorStrings, eServerPacketType_QLaunchArch, eServerPacketType_QSetDisableASLR, eServerPacketType_QSetDetachOnError, @@ -190,6 +192,8 @@ public: // digits. Otherwise the error encoded in XX is returned. uint8_t GetError(); + lldb_private::Status GetStatus(); + size_t GetEscapedBinaryData(std::string &str); protected: |