diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /lldb/source/Target/Target.cpp | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'lldb/source/Target/Target.cpp')
| -rw-r--r-- | lldb/source/Target/Target.cpp | 198 |
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 §ion_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); } |
