aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Target/Target.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
commitc0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch)
treef42add1021b9f2ac6a69ac7cf6c4499962739a45 /lldb/source/Target/Target.cpp
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'lldb/source/Target/Target.cpp')
-rw-r--r--lldb/source/Target/Target.cpp198
1 files changed, 140 insertions, 58 deletions
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 1f8e8c54fa9e..28575b50cf96 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -60,6 +60,7 @@
#include "lldb/Utility/Timer.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SetVector.h"
#include <memory>
#include <mutex>
@@ -95,14 +96,10 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_watchpoint_list(), m_process_sp(), m_search_filter_sp(),
m_image_search_paths(ImageSearchPathsChanged, this),
m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
- m_latest_stop_hook_id(0),
- m_valid(true), m_suppress_stop_hooks(false),
+ m_latest_stop_hook_id(0), m_valid(true), m_suppress_stop_hooks(false),
m_is_dummy_target(is_dummy_target),
m_frame_recognizer_manager_up(
- std::make_unique<StackFrameRecognizerManager>()),
- m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))
-
-{
+ std::make_unique<StackFrameRecognizerManager>()) {
SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
SetEventName(eBroadcastBitModulesLoaded, "modules-loaded");
SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded");
@@ -1022,7 +1019,7 @@ Status Target::SerializeBreakpointsToFile(const FileSpec &file,
}
StreamFile out_file(path.c_str(),
- File::eOpenOptionTruncate | File::eOpenOptionWrite |
+ File::eOpenOptionTruncate | File::eOpenOptionWriteOnly |
File::eOpenOptionCanCreate |
File::eOpenOptionCloseOnExec,
lldb::eFilePermissionsFileDefault);
@@ -1400,6 +1397,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
ClearModules(false);
if (executable_sp) {
+ ElapsedTime elapsed(m_stats.GetCreateTime());
LLDB_SCOPED_TIMERF("Target::SetExecutableModule (executable = '%s')",
executable_sp->GetFileSpec().GetPath().c_str());
@@ -1906,6 +1904,68 @@ size_t Target::ReadCStringFromMemory(const Address &addr, char *dst,
return total_cstr_len;
}
+addr_t Target::GetReasonableReadSize(const Address &addr) {
+ addr_t load_addr = addr.GetLoadAddress(this);
+ if (load_addr != LLDB_INVALID_ADDRESS && m_process_sp) {
+ // Avoid crossing cache line boundaries.
+ addr_t cache_line_size = m_process_sp->GetMemoryCacheLineSize();
+ return cache_line_size - (load_addr % cache_line_size);
+ }
+
+ // The read is going to go to the file cache, so we can just pick a largish
+ // value.
+ return 0x1000;
+}
+
+size_t Target::ReadStringFromMemory(const Address &addr, char *dst,
+ size_t max_bytes, Status &error,
+ size_t type_width, bool force_live_memory) {
+ if (!dst || !max_bytes || !type_width || max_bytes < type_width)
+ return 0;
+
+ size_t total_bytes_read = 0;
+
+ // Ensure a null terminator independent of the number of bytes that is
+ // read.
+ memset(dst, 0, max_bytes);
+ size_t bytes_left = max_bytes - type_width;
+
+ const char terminator[4] = {'\0', '\0', '\0', '\0'};
+ assert(sizeof(terminator) >= type_width && "Attempting to validate a "
+ "string with more than 4 bytes "
+ "per character!");
+
+ Address address = addr;
+ char *curr_dst = dst;
+
+ error.Clear();
+ while (bytes_left > 0 && error.Success()) {
+ addr_t bytes_to_read =
+ std::min<addr_t>(bytes_left, GetReasonableReadSize(address));
+ size_t bytes_read =
+ ReadMemory(address, curr_dst, bytes_to_read, error, force_live_memory);
+
+ if (bytes_read == 0)
+ break;
+
+ // Search for a null terminator of correct size and alignment in
+ // bytes_read
+ size_t aligned_start = total_bytes_read - total_bytes_read % type_width;
+ for (size_t i = aligned_start;
+ i + type_width <= total_bytes_read + bytes_read; i += type_width)
+ if (::memcmp(&dst[i], terminator, type_width) == 0) {
+ error.Clear();
+ return i;
+ }
+
+ total_bytes_read += bytes_read;
+ curr_dst += bytes_read;
+ address.Slide(bytes_read);
+ bytes_left -= bytes_read;
+ }
+ return total_bytes_read;
+}
+
size_t Target::ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_size,
bool is_signed, Scalar &scalar,
Status &error,
@@ -2231,7 +2291,10 @@ std::vector<TypeSystem *> Target::GetScratchTypeSystems(bool create_on_demand) {
if (!m_valid)
return {};
- std::vector<TypeSystem *> scratch_type_systems;
+ // Some TypeSystem instances are associated with several LanguageTypes so
+ // they will show up several times in the loop below. The SetVector filters
+ // out all duplicates as they serve no use for the caller.
+ llvm::SetVector<TypeSystem *> scratch_type_systems;
LanguageSet languages_for_expressions =
Language::GetLanguagesSupportingTypeSystemsForExpressions();
@@ -2247,10 +2310,10 @@ std::vector<TypeSystem *> Target::GetScratchTypeSystems(bool create_on_demand) {
"system available",
Language::GetNameForLanguageType(language));
else
- scratch_type_systems.emplace_back(&type_system_or_err.get());
+ scratch_type_systems.insert(&type_system_or_err.get());
}
- return scratch_type_systems;
+ return scratch_type_systems.takeVector();
}
PersistentExpressionState *
@@ -2345,35 +2408,22 @@ void Target::SettingsInitialize() { Process::SettingsInitialize(); }
void Target::SettingsTerminate() { Process::SettingsTerminate(); }
FileSpecList Target::GetDefaultExecutableSearchPaths() {
- TargetPropertiesSP properties_sp(Target::GetGlobalProperties());
- if (properties_sp)
- return properties_sp->GetExecutableSearchPaths();
- return FileSpecList();
+ return Target::GetGlobalProperties().GetExecutableSearchPaths();
}
FileSpecList Target::GetDefaultDebugFileSearchPaths() {
- TargetPropertiesSP properties_sp(Target::GetGlobalProperties());
- if (properties_sp)
- return properties_sp->GetDebugFileSearchPaths();
- return FileSpecList();
+ return Target::GetGlobalProperties().GetDebugFileSearchPaths();
}
ArchSpec Target::GetDefaultArchitecture() {
- TargetPropertiesSP properties_sp(Target::GetGlobalProperties());
- if (properties_sp)
- return properties_sp->GetDefaultArchitecture();
- return ArchSpec();
+ return Target::GetGlobalProperties().GetDefaultArchitecture();
}
void Target::SetDefaultArchitecture(const ArchSpec &arch) {
- TargetPropertiesSP properties_sp(Target::GetGlobalProperties());
- if (properties_sp) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET),
- "Target::SetDefaultArchitecture setting target's "
- "default architecture to {0} ({1})",
- arch.GetArchitectureName(), arch.GetTriple().getTriple());
- return properties_sp->SetDefaultArchitecture(arch);
- }
+ LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET),
+ "setting target's default architecture to {0} ({1})",
+ arch.GetArchitectureName(), arch.GetTriple().getTriple());
+ Target::GetGlobalProperties().SetDefaultArchitecture(arch);
}
Target *Target::GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
@@ -2399,8 +2449,10 @@ ExpressionResults Target::EvaluateExpression(
ExpressionResults execution_results = eExpressionSetupError;
- if (expr.empty())
+ if (expr.empty()) {
+ m_stats.GetExpressionStats().NotifyFailure();
return execution_results;
+ }
// We shouldn't run stop hooks in expressions.
bool old_suppress_value = m_suppress_stop_hooks;
@@ -2445,6 +2497,10 @@ ExpressionResults Target::EvaluateExpression(
fixed_expression, ctx_obj);
}
+ if (execution_results == eExpressionCompleted)
+ m_stats.GetExpressionStats().NotifySuccess();
+ else
+ m_stats.GetExpressionStats().NotifyFailure();
return execution_results;
}
@@ -2768,12 +2824,12 @@ bool Target::RunStopHooks() {
return false;
}
-const TargetPropertiesSP &Target::GetGlobalProperties() {
+TargetProperties &Target::GetGlobalProperties() {
// NOTE: intentional leak so we don't crash if global destructor chain gets
// called as other threads still use the result of this function
- static TargetPropertiesSP *g_settings_sp_ptr =
- new TargetPropertiesSP(new TargetProperties(nullptr));
- return *g_settings_sp_ptr;
+ static TargetProperties *g_settings_ptr =
+ new TargetProperties(nullptr);
+ return *g_settings_ptr;
}
Status Target::Install(ProcessLaunchInfo *launch_info) {
@@ -2908,6 +2964,7 @@ bool Target::SetSectionUnloaded(const lldb::SectionSP &section_sp,
void Target::ClearAllLoadedSections() { m_section_load_history.Clear(); }
Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
+ m_stats.SetLaunchOrAttachTime();
Status error;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
@@ -2936,17 +2993,9 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
launch_info.GetFlags().Set(eLaunchFlagDebug);
if (launch_info.IsScriptedProcess()) {
- TargetPropertiesSP properties_sp = GetGlobalProperties();
-
- if (!properties_sp) {
- LLDB_LOGF(log, "Target::%s Couldn't fetch target global properties.",
- __FUNCTION__);
- return error;
- }
-
// Only copy scripted process launch options.
- ProcessLaunchInfo &default_launch_info =
- const_cast<ProcessLaunchInfo &>(properties_sp->GetProcessLaunchInfo());
+ ProcessLaunchInfo &default_launch_info = const_cast<ProcessLaunchInfo &>(
+ GetGlobalProperties().GetProcessLaunchInfo());
default_launch_info.SetProcessPluginName("ScriptedProcess");
default_launch_info.SetScriptedProcessClassName(
@@ -2993,7 +3042,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
DeleteCurrentProcess();
m_process_sp =
- GetPlatform()->DebugProcess(launch_info, debugger, this, error);
+ GetPlatform()->DebugProcess(launch_info, debugger, *this, error);
} else {
LLDB_LOGF(log,
@@ -3119,6 +3168,7 @@ llvm::Expected<TraceSP> Target::GetTraceOrCreate() {
}
Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
+ m_stats.SetLaunchOrAttachTime();
auto state = eStateInvalid;
auto process_sp = GetProcessSP();
if (process_sp) {
@@ -3731,7 +3781,7 @@ TargetProperties::TargetProperties(Target *target)
: Properties(), m_launch_info(), m_target(target) {
if (target) {
m_collection_sp =
- OptionValueProperties::CreateLocalCopy(*Target::GetGlobalProperties());
+ OptionValueProperties::CreateLocalCopy(Target::GetGlobalProperties());
// Set callbacks to update launch_info whenever "settins set" updated any
// of these properties
@@ -3781,7 +3831,7 @@ TargetProperties::TargetProperties(Target *target)
true, m_experimental_properties_up->GetValueProperties());
m_collection_sp->AppendProperty(
ConstString("process"), ConstString("Settings specific to processes."),
- true, Process::GetGlobalProperties()->GetValueProperties());
+ true, Process::GetGlobalProperties().GetValueProperties());
}
}
@@ -3985,6 +4035,45 @@ Environment TargetProperties::GetEnvironment() const {
return ComputeEnvironment();
}
+Environment TargetProperties::GetInheritedEnvironment() const {
+ Environment environment;
+
+ if (m_target == nullptr)
+ return environment;
+
+ if (!m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, ePropertyInheritEnv,
+ g_target_properties[ePropertyInheritEnv].default_uint_value != 0))
+ return environment;
+
+ PlatformSP platform_sp = m_target->GetPlatform();
+ if (platform_sp == nullptr)
+ return environment;
+
+ Environment platform_environment = platform_sp->GetEnvironment();
+ for (const auto &KV : platform_environment)
+ environment[KV.first()] = KV.second;
+
+ Args property_unset_environment;
+ m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyUnsetEnvVars,
+ property_unset_environment);
+ for (const auto &var : property_unset_environment)
+ environment.erase(var.ref());
+
+ return environment;
+}
+
+Environment TargetProperties::GetTargetEnvironment() const {
+ Args property_environment;
+ m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEnvVars,
+ property_environment);
+ Environment environment;
+ for (const auto &KV : Environment(property_environment))
+ environment[KV.first()] = KV.second;
+
+ return environment;
+}
+
void TargetProperties::SetEnvironment(Environment env) {
// TODO: Get rid of the Args intermediate step
const uint32_t idx = ePropertyEnvVars;
@@ -4249,16 +4338,6 @@ void TargetProperties::SetDisplayRecognizedArguments(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
-bool TargetProperties::GetNonStopModeEnabled() const {
- const uint32_t idx = ePropertyNonStopModeEnabled;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
-}
-
-void TargetProperties::SetNonStopModeEnabled(bool b) {
- const uint32_t idx = ePropertyNonStopModeEnabled;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
-}
-
const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() const {
return m_launch_info;
}
@@ -4435,3 +4514,6 @@ std::recursive_mutex &Target::GetAPIMutex() {
else
return m_mutex;
}
+
+/// Get metrics associated with this target in JSON format.
+llvm::json::Value Target::ReportStatistics() { return m_stats.ToJSON(*this); }