summaryrefslogtreecommitdiff
path: root/source/Host/common
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/common')
-rw-r--r--source/Host/common/Host.cpp4
-rw-r--r--source/Host/common/HostInfoBase.cpp31
-rw-r--r--source/Host/common/MainLoop.cpp37
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp121
-rw-r--r--source/Host/common/NativeRegisterContext.cpp22
-rw-r--r--source/Host/common/NativeThreadProtocol.cpp26
-rw-r--r--source/Host/common/PseudoTerminal.cpp2
-rw-r--r--source/Host/common/Socket.cpp2
-rw-r--r--source/Host/common/Symbols.cpp48
-rw-r--r--source/Host/common/TaskPool.cpp120
-rw-r--r--source/Host/common/XML.cpp2
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 &reg_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 &reg_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->ReadRegister(reg_info, reg_value);
+ return register_context.ReadRegister(reg_info, reg_value);
;
}
Status NativeThreadProtocol::WriteRegister(uint32_t reg,
const RegisterValue &reg_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;