summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Host/HostInfoBase.h4
-rw-r--r--lldb/include/lldb/Host/posix/HostInfoPosix.h3
-rw-r--r--lldb/include/lldb/Target/Platform.h69
-rw-r--r--lldb/include/lldb/Target/Process.h8
-rw-r--r--lldb/include/lldb/Target/RemoteAwarePlatform.h3
-rw-r--r--lldb/include/lldb/Utility/UserIDResolver.h56
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.cpp14
-rw-r--r--lldb/source/Host/posix/HostInfoPosix.cpp61
-rw-r--r--lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.h4
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp25
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h9
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp12
-rw-r--r--lldb/source/Target/Platform.cpp36
-rw-r--r--lldb/source/Target/Process.cpp82
-rw-r--r--lldb/source/Target/RemoteAwarePlatform.cpp26
-rw-r--r--lldb/source/Utility/CMakeLists.txt1
-rw-r--r--lldb/source/Utility/UserIDResolver.cpp44
-rw-r--r--lldb/unittests/Target/CMakeLists.txt1
-rw-r--r--lldb/unittests/Target/ProcessInstanceInfoTest.cpp75
-rw-r--r--lldb/unittests/Utility/CMakeLists.txt1
-rw-r--r--lldb/unittests/Utility/UserIDResolverTest.cpp47
21 files changed, 338 insertions, 243 deletions
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index 6a5ad207d02..f2370f1d00a 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -11,8 +11,8 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/UserIDResolver.h"
#include "lldb/lldb-enumerations.h"
-
#include "llvm/ADT/StringRef.h"
#include <stdint.h>
@@ -99,6 +99,8 @@ public:
//---------------------------------------------------------------------------
static ArchSpec GetAugmentedArchSpec(llvm::StringRef triple);
+ static UserIDResolver &GetUserIDResolver();
+
protected:
static bool ComputeSharedLibraryDirectory(FileSpec &file_spec);
static bool ComputeSupportExeDirectory(FileSpec &file_spec);
diff --git a/lldb/include/lldb/Host/posix/HostInfoPosix.h b/lldb/include/lldb/Host/posix/HostInfoPosix.h
index af2ad649643..2ae1415e030 100644
--- a/lldb/include/lldb/Host/posix/HostInfoPosix.h
+++ b/lldb/include/lldb/Host/posix/HostInfoPosix.h
@@ -20,8 +20,7 @@ class HostInfoPosix : public HostInfoBase {
public:
static size_t GetPageSize();
static bool GetHostname(std::string &s);
- static const char *LookupUserName(uint32_t uid, std::string &user_name);
- static const char *LookupGroupName(uint32_t gid, std::string &group_name);
+ static UserIDResolver &GetUserIDResolver();
static uint32_t GetUserID();
static uint32_t GetGroupID();
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index f09a1a99ee4..f581ac3f9c7 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -23,6 +23,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Timeout.h"
+#include "lldb/Utility/UserIDResolver.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-public.h"
#include "llvm/Support/VersionTuple.h"
@@ -276,9 +277,7 @@ public:
virtual bool SetRemoteWorkingDirectory(const FileSpec &working_dir);
- virtual const char *GetUserName(uint32_t uid);
-
- virtual const char *GetGroupName(uint32_t gid);
+ virtual UserIDResolver &GetUserIDResolver() = 0;
//------------------------------------------------------------------
/// Locate a file for a platform.
@@ -916,8 +915,6 @@ protected:
// Mutex for modifying Platform data structures that should only be used for
// non-reentrant code
std::mutex m_mutex;
- IDToNameMap m_uid_map;
- IDToNameMap m_gid_map;
size_t m_max_uid_name_len;
size_t m_max_gid_name_len;
bool m_supports_rsync;
@@ -946,68 +943,6 @@ protected:
//------------------------------------------------------------------
virtual void CalculateTrapHandlerSymbolNames() = 0;
- const char *GetCachedUserName(uint32_t uid) {
- std::lock_guard<std::mutex> guard(m_mutex);
- // return the empty string if our string is NULL so we can tell when things
- // were in the negative cached (didn't find a valid user name, don't keep
- // trying)
- const auto pos = m_uid_map.find(uid);
- return ((pos != m_uid_map.end()) ? pos->second.AsCString("") : nullptr);
- }
-
- const char *SetCachedUserName(uint32_t uid, const char *name,
- size_t name_len) {
- std::lock_guard<std::mutex> guard(m_mutex);
- ConstString const_name(name);
- m_uid_map[uid] = const_name;
- if (m_max_uid_name_len < name_len)
- m_max_uid_name_len = name_len;
- // Const strings lives forever in our const string pool, so we can return
- // the const char *
- return const_name.GetCString();
- }
-
- void SetUserNameNotFound(uint32_t uid) {
- std::lock_guard<std::mutex> guard(m_mutex);
- m_uid_map[uid] = ConstString();
- }
-
- void ClearCachedUserNames() {
- std::lock_guard<std::mutex> guard(m_mutex);
- m_uid_map.clear();
- }
-
- const char *GetCachedGroupName(uint32_t gid) {
- std::lock_guard<std::mutex> guard(m_mutex);
- // return the empty string if our string is NULL so we can tell when things
- // were in the negative cached (didn't find a valid group name, don't keep
- // trying)
- const auto pos = m_gid_map.find(gid);
- return ((pos != m_gid_map.end()) ? pos->second.AsCString("") : nullptr);
- }
-
- const char *SetCachedGroupName(uint32_t gid, const char *name,
- size_t name_len) {
- std::lock_guard<std::mutex> guard(m_mutex);
- ConstString const_name(name);
- m_gid_map[gid] = const_name;
- if (m_max_gid_name_len < name_len)
- m_max_gid_name_len = name_len;
- // Const strings lives forever in our const string pool, so we can return
- // the const char *
- return const_name.GetCString();
- }
-
- void SetGroupNameNotFound(uint32_t gid) {
- std::lock_guard<std::mutex> guard(m_mutex);
- m_gid_map[gid] = ConstString();
- }
-
- void ClearCachedGroupNames() {
- std::lock_guard<std::mutex> guard(m_mutex);
- m_gid_map.clear();
- }
-
Status GetCachedExecutable(ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
Platform &remote_platform);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index f0b034daa56..54ee084f480 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -46,6 +46,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/TraceOptions.h"
+#include "lldb/Utility/UserIDResolver.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/ArrayRef.h"
@@ -150,12 +151,11 @@ public:
return m_parent_pid != LLDB_INVALID_PROCESS_ID;
}
- void Dump(Stream &s, Platform *platform) const;
+ void Dump(Stream &s, UserIDResolver &resolver) const;
- static void DumpTableHeader(Stream &s, Platform *platform, bool show_args,
- bool verbose);
+ static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
- void DumpAsTableRow(Stream &s, Platform *platform, bool show_args,
+ void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args,
bool verbose) const;
protected:
diff --git a/lldb/include/lldb/Target/RemoteAwarePlatform.h b/lldb/include/lldb/Target/RemoteAwarePlatform.h
index ca2a2deb58d..524332f948a 100644
--- a/lldb/include/lldb/Target/RemoteAwarePlatform.h
+++ b/lldb/include/lldb/Target/RemoteAwarePlatform.h
@@ -70,8 +70,7 @@ public:
const Timeout<std::micro> &timeout) override;
const char *GetHostname() override;
- const char *GetUserName(uint32_t uid) override;
- const char *GetGroupName(uint32_t gid) override;
+ UserIDResolver &GetUserIDResolver() override;
lldb_private::Environment GetEnvironment() override;
bool IsConnected() const override;
diff --git a/lldb/include/lldb/Utility/UserIDResolver.h b/lldb/include/lldb/Utility/UserIDResolver.h
new file mode 100644
index 00000000000..bca82a11b66
--- /dev/null
+++ b/lldb/include/lldb/Utility/UserIDResolver.h
@@ -0,0 +1,56 @@
+//===-- UserIDResolver.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_USERIDRESOLVER_H
+#define LLDB_UTILITY_USERIDRESOLVER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <mutex>
+
+namespace lldb_private {
+
+/// An abstract interface for things that know how to map numeric user/group IDs
+/// into names. It caches the resolved names to avoid repeating expensive
+/// queries. The cache is internally protected by a mutex, so concurrent queries
+/// are safe.
+class UserIDResolver {
+public:
+ typedef uint32_t id_t;
+ virtual ~UserIDResolver(); // anchor
+
+ llvm::Optional<llvm::StringRef> GetUserName(id_t uid) {
+ return Get(uid, m_uid_cache, &UserIDResolver::DoGetUserName);
+ }
+ llvm::Optional<llvm::StringRef> GetGroupName(id_t gid) {
+ return Get(gid, m_gid_cache, &UserIDResolver::DoGetGroupName);
+ }
+
+ /// Returns a resolver which returns a failure value for each query. Useful as
+ /// a fallback value for the case when we know all lookups will fail.
+ static UserIDResolver &GetNoopResolver();
+
+protected:
+ virtual llvm::Optional<std::string> DoGetUserName(id_t uid) = 0;
+ virtual llvm::Optional<std::string> DoGetGroupName(id_t gid) = 0;
+
+private:
+ using Map = llvm::DenseMap<id_t, llvm::Optional<std::string>>;
+
+ llvm::Optional<llvm::StringRef>
+ Get(id_t id, Map &cache,
+ llvm::Optional<std::string> (UserIDResolver::*do_get)(id_t));
+
+ std::mutex m_mutex;
+ Map m_uid_cache;
+ Map m_gid_cache;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef LLDB_HOST_USERIDRESOLVER_H
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index c4aee060d7d..8bb88f965cf 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -1151,10 +1151,9 @@ protected:
if (pid != LLDB_INVALID_PROCESS_ID) {
ProcessInstanceInfo proc_info;
if (platform_sp->GetProcessInfo(pid, proc_info)) {
- ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
- m_options.show_args,
+ ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
m_options.verbose);
- proc_info.DumpAsTableRow(ostrm, platform_sp.get(),
+ proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
m_options.show_args, m_options.verbose);
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
@@ -1212,13 +1211,12 @@ protected:
result.AppendMessageWithFormat(" whose name %s \"%s\"",
match_desc, match_name);
result.AppendMessageWithFormat("\n");
- ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
- m_options.show_args,
+ ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
m_options.verbose);
for (uint32_t i = 0; i < matches; ++i) {
proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
- ostrm, platform_sp.get(), m_options.show_args,
- m_options.verbose);
+ ostrm, platform_sp->GetUserIDResolver(),
+ m_options.show_args, m_options.verbose);
}
}
}
@@ -1453,7 +1451,7 @@ protected:
if (platform_sp->GetProcessInfo(pid, proc_info)) {
ostrm.Printf("Process information for process %" PRIu64 ":\n",
pid);
- proc_info.Dump(ostrm, platform_sp.get());
+ proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
} else {
ostrm.Printf("error: no process information is available for "
"process %" PRIu64 "\n",
diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp
index 76f9cdbc4ed..864d6c9a252 100644
--- a/lldb/source/Host/posix/HostInfoPosix.cpp
+++ b/lldb/source/Host/posix/HostInfoPosix.cpp
@@ -48,40 +48,38 @@ bool HostInfoPosix::GetHostname(std::string &s) {
#define USE_GETPWUID
#endif
-#ifdef USE_GETPWUID
-static std::mutex s_getpwuid_lock;
-#endif
-
-const char *HostInfoPosix::LookupUserName(uint32_t uid,
- std::string &user_name) {
+namespace {
+class PosixUserIDResolver : public UserIDResolver {
+protected:
+ llvm::Optional<std::string> DoGetUserName(id_t uid) override;
+ llvm::Optional<std::string> DoGetGroupName(id_t gid) override;
+};
+} // namespace
+
+llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) {
#ifdef USE_GETPWUID
// getpwuid_r is missing from android-9
- // make getpwuid thread safe with a mutex
- std::lock_guard<std::mutex> lock(s_getpwuid_lock);
+ // UserIDResolver provides some thread safety by making sure noone calls this
+ // function concurrently, but using getpwuid is ultimately not thread-safe as
+ // we don't know who else might be calling it.
struct passwd *user_info_ptr = ::getpwuid(uid);
- if (user_info_ptr) {
- user_name.assign(user_info_ptr->pw_name);
- return user_name.c_str();
- }
+ if (user_info_ptr)
+ return std::string(user_info_ptr->pw_name);
#else
struct passwd user_info;
struct passwd *user_info_ptr = &user_info;
char user_buffer[PATH_MAX];
size_t user_buffer_size = sizeof(user_buffer);
if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size,
- &user_info_ptr) == 0) {
- if (user_info_ptr) {
- user_name.assign(user_info_ptr->pw_name);
- return user_name.c_str();
- }
+ &user_info_ptr) == 0 &&
+ user_info_ptr) {
+ return std::string(user_info_ptr->pw_name);
}
#endif
- user_name.clear();
- return nullptr;
+ return llvm::None;
}
-const char *HostInfoPosix::LookupGroupName(uint32_t gid,
- std::string &group_name) {
+llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) {
#ifndef __ANDROID__
char group_buffer[PATH_MAX];
size_t group_buffer_size = sizeof(group_buffer);
@@ -90,24 +88,25 @@ const char *HostInfoPosix::LookupGroupName(uint32_t gid,
// Try the threadsafe version first
if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size,
&group_info_ptr) == 0) {
- if (group_info_ptr) {
- group_name.assign(group_info_ptr->gr_name);
- return group_name.c_str();
- }
+ if (group_info_ptr)
+ return std::string(group_info_ptr->gr_name);
} else {
// The threadsafe version isn't currently working for me on darwin, but the
// non-threadsafe version is, so I am calling it below.
group_info_ptr = ::getgrgid(gid);
- if (group_info_ptr) {
- group_name.assign(group_info_ptr->gr_name);
- return group_name.c_str();
- }
+ if (group_info_ptr)
+ return std::string(group_info_ptr->gr_name);
}
- group_name.clear();
#else
assert(false && "getgrgid_r() not supported on Android");
#endif
- return NULL;
+ return llvm::None;
+}
+
+static llvm::ManagedStatic<PosixUserIDResolver> g_user_id_resolver;
+
+UserIDResolver &HostInfoPosix::GetUserIDResolver() {
+ return *g_user_id_resolver;
}
uint32_t HostInfoPosix::GetUserID() { return getuid(); }
diff --git a/lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.h b/lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.h
index 2d395925bb1..880c3ae7057 100644
--- a/lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.h
+++ b/lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.h
@@ -62,6 +62,10 @@ public:
void CalculateTrapHandlerSymbolNames() override;
+ UserIDResolver &GetUserIDResolver() override {
+ return UserIDResolver::GetNoopResolver();
+ }
+
protected:
lldb::PlatformSP m_remote_platform_sp;
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index cb971b02dcb..4ced723b0b2 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -340,29 +340,20 @@ const char *PlatformRemoteGDBServer::GetHostname() {
return m_name.c_str();
}
-const char *PlatformRemoteGDBServer::GetUserName(uint32_t uid) {
- // Try and get a cache user name first
- const char *cached_user_name = Platform::GetUserName(uid);
- if (cached_user_name)
- return cached_user_name;
+llvm::Optional<std::string>
+PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) {
std::string name;
if (m_gdb_client.GetUserName(uid, name))
- return SetCachedUserName(uid, name.c_str(), name.size());
-
- SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets
- return NULL;
+ return std::move(name);
+ return llvm::None;
}
-const char *PlatformRemoteGDBServer::GetGroupName(uint32_t gid) {
- const char *cached_group_name = Platform::GetGroupName(gid);
- if (cached_group_name)
- return cached_group_name;
+llvm::Optional<std::string>
+PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) {
std::string name;
if (m_gdb_client.GetGroupName(gid, name))
- return SetCachedGroupName(gid, name.c_str(), name.size());
-
- SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets
- return NULL;
+ return std::move(name);
+ return llvm::None;
}
uint32_t PlatformRemoteGDBServer::FindProcesses(
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index d7a5aa5537c..d67cfc2f5da 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -19,7 +19,7 @@
namespace lldb_private {
namespace platform_gdb_server {
-class PlatformRemoteGDBServer : public Platform {
+class PlatformRemoteGDBServer : public Platform, private UserIDResolver {
public:
static void Initialize();
@@ -100,9 +100,7 @@ public:
// name if connected.
const char *GetHostname() override;
- const char *GetUserName(uint32_t uid) override;
-
- const char *GetGroupName(uint32_t gid) override;
+ UserIDResolver &GetUserIDResolver() override { return *this; }
bool IsConnected() const override;
@@ -195,6 +193,9 @@ private:
const std::string &platform_hostname,
uint16_t port, const char *socket_name);
+ llvm::Optional<std::string> DoGetUserName(UserIDResolver::id_t uid) override;
+ llvm::Optional<std::string> DoGetGroupName(UserIDResolver::id_t uid) override;
+
DISALLOW_COPY_AND_ASSIGN(PlatformRemoteGDBServer);
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index c7a4127d9d4..5bc0c25c587 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -436,10 +436,10 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName(
packet.SetFilePos(::strlen("qUserName:"));
uint32_t uid = packet.GetU32(UINT32_MAX);
if (uid != UINT32_MAX) {
- std::string name;
- if (HostInfo::LookupUserName(uid, name)) {
+ if (llvm::Optional<llvm::StringRef> name =
+ HostInfo::GetUserIDResolver().GetUserName(uid)) {
StreamString response;
- response.PutStringAsRawHex8(name);
+ response.PutStringAsRawHex8(*name);
return SendPacketNoLock(response.GetString());
}
}
@@ -457,10 +457,10 @@ GDBRemoteCommunicationServerCommon::Handle_qGroupName(
packet.SetFilePos(::strlen("qGroupName:"));
uint32_t gid = packet.GetU32(UINT32_MAX);
if (gid != UINT32_MAX) {
- std::string name;
- if (HostInfo::LookupGroupName(gid, name)) {
+ if (llvm::Optional<llvm::StringRef> name =
+ HostInfo::GetUserIDResolver().GetGroupName(gid)) {
StreamString response;
- response.PutStringAsRawHex8(name);
+ response.PutStringAsRawHex8(*name);
return SendPacketNoLock(response.GetString());
}
}
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index a93913b25c8..b57c3523e72 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -384,10 +384,10 @@ Platform::Platform(bool is_host)
: m_is_host(is_host), m_os_version_set_while_connected(false),
m_system_arch_set_while_connected(false), m_sdk_sysroot(), m_sdk_build(),
m_working_dir(), m_remote_url(), m_name(), m_system_arch(), m_mutex(),
- m_uid_map(), m_gid_map(), m_max_uid_name_len(0), m_max_gid_name_len(0),
- m_supports_rsync(false), m_rsync_opts(), m_rsync_prefix(),
- m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false),
- m_trap_handlers(), m_calculated_trap_handlers(false),
+ m_max_uid_name_len(0), m_max_gid_name_len(0), m_supports_rsync(false),
+ m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
+ m_ignores_remote_hostname(false), m_trap_handlers(),
+ m_calculated_trap_handlers(false),
m_module_cache(llvm::make_unique<ModuleCache>()) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
if (log)
@@ -834,34 +834,6 @@ bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
return true;
}
-const char *Platform::GetUserName(uint32_t uid) {
-#if !defined(LLDB_DISABLE_POSIX)
- const char *user_name = GetCachedUserName(uid);
- if (user_name)
- return user_name;
- if (IsHost()) {
- std::string name;
- if (HostInfo::LookupUserName(uid, name))
- return SetCachedUserName(uid, name.c_str(), name.size());
- }
-#endif
- return nullptr;
-}
-
-const char *Platform::GetGroupName(uint32_t gid) {
-#if !defined(LLDB_DISABLE_POSIX)
- const char *group_name = GetCachedGroupName(gid);
- if (group_name)
- return group_name;
- if (IsHost()) {
- std::string name;
- if (HostInfo::LookupGroupName(gid, name))
- return SetCachedGroupName(gid, name.c_str(), name.size());
- }
-#endif
- return nullptr;
-}
-
bool Platform::SetOSVersion(llvm::VersionTuple version) {
if (IsHost()) {
// We don't need anyone setting the OS version for the host platform, we
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 0e8b314917e..2723b698517 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -278,8 +278,7 @@ bool ProcessProperties::GetStopOnExec() const {
nullptr, idx, g_properties[idx].default_uint_value != 0);
}
-void ProcessInstanceInfo::Dump(Stream &s, Platform *platform) const {
- const char *cstr;
+void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
if (m_pid != LLDB_INVALID_PROCESS_ID)
s.Printf(" pid = %" PRIu64 "\n", m_pid);
@@ -311,26 +310,26 @@ void ProcessInstanceInfo::Dump(Stream &s, Platform *platform) const {
s.EOL();
}
- if (m_uid != UINT32_MAX) {
- cstr = platform->GetUserName(m_uid);
- s.Printf(" uid = %-5u (%s)\n", m_uid, cstr ? cstr : "");
+ if (UserIDIsValid()) {
+ s.Format(" uid = {0,-5} ({1})\n", GetUserID(),
+ resolver.GetUserName(GetUserID()).getValueOr(""));
}
- if (m_gid != UINT32_MAX) {
- cstr = platform->GetGroupName(m_gid);
- s.Printf(" gid = %-5u (%s)\n", m_gid, cstr ? cstr : "");
+ if (GroupIDIsValid()) {
+ s.Format(" gid = {0,-5} ({1})\n", GetGroupID(),
+ resolver.GetGroupName(GetGroupID()).getValueOr(""));
}
- if (m_euid != UINT32_MAX) {
- cstr = platform->GetUserName(m_euid);
- s.Printf(" euid = %-5u (%s)\n", m_euid, cstr ? cstr : "");
+ if (EffectiveUserIDIsValid()) {
+ s.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(),
+ resolver.GetUserName(GetEffectiveUserID()).getValueOr(""));
}
- if (m_egid != UINT32_MAX) {
- cstr = platform->GetGroupName(m_egid);
- s.Printf(" egid = %-5u (%s)\n", m_egid, cstr ? cstr : "");
+ if (EffectiveGroupIDIsValid()) {
+ s.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(),
+ resolver.GetGroupName(GetEffectiveGroupID()).getValueOr(""));
}
}
-void ProcessInstanceInfo::DumpTableHeader(Stream &s, Platform *platform,
- bool show_args, bool verbose) {
+void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args,
+ bool verbose) {
const char *label;
if (show_args || verbose)
label = "ARGUMENTS";
@@ -350,49 +349,33 @@ void ProcessInstanceInfo::DumpTableHeader(Stream &s, Platform *platform,
}
}
-void ProcessInstanceInfo::DumpAsTableRow(Stream &s, Platform *platform,
+void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver,
bool show_args, bool verbose) const {
if (m_pid != LLDB_INVALID_PROCESS_ID) {
- const char *cstr;
s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);
StreamString arch_strm;
if (m_arch.IsValid())
m_arch.DumpTriple(arch_strm);
- if (verbose) {
- cstr = platform->GetUserName(m_uid);
- if (cstr &&
- cstr[0]) // Watch for empty string that indicates lookup failed
- s.Printf("%-10s ", cstr);
- else
- s.Printf("%-10u ", m_uid);
-
- cstr = platform->GetGroupName(m_gid);
- if (cstr &&
- cstr[0]) // Watch for empty string that indicates lookup failed
- s.Printf("%-10s ", cstr);
- else
- s.Printf("%-10u ", m_gid);
-
- cstr = platform->GetUserName(m_euid);
- if (cstr &&
- cstr[0]) // Watch for empty string that indicates lookup failed
- s.Printf("%-10s ", cstr);
- else
- s.Printf("%-10u ", m_euid);
-
- cstr = platform->GetGroupName(m_egid);
- if (cstr &&
- cstr[0]) // Watch for empty string that indicates lookup failed
- s.Printf("%-10s ", cstr);
+ auto print = [&](UserIDResolver::id_t id,
+ llvm::Optional<llvm::StringRef> (UserIDResolver::*get)(
+ UserIDResolver::id_t id)) {
+ if (auto name = (resolver.*get)(id))
+ s.Format("{0,-10} ", *name);
else
- s.Printf("%-10u ", m_egid);
+ s.Format("{0,-10} ", id);
+ };
+ if (verbose) {
+ print(m_uid, &UserIDResolver::GetUserName);
+ print(m_gid, &UserIDResolver::GetGroupName);
+ print(m_euid, &UserIDResolver::GetUserName);
+ print(m_egid, &UserIDResolver::GetGroupName);
s.Printf("%-24s ", arch_strm.GetData());
} else {
- s.Printf("%-10s %-24s ", platform->GetUserName(m_euid),
- arch_strm.GetData());
+ print(m_euid, &UserIDResolver::GetUserName);
+ s.Printf(" %-24s ", arch_strm.GetData());
}
if (verbose || show_args) {
@@ -3057,11 +3040,10 @@ Status Process::Attach(ProcessAttachInfo &attach_info) {
process_name, sizeof(process_name));
if (num_matches > 1) {
StreamString s;
- ProcessInstanceInfo::DumpTableHeader(s, platform_sp.get(), true,
- false);
+ ProcessInstanceInfo::DumpTableHeader(s, true, false);
for (size_t i = 0; i < num_matches; i++) {
process_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
- s, platform_sp.get(), true, false);
+ s, platform_sp->GetUserIDResolver(), true, false);
}
error.SetErrorStringWithFormat(
"more than one process named %s:\n%s", process_name,
diff --git a/lldb/source/Target/RemoteAwarePlatform.cpp b/lldb/source/Target/RemoteAwarePlatform.cpp
index 04cb6cedccf..1704e1533e9 100644
--- a/lldb/source/Target/RemoteAwarePlatform.cpp
+++ b/lldb/source/Target/RemoteAwarePlatform.cpp
@@ -10,6 +10,7 @@
#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
using namespace lldb_private;
@@ -204,25 +205,12 @@ const char *RemoteAwarePlatform::GetHostname() {
return nullptr;
}
-const char *RemoteAwarePlatform::GetUserName(uint32_t uid) {
- // Check the cache in Platform in case we have already looked this uid up
- const char *user_name = Platform::GetUserName(uid);
- if (user_name)
- return user_name;
-
- if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->GetUserName(uid);
- return nullptr;
-}
-
-const char *RemoteAwarePlatform::GetGroupName(uint32_t gid) {
- const char *group_name = Platform::GetGroupName(gid);
- if (group_name)
- return group_name;
-
- if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->GetGroupName(gid);
- return nullptr;
+UserIDResolver &RemoteAwarePlatform::GetUserIDResolver() {
+ if (IsHost())
+ return HostInfo::GetUserIDResolver();
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetUserIDResolver();
+ return UserIDResolver::GetNoopResolver();
}
Environment RemoteAwarePlatform::GetEnvironment() {
diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt
index 03f965465da..34b6fb27e64 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -85,6 +85,7 @@ add_lldb_library(lldbUtility
TildeExpressionResolver.cpp
Timer.cpp
UserID.cpp
+ UserIDResolver.cpp
UriParser.cpp
UUID.cpp
VASprintf.cpp
diff --git a/lldb/source/Utility/UserIDResolver.cpp b/lldb/source/Utility/UserIDResolver.cpp
new file mode 100644
index 00000000000..8aac6f948cd
--- /dev/null
+++ b/lldb/source/Utility/UserIDResolver.cpp
@@ -0,0 +1,44 @@
+//===-- UserIDResolver.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/UserIDResolver.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace lldb_private;
+
+UserIDResolver::~UserIDResolver() = default;
+
+llvm::Optional<llvm::StringRef> UserIDResolver::Get(
+ id_t id, Map &cache,
+ llvm::Optional<std::string> (UserIDResolver::*do_get)(id_t)) {
+
+ std::lock_guard<std::mutex> guard(m_mutex);
+ auto iter_bool = cache.try_emplace(id, llvm::None);
+ if (iter_bool.second)
+ iter_bool.first->second = (this->*do_get)(id);
+ if (iter_bool.first->second)
+ return llvm::StringRef(*iter_bool.first->second);
+ return llvm::None;
+}
+
+namespace {
+class NoopResolver : public UserIDResolver {
+protected:
+ llvm::Optional<std::string> DoGetUserName(id_t uid) override {
+ return llvm::None;
+ }
+
+ llvm::Optional<std::string> DoGetGroupName(id_t gid) override {
+ return llvm::None;
+ }
+};
+} // namespace
+
+static llvm::ManagedStatic<NoopResolver> g_noop_resolver;
+
+UserIDResolver &UserIDResolver::GetNoopResolver() { return *g_noop_resolver; }
diff --git a/lldb/unittests/Target/CMakeLists.txt b/lldb/unittests/Target/CMakeLists.txt
index bd73d708cb8..ba3039e1d42 100644
--- a/lldb/unittests/Target/CMakeLists.txt
+++ b/lldb/unittests/Target/CMakeLists.txt
@@ -2,6 +2,7 @@ add_lldb_unittest(TargetTests
MemoryRegionInfoTest.cpp
ModuleCacheTest.cpp
PathMappingListTest.cpp
+ ProcessInstanceInfoTest.cpp
LINK_LIBS
lldbCore
diff --git a/lldb/unittests/Target/ProcessInstanceInfoTest.cpp b/lldb/unittests/Target/ProcessInstanceInfoTest.cpp
new file mode 100644
index 00000000000..657f500d387
--- /dev/null
+++ b/lldb/unittests/Target/ProcessInstanceInfoTest.cpp
@@ -0,0 +1,75 @@
+//===-- ProcessInstanceInfoTest.cpp -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Process.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+namespace {
+/// A very simple resolver which fails for even ids and returns a simple string
+/// for odd ones.
+class DummyUserIDResolver : public UserIDResolver {
+protected:
+ llvm::Optional<std::string> DoGetUserName(id_t uid) {
+ if (uid % 2)
+ return ("user" + llvm::Twine(uid)).str();
+ return llvm::None;
+ }
+
+ llvm::Optional<std::string> DoGetGroupName(id_t gid) {
+ if (gid % 2)
+ return ("group" + llvm::Twine(gid)).str();
+ return llvm::None;
+ }
+};
+} // namespace
+
+TEST(ProcessInstanceInfo, Dump) {
+ ProcessInstanceInfo info("a.out", ArchSpec("x86_64-pc-linux"), 47);
+ info.SetUserID(1);
+ info.SetEffectiveUserID(2);
+ info.SetGroupID(3);
+ info.SetEffectiveGroupID(4);
+
+ DummyUserIDResolver resolver;
+ StreamString s;
+ info.Dump(s, resolver);
+ EXPECT_STREQ(R"( pid = 47
+ name = a.out
+ file = a.out
+ arch = x86_64-pc-linux
+ uid = 1 (user1)
+ gid = 3 (group3)
+ euid = 2 ()
+ egid = 4 ()
+)",
+ s.GetData());
+}
+
+TEST(ProcessInstanceInfo, DumpTable) {
+ ProcessInstanceInfo info("a.out", ArchSpec("x86_64-pc-linux"), 47);
+ info.SetUserID(1);
+ info.SetEffectiveUserID(2);
+ info.SetGroupID(3);
+ info.SetEffectiveGroupID(4);
+
+ DummyUserIDResolver resolver;
+ StreamString s;
+
+ const bool show_args = false;
+ const bool verbose = true;
+ ProcessInstanceInfo::DumpTableHeader(s, show_args, verbose);
+ info.DumpAsTableRow(s, resolver, show_args, verbose);
+ EXPECT_STREQ(
+ R"(PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS
+====== ====== ========== ========== ========== ========== ======================== ============================
+47 0 user1 group3 2 4 x86_64-pc-linux
+)",
+ s.GetData());
+}
diff --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt
index e16320d5247..093dc726d87 100644
--- a/lldb/unittests/Utility/CMakeLists.txt
+++ b/lldb/unittests/Utility/CMakeLists.txt
@@ -34,6 +34,7 @@ add_lldb_unittest(UtilityTests
TimeoutTest.cpp
TimerTest.cpp
UriParserTest.cpp
+ UserIDResolverTest.cpp
UUIDTest.cpp
VASprintfTest.cpp
VMRangeTest.cpp
diff --git a/lldb/unittests/Utility/UserIDResolverTest.cpp b/lldb/unittests/Utility/UserIDResolverTest.cpp
new file mode 100644
index 00000000000..4709b342ddb
--- /dev/null
+++ b/lldb/unittests/Utility/UserIDResolverTest.cpp
@@ -0,0 +1,47 @@
+//===-- UserIDResolverTest.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/UserIDResolver.h"
+#include "gmock/gmock.h"
+
+using namespace lldb_private;
+using namespace testing;
+
+namespace {
+class TestUserIDResolver : public UserIDResolver {
+public:
+ MOCK_METHOD1(DoGetUserName, llvm::Optional<std::string>(id_t uid));
+ MOCK_METHOD1(DoGetGroupName, llvm::Optional<std::string>(id_t gid));
+};
+} // namespace
+
+TEST(UserIDResolver, GetUserName) {
+ StrictMock<TestUserIDResolver> r;
+ llvm::StringRef user47("foo");
+ EXPECT_CALL(r, DoGetUserName(47)).Times(1).WillOnce(Return(user47.str()));
+ EXPECT_CALL(r, DoGetUserName(42)).Times(1).WillOnce(Return(llvm::None));
+
+ // Call functions twice to make sure the caching works.
+ EXPECT_EQ(user47, r.GetUserName(47));
+ EXPECT_EQ(user47, r.GetUserName(47));
+ EXPECT_EQ(llvm::None, r.GetUserName(42));
+ EXPECT_EQ(llvm::None, r.GetUserName(42));
+}
+
+TEST(UserIDResolver, GetGroupName) {
+ StrictMock<TestUserIDResolver> r;
+ llvm::StringRef group47("foo");
+ EXPECT_CALL(r, DoGetGroupName(47)).Times(1).WillOnce(Return(group47.str()));
+ EXPECT_CALL(r, DoGetGroupName(42)).Times(1).WillOnce(Return(llvm::None));
+
+ // Call functions twice to make sure the caching works.
+ EXPECT_EQ(group47, r.GetGroupName(47));
+ EXPECT_EQ(group47, r.GetGroupName(47));
+ EXPECT_EQ(llvm::None, r.GetGroupName(42));
+ EXPECT_EQ(llvm::None, r.GetGroupName(42));
+}
OpenPOWER on IntegriCloud