diff options
Diffstat (limited to 'source/Host/common')
| -rw-r--r-- | source/Host/common/Host.cpp | 4 | ||||
| -rw-r--r-- | source/Host/common/HostInfoBase.cpp | 31 | ||||
| -rw-r--r-- | source/Host/common/MainLoop.cpp | 37 | ||||
| -rw-r--r-- | source/Host/common/NativeProcessProtocol.cpp | 121 | ||||
| -rw-r--r-- | source/Host/common/NativeRegisterContext.cpp | 22 | ||||
| -rw-r--r-- | source/Host/common/NativeThreadProtocol.cpp | 26 | ||||
| -rw-r--r-- | source/Host/common/PseudoTerminal.cpp | 2 | ||||
| -rw-r--r-- | source/Host/common/Socket.cpp | 2 | ||||
| -rw-r--r-- | source/Host/common/Symbols.cpp | 48 | ||||
| -rw-r--r-- | source/Host/common/TaskPool.cpp | 120 | ||||
| -rw-r--r-- | source/Host/common/XML.cpp | 2 |
11 files changed, 262 insertions, 153 deletions
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 8248aa3c5118..97581185ad9e 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -48,10 +48,6 @@ // C++ Includes #include <csignal> -// Other libraries and framework includes -// Project includes - -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostProcess.h" diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index a6c9e91a98e8..aff887f9f1d2 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -9,11 +9,11 @@ #include "lldb/Host/Config.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostInfoBase.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -103,6 +103,14 @@ const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { : g_fields->m_host_arch_32; } +llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { + return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) + .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) + .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) + .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) + .Default(llvm::None); +} + bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { file_spec.Clear(); @@ -251,6 +259,27 @@ bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { return true; } +ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { + if (triple.empty()) + return ArchSpec(); + llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); + if (!ArchSpec::ContainsOnlyArch(normalized_triple)) + return ArchSpec(triple); + + if (auto kind = HostInfo::ParseArchitectureKind(triple)) + return HostInfo::GetArchitecture(*kind); + + llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); + + if (normalized_triple.getVendorName().empty()) + normalized_triple.setVendor(host_triple.getVendor()); + if (normalized_triple.getOSName().empty()) + normalized_triple.setOS(host_triple.getOS()); + if (normalized_triple.getEnvironmentName().empty()) + normalized_triple.setEnvironment(host_triple.getEnvironment()); + return ArchSpec(normalized_triple); +} + bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { // To get paths related to LLDB we get the path to the executable that // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index d0e0d00a3151..6cbb5a842562 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -28,6 +28,8 @@ #include <sys/event.h> #elif defined(LLVM_ON_WIN32) #include <winsock2.h> +#elif defined(__ANDROID__) +#include <sys/syscall.h> #else #include <poll.h> #endif @@ -38,10 +40,6 @@ #define POLL poll #endif -#ifdef __ANDROID__ -#define FORCE_PSELECT -#endif - #if SIGNAL_POLLING_UNSUPPORTED #ifdef LLVM_ON_WIN32 typedef int sigset_t; @@ -86,7 +84,7 @@ private: int num_events = -1; #else -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ fd_set read_fd_set; #else std::vector<struct pollfd> read_fds; @@ -134,7 +132,7 @@ void MainLoop::RunImpl::ProcessEvents() { } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { -#ifndef FORCE_PSELECT +#ifndef __ANDROID__ read_fds.reserve(loop.m_read_fds.size()); #endif } @@ -154,8 +152,14 @@ sigset_t MainLoop::RunImpl::get_sigmask() { #endif } -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ Status MainLoop::RunImpl::Poll() { + // ppoll(2) is not supported on older all android versions. Also, older + // versions android (API <= 19) implemented pselect in a non-atomic way, as a + // combination of pthread_sigmask and select. This is not sufficient for us, + // as we rely on the atomicity to correctly implement signal polling, so we + // call the underlying syscall ourselves. + FD_ZERO(&read_fd_set); int nfds = 0; for (const auto &fd : loop.m_read_fds) { @@ -163,8 +167,19 @@ Status MainLoop::RunImpl::Poll() { nfds = std::max(nfds, fd.first + 1); } - sigset_t sigmask = get_sigmask(); - if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && + union { + sigset_t set; + uint64_t pad; + } kernel_sigset; + memset(&kernel_sigset, 0, sizeof(kernel_sigset)); + kernel_sigset.set = get_sigmask(); + + struct { + void *sigset_ptr; + size_t sigset_len; + } extra_data = {&kernel_sigset, sizeof(kernel_sigset)}; + if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr, + &extra_data) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); @@ -193,7 +208,7 @@ Status MainLoop::RunImpl::Poll() { #endif void MainLoop::RunImpl::ProcessEvents() { -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ // 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 @@ -206,7 +221,7 @@ void MainLoop::RunImpl::ProcessEvents() { for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { - if ((fd.revents & POLLIN) == 0) + if ((fd.revents & (POLLIN | POLLHUP)) == 0) continue; IOObject::WaitableHandle handle = fd.fd; #endif diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index b5b6e9d8b923..1fcb11b8b6f5 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -8,8 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/common/NativeProcessProtocol.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" @@ -90,23 +88,23 @@ bool NativeProcessProtocol::SetExitStatus(WaitStatus status, return true; } -NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { +NativeThreadProtocol *NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); if (idx < m_threads.size()) - return m_threads[idx]; - return NativeThreadProtocolSP(); + return m_threads[idx].get(); + return nullptr; } -NativeThreadProtocolSP +NativeThreadProtocol * NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { - for (auto thread_sp : m_threads) { - if (thread_sp->GetID() == tid) - return thread_sp; + for (const auto &thread : m_threads) { + if (thread->GetID() == tid) + return thread.get(); } - return NativeThreadProtocolSP(); + return nullptr; } -NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { +NativeThreadProtocol *NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); return GetThreadByIDUnlocked(tid); } @@ -116,14 +114,6 @@ bool NativeProcessProtocol::IsAlive() const { m_state != eStateInvalid && m_state != eStateUnloaded; } -bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { - ArchSpec process_arch; - if (!GetArchitecture(process_arch)) - return false; - byte_order = process_arch.GetByteOrder(); - return true; -} - const NativeWatchpointList::WatchpointMap & NativeProcessProtocol::GetWatchpointMap() const { return m_watchpoint_list.GetWatchpointMap(); @@ -134,27 +124,16 @@ NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // get any thread - NativeThreadProtocolSP thread_sp( + NativeThreadProtocol *thread( const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); - if (!thread_sp) { - if (log) - log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " - "grab a NativeRegisterContext!", - __FUNCTION__); + if (!thread) { + LLDB_LOG(log, "failed to find a thread to grab a NativeRegisterContext!"); return llvm::None; } - NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); - if (!reg_ctx_sp) { - if (log) - log->Warning("NativeProcessProtocol::%s (): failed to get a " - "RegisterContextNativeProcess from the first thread!", - __FUNCTION__); - return llvm::None; - } - - return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), - reg_ctx_sp->NumSupportedHardwareWatchpoints()); + NativeRegisterContext ®_ctx = thread->GetRegisterContext(); + return std::make_pair(reg_ctx.NumSupportedHardwareBreakpoints(), + reg_ctx.NumSupportedHardwareWatchpoints()); } Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -175,7 +154,7 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, // for. If one of the thread watchpoint setting operations fails, // back off and remove the watchpoint for all the threads that // were successfully set so we get back to a consistent state. - std::vector<NativeThreadProtocolSP> watchpoint_established_threads; + std::vector<NativeThreadProtocol *> watchpoint_established_threads; // Tell each thread to set a watchpoint. In the event that // hardware watchpoints are requested but the SetWatchpoint fails, @@ -184,40 +163,33 @@ Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, // watchpoints available, some of the threads will fail to set // hardware watchpoints while software ones may be available. std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); Status thread_error = - thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); + thread->SetWatchpoint(addr, size, watch_flags, hardware); if (thread_error.Fail() && hardware) { // Try software watchpoints since we failed on hardware watchpoint setting // and we may have just run out of hardware watchpoints. - thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); - if (thread_error.Success()) { - if (log) - log->Warning( - "hardware watchpoint requested but software watchpoint set"); - } + thread_error = thread->SetWatchpoint(addr, size, watch_flags, false); + if (thread_error.Success()) + LLDB_LOG(log, + "hardware watchpoint requested but software watchpoint set"); } if (thread_error.Success()) { // Remember that we set this watchpoint successfully in // case we need to clear it later. - watchpoint_established_threads.push_back(thread_sp); + watchpoint_established_threads.push_back(thread.get()); } else { // Unset the watchpoint for each thread we successfully // set so that we get back to a consistent state of "not // set" for the watchpoint. for (auto unwatch_thread_sp : watchpoint_established_threads) { Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); - if (remove_error.Fail() && log) { - log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " - "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), - remove_error.AsCString()); - } + if (remove_error.Fail()) + LLDB_LOG(log, "RemoveWatchpoint failed for pid={0}, tid={1}: {2}", + GetID(), unwatch_thread_sp->GetID(), remove_error); } return thread_error; @@ -233,12 +205,10 @@ Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { Status overall_error; std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); - const Status thread_error = thread_sp->RemoveWatchpoint(addr); + const Status thread_error = thread->RemoveWatchpoint(addr); if (thread_error.Fail()) { // Keep track of the first thread error if any threads // fail. We want to try to remove the watchpoint from @@ -277,20 +247,18 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, // set this hardware breakpoint. If any of the current process threads fails // to set this hardware breakpoint then roll back and remove this breakpoint // for all the threads that had already set it successfully. - std::vector<NativeThreadProtocolSP> breakpoint_established_threads; + std::vector<NativeThreadProtocol *> breakpoint_established_threads; // Request to set a hardware breakpoint for each of current process threads. std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); - Status thread_error = thread_sp->SetHardwareBreakpoint(addr, size); + Status thread_error = thread->SetHardwareBreakpoint(addr, size); if (thread_error.Success()) { // Remember that we set this breakpoint successfully in // case we need to clear it later. - breakpoint_established_threads.push_back(thread_sp); + breakpoint_established_threads.push_back(thread.get()); } else { // Unset the breakpoint for each thread we successfully // set so that we get back to a consistent state of "not @@ -298,12 +266,10 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, for (auto rollback_thread_sp : breakpoint_established_threads) { Status remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); - if (remove_error.Fail() && log) { - log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" - " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", - __FUNCTION__, GetID(), rollback_thread_sp->GetID(), - remove_error.AsCString()); - } + if (remove_error.Fail()) + LLDB_LOG(log, + "RemoveHardwareBreakpoint failed for pid={0}, tid={1}: {2}", + GetID(), rollback_thread_sp->GetID(), remove_error); } return thread_error; @@ -324,12 +290,9 @@ Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { Status error; std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not have a NULL thread!"); - if (!thread_sp) - continue; - - error = thread_sp->RemoveHardwareBreakpoint(addr); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not have a NULL thread!"); + error = thread->RemoveHardwareBreakpoint(addr); } // Also remove from hardware breakpoint map of current process. diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 629b0247422d..60eaebdc94cd 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -19,9 +19,8 @@ using namespace lldb; using namespace lldb_private; -NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread, - uint32_t concrete_frame_idx) - : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx) {} +NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) + : m_thread(thread) {} //---------------------------------------------------------------------- // Destructor @@ -368,13 +367,8 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory( // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are assuming // they are the same. - lldb::ByteOrder byte_order; - if (process.GetByteOrder(byte_order)) { - error.SetErrorString("NativeProcessProtocol::GetByteOrder () failed"); - return error; - } - - reg_value.SetFromMemoryData(reg_info, src, src_len, byte_order, error); + reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(), + error); return error; } @@ -393,12 +387,8 @@ Status NativeRegisterContext::WriteRegisterValueToMemory( // order of the memory data doesn't match the process. For now we are // assuming // they are the same. - lldb::ByteOrder byte_order; - if (!process.GetByteOrder(byte_order)) - return Status("NativeProcessProtocol::GetByteOrder () failed"); - - const size_t bytes_copied = - reg_value.GetAsMemoryData(reg_info, dst, dst_len, byte_order, error); + const size_t bytes_copied = reg_value.GetAsMemoryData( + reg_info, dst, dst_len, process.GetByteOrder(), error); if (error.Success()) { if (bytes_copied == 0) { diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 54ac96dd3c6f..3f3915e006da 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -22,43 +22,33 @@ NativeThreadProtocol::NativeThreadProtocol(NativeProcessProtocol &process, Status NativeThreadProtocol::ReadRegister(uint32_t reg, RegisterValue ®_value) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); + NativeRegisterContext ®ister_context = GetRegisterContext(); const RegisterInfo *const reg_info = - register_context_sp->GetRegisterInfoAtIndex(reg); + register_context.GetRegisterInfoAtIndex(reg); if (!reg_info) return Status("no register info for reg num %" PRIu32, reg); - return register_context_sp->ReadRegister(reg_info, reg_value); + return register_context.ReadRegister(reg_info, reg_value); ; } Status NativeThreadProtocol::WriteRegister(uint32_t reg, const RegisterValue ®_value) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); + NativeRegisterContext& register_context = GetRegisterContext(); const RegisterInfo *const reg_info = - register_context_sp->GetRegisterInfoAtIndex(reg); + register_context.GetRegisterInfoAtIndex(reg); if (!reg_info) return Status("no register info for reg num %" PRIu32, reg); - return register_context_sp->WriteRegister(reg_info, reg_value); + return register_context.WriteRegister(reg_info, reg_value); } Status NativeThreadProtocol::SaveAllRegisters(lldb::DataBufferSP &data_sp) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); - return register_context_sp->WriteAllRegisterValues(data_sp); + return GetRegisterContext().WriteAllRegisterValues(data_sp); } Status NativeThreadProtocol::RestoreAllRegisters(lldb::DataBufferSP &data_sp) { - NativeRegisterContextSP register_context_sp = GetRegisterContext(); - if (!register_context_sp) - return Status("no register context"); - return register_context_sp->ReadAllRegisterValues(data_sp); + return GetRegisterContext().ReadAllRegisterValues(data_sp); } diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp index 58c32e4a1c4b..9657cb6523dc 100644 --- a/source/Host/common/PseudoTerminal.cpp +++ b/source/Host/common/PseudoTerminal.cpp @@ -24,7 +24,7 @@ int posix_openpt(int flags); #endif -using namespace lldb_utility; +using namespace lldb_private; //---------------------------------------------------------------------- // PseudoTerminal constructor diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 5490e9b30bda..4c23e4eb560c 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -450,7 +450,7 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, close(fd); } return fd; -#elif defined(SOCK_CLOEXEC) +#elif defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) int flags = 0; if (!child_processes_inherit) { flags |= SOCK_CLOEXEC; diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index e7bdf084d385..3f70fdc4bf95 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Symbols.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" @@ -109,25 +109,25 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, // Remove the binary name from the FileSpec parent_dirs.RemoveLastPathComponent(); - // Add a ".dSYM" name to each directory component of the path, stripping - // off components. e.g. we may have a binary like + // Add a ".dSYM" name to each directory component of the path, + // stripping off components. e.g. we may have a binary like // /S/L/F/Foundation.framework/Versions/A/Foundation // and // /S/L/F/Foundation.framework.dSYM // // so we'll need to start with /S/L/F/Foundation.framework/Versions/A, // add the .dSYM part to the "A", and if that doesn't exist, strip off - // the "A" and try it again with "Versions", etc., until we find a dSYM - // bundle or we've stripped off enough path components that there's no - // need to continue. + // the "A" and try it again with "Versions", etc., until we find a + // dSYM bundle or we've stripped off enough path components that + // there's no need to continue. for (int i = 0; i < 4; i++) { - // Does this part of the path have a "." character - could it be a bundle's - // top level directory? + // Does this part of the path have a "." character - could it be a + // bundle's top level directory? const char *fn = parent_dirs.GetFilename().AsCString(); if (fn == nullptr) - break; - if (::strchr (fn, '.') != nullptr) { + break; + if (::strchr(fn, '.') != nullptr) { dsym_fspec = parent_dirs; dsym_fspec.RemoveLastPathComponent(); @@ -140,16 +140,17 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, dsym_fspec.AppendPathComponent("Contents"); dsym_fspec.AppendPathComponent("Resources"); dsym_fspec.AppendPathComponent("DWARF"); - dsym_fspec.AppendPathComponent(exec_fspec->GetFilename().AsCString()); + dsym_fspec.AppendPathComponent( + exec_fspec->GetFilename().AsCString()); if (dsym_fspec.Exists() && - FileAtPathContainsArchAndUUID( - dsym_fspec, module_spec.GetArchitecturePtr(), - module_spec.GetUUIDPtr())) { - if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; + FileAtPathContainsArchAndUUID( + dsym_fspec, module_spec.GetArchitecturePtr(), + module_spec.GetUUIDPtr())) { + if (log) { + log->Printf("dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; } } parent_dirs.RemoveLastPathComponent(); @@ -231,7 +232,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { #ifndef LLVM_ON_WIN32 #if defined(__NetBSD__) // Add /usr/libdata/debug directory. - debug_file_search_paths.AppendIfUnique(FileSpec("/usr/libdata/debug", true)); + debug_file_search_paths.AppendIfUnique( + FileSpec("/usr/libdata/debug", true)); #else // Add /usr/lib/debug directory. debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); @@ -285,7 +287,11 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { if (num_specs == 1) { ModuleSpec mspec; if (specs.GetModuleSpecAtIndex(0, mspec)) { - if (mspec.GetUUID() == module_uuid) + // Skip the uuids check if module_uuid is invalid. + // For example, this happens for *.dwp files since + // at the moment llvm-dwp doesn't output build ids, + // nor does binutils dwp. + if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) return file_spec; } } diff --git a/source/Host/common/TaskPool.cpp b/source/Host/common/TaskPool.cpp new file mode 100644 index 000000000000..156a07942998 --- /dev/null +++ b/source/Host/common/TaskPool.cpp @@ -0,0 +1,120 @@ +//===--------------------- TaskPool.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/TaskPool.h" +#include "lldb/Host/ThreadLauncher.h" + +#include <cstdint> // for uint32_t +#include <queue> // for queue +#include <thread> // for thread + +namespace lldb_private { + +namespace { +class TaskPoolImpl { +public: + static TaskPoolImpl &GetInstance(); + + void AddTask(std::function<void()> &&task_fn); + +private: + TaskPoolImpl(); + + static lldb::thread_result_t WorkerPtr(void *pool); + + static void Worker(TaskPoolImpl *pool); + + std::queue<std::function<void()>> m_tasks; + std::mutex m_tasks_mutex; + uint32_t m_thread_count; +}; + +} // end of anonymous namespace + +TaskPoolImpl &TaskPoolImpl::GetInstance() { + static TaskPoolImpl g_task_pool_impl; + return g_task_pool_impl; +} + +void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) { + TaskPoolImpl::GetInstance().AddTask(std::move(task_fn)); +} + +TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {} + +unsigned GetHardwareConcurrencyHint() { + // std::thread::hardware_concurrency may return 0 + // if the value is not well defined or not computable. + static const unsigned g_hardware_concurrency = + std::max(1u, std::thread::hardware_concurrency()); + return g_hardware_concurrency; +} + +void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { + const size_t min_stack_size = 8 * 1024 * 1024; + + std::unique_lock<std::mutex> lock(m_tasks_mutex); + m_tasks.emplace(std::move(task_fn)); + if (m_thread_count < GetHardwareConcurrencyHint()) { + m_thread_count++; + // Note that this detach call needs to happen with the m_tasks_mutex held. + // This prevents the thread + // from exiting prematurely and triggering a linux libc bug + // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). + lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, + this, nullptr, min_stack_size) + .Release(); + } +} + +lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { + Worker((TaskPoolImpl *)pool); + return 0; +} + +void TaskPoolImpl::Worker(TaskPoolImpl *pool) { + while (true) { + std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); + if (pool->m_tasks.empty()) { + pool->m_thread_count--; + break; + } + + std::function<void()> f = std::move(pool->m_tasks.front()); + pool->m_tasks.pop(); + lock.unlock(); + + f(); + } +} + +void TaskMapOverInt(size_t begin, size_t end, + const llvm::function_ref<void(size_t)> &func) { + const size_t num_workers = std::min<size_t>(end, GetHardwareConcurrencyHint()); + std::atomic<size_t> idx{begin}; + + auto wrapper = [&idx, end, &func]() { + while (true) { + size_t i = idx.fetch_add(1); + if (i >= end) + break; + func(i); + } + }; + + std::vector<std::future<void>> futures; + futures.reserve(num_workers); + for (size_t i = 0; i < num_workers; i++) + futures.push_back(TaskPool::AddTask(wrapper)); + for (size_t i = 0; i < num_workers; i++) + futures[i].wait(); +} + +} // namespace lldb_private + diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index c637d938dffa..c3169bd6e08d 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -339,7 +339,7 @@ XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const { #if defined(LIBXML2_DEFINED) ForEachChildElementWithName( - name, [&result_node, name](const XMLNode &node) -> bool { + name, [&result_node](const XMLNode &node) -> bool { result_node = node; // Stop iterating, we found the node we wanted return false; |
