aboutsummaryrefslogtreecommitdiffstats
path: root/source/Target
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Target
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
downloadsrc-94994d372d014ce4c8758b9605d63fae651bd8aa.tar.gz
src-94994d372d014ce4c8758b9605d63fae651bd8aa.zip
Vendor import of lldb trunk r351319 (just before the release_80 branchvendor/lldb/lldb-trunk-r351319
Notes
Notes: svn path=/vendor/lldb/dist/; revision=343181 svn path=/vendor/lldb/lldb-trunk-r351319/; revision=343182; tag=vendor/lldb/lldb-trunk-r351319
Diffstat (limited to 'source/Target')
-rw-r--r--source/Target/ABI.cpp4
-rw-r--r--source/Target/CMakeLists.txt1
-rw-r--r--source/Target/CPPLanguageRuntime.cpp304
-rw-r--r--source/Target/ExecutionContext.cpp6
-rw-r--r--source/Target/InstrumentationRuntime.cpp4
-rw-r--r--source/Target/JITLoader.cpp4
-rw-r--r--source/Target/Language.cpp35
-rw-r--r--source/Target/LanguageRuntime.cpp8
-rw-r--r--source/Target/Memory.cpp6
-rw-r--r--source/Target/MemoryHistory.cpp4
-rw-r--r--source/Target/ModuleCache.cpp20
-rw-r--r--source/Target/ObjCLanguageRuntime.cpp3
-rw-r--r--source/Target/OperatingSystem.cpp4
-rw-r--r--source/Target/PathMappingList.cpp22
-rw-r--r--source/Target/Platform.cpp160
-rw-r--r--source/Target/Process.cpp125
-rw-r--r--source/Target/ProcessInfo.cpp16
-rw-r--r--source/Target/ProcessLaunchInfo.cpp162
-rw-r--r--source/Target/Queue.cpp4
-rw-r--r--source/Target/QueueItem.cpp2
-rw-r--r--source/Target/RegisterContext.cpp8
-rw-r--r--source/Target/RegisterNumber.cpp17
-rw-r--r--source/Target/SectionLoadHistory.cpp4
-rw-r--r--source/Target/SectionLoadList.cpp4
-rw-r--r--source/Target/StackFrame.cpp102
-rw-r--r--source/Target/StackFrameList.cpp768
-rw-r--r--source/Target/StackFrameRecognizer.cpp191
-rw-r--r--source/Target/StackID.cpp4
-rw-r--r--source/Target/StopInfo.cpp44
-rw-r--r--source/Target/SystemRuntime.cpp4
-rw-r--r--source/Target/Target.cpp708
-rw-r--r--source/Target/TargetList.cpp46
-rw-r--r--source/Target/Thread.cpp193
-rw-r--r--source/Target/ThreadList.cpp6
-rw-r--r--source/Target/ThreadPlan.cpp7
-rw-r--r--source/Target/ThreadPlanBase.cpp9
-rw-r--r--source/Target/ThreadPlanCallFunction.cpp4
-rw-r--r--source/Target/ThreadPlanCallFunctionUsingABI.cpp4
-rw-r--r--source/Target/ThreadPlanCallOnFunctionExit.cpp7
-rw-r--r--source/Target/ThreadPlanCallUserExpression.cpp4
-rw-r--r--source/Target/ThreadPlanPython.cpp24
-rw-r--r--source/Target/ThreadPlanRunToAddress.cpp14
-rw-r--r--source/Target/ThreadPlanShouldStopHere.cpp31
-rw-r--r--source/Target/ThreadPlanStepInRange.cpp36
-rw-r--r--source/Target/ThreadPlanStepInstruction.cpp17
-rw-r--r--source/Target/ThreadPlanStepOut.cpp61
-rw-r--r--source/Target/ThreadPlanStepOverBreakpoint.cpp4
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp41
-rw-r--r--source/Target/ThreadPlanStepRange.cpp22
-rw-r--r--source/Target/ThreadPlanStepThrough.cpp39
-rw-r--r--source/Target/ThreadPlanStepUntil.cpp19
-rw-r--r--source/Target/ThreadPlanTracer.cpp4
-rw-r--r--source/Target/ThreadSpec.cpp4
-rw-r--r--source/Target/UnixSignals.cpp6
-rw-r--r--source/Target/UnwindAssembly.cpp4
55 files changed, 2008 insertions, 1346 deletions
diff --git a/source/Target/ABI.cpp b/source/Target/ABI.cpp
index 8d4513ad6811..96e09b75094a 100644
--- a/source/Target/ABI.cpp
+++ b/source/Target/ABI.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/PluginManager.h"
diff --git a/source/Target/CMakeLists.txt b/source/Target/CMakeLists.txt
index df137c314afa..265b3a80779d 100644
--- a/source/Target/CMakeLists.txt
+++ b/source/Target/CMakeLists.txt
@@ -28,6 +28,7 @@ add_lldb_library(lldbTarget
SectionLoadList.cpp
StackFrame.cpp
StackFrameList.cpp
+ StackFrameRecognizer.cpp
StackID.cpp
StopInfo.cpp
StructuredDataPlugin.cpp
diff --git a/source/Target/CPPLanguageRuntime.cpp b/source/Target/CPPLanguageRuntime.cpp
index c7e7b2511971..f0bd1758461c 100644
--- a/source/Target/CPPLanguageRuntime.cpp
+++ b/source/Target/CPPLanguageRuntime.cpp
@@ -14,9 +14,19 @@
#include "llvm/ADT/StringRef.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/VariableList.h"
+
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
using namespace lldb;
using namespace lldb_private;
@@ -40,3 +50,297 @@ bool CPPLanguageRuntime::GetObjectDescription(
// C++ has no generic way to do this.
return false;
}
+
+CPPLanguageRuntime::LibCppStdFunctionCallableInfo
+CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
+ lldb::ValueObjectSP &valobj_sp) {
+ LibCppStdFunctionCallableInfo optional_info;
+
+ if (!valobj_sp)
+ return optional_info;
+
+ // Member __f_ has type __base*, the contents of which will hold:
+ // 1) a vtable entry which may hold type information needed to discover the
+ // lambda being called
+ // 2) possibly hold a pointer to the callable object
+ // e.g.
+ //
+ // (lldb) frame var -R f_display
+ // (std::__1::function<void (int)>) f_display = {
+ // __buf_ = {
+ // …
+ // }
+ // __f_ = 0x00007ffeefbffa00
+ // }
+ // (lldb) memory read -fA 0x00007ffeefbffa00
+ // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
+ // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
+ //
+ // We will be handling five cases below, std::function is wrapping:
+ //
+ // 1) a lambda we know at compile time. We will obtain the name of the lambda
+ // from the first template pameter from __func's vtable. We will look up
+ // the lambda's operator()() and obtain the line table entry.
+ // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
+ // will be stored after the vtable. We will obtain the lambdas name from
+ // this entry and lookup operator()() and obtain the line table entry.
+ // 3) a callable object via operator()(). We will obtain the name of the
+ // object from the first template parameter from __func's vtable. We will
+ // look up the objectc operator()() and obtain the line table entry.
+ // 4) a member function. A pointer to the function will stored after the
+ // we will obtain the name from this pointer.
+ // 5) a free function. A pointer to the function will stored after the vtable
+ // we will obtain the name from this pointer.
+ ValueObjectSP member__f_(
+ valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));
+
+ if (member__f_) {
+ ValueObjectSP sub_member__f_(
+ member__f_->GetChildMemberWithName(ConstString("__f_"), true));
+
+ if (sub_member__f_)
+ member__f_ = sub_member__f_;
+ }
+
+ lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);
+
+ optional_info.member__f_pointer_value = member__f_pointer_value;
+
+ ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == nullptr)
+ return optional_info;
+
+ uint32_t address_size = process->GetAddressByteSize();
+ Status status;
+
+ // First item pointed to by __f_ should be the pointer to the vtable for
+ // a __base object.
+ lldb::addr_t vtable_address =
+ process->ReadPointerFromMemory(member__f_pointer_value, status);
+
+ if (status.Fail())
+ return optional_info;
+
+ lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
+ // As commened above we may not have a function pointer but if we do we will
+ // need it.
+ lldb::addr_t possible_function_address =
+ process->ReadPointerFromMemory(address_after_vtable, status);
+
+ if (status.Fail())
+ return optional_info;
+
+ Target &target = process->GetTarget();
+
+ if (target.GetSectionLoadList().IsEmpty())
+ return optional_info;
+
+ Address vtable_addr_resolved;
+ SymbolContext sc;
+ Symbol *symbol;
+
+ if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
+ vtable_addr_resolved))
+ return optional_info;
+
+ target.GetImages().ResolveSymbolContextForAddress(
+ vtable_addr_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+
+ if (symbol == nullptr)
+ return optional_info;
+
+ llvm::StringRef vtable_name(symbol->GetName().GetCString());
+ bool found_expected_start_string =
+ vtable_name.startswith("vtable for std::__1::__function::__func<");
+
+ if (!found_expected_start_string)
+ return optional_info;
+
+ // Given case 1 or 3 we have a vtable name, we are want to extract the first
+ // template parameter
+ //
+ // ... __func<main::$_0, std::__1::allocator<main::$_0> ...
+ // ^^^^^^^^^
+ //
+ // We do this by find the first < and , and extracting in between.
+ //
+ // This covers the case of the lambda known at compile time.
+ size_t first_open_angle_bracket = vtable_name.find('<') + 1;
+ size_t first_comma = vtable_name.find_first_of(',');
+
+ llvm::StringRef first_template_parameter =
+ vtable_name.slice(first_open_angle_bracket, first_comma);
+
+ Address function_address_resolved;
+
+ // Setup for cases 2, 4 and 5 we have a pointer to a function after the
+ // vtable. We will use a process of elimination to drop through each case
+ // and obtain the data we need.
+ if (target.GetSectionLoadList().ResolveLoadAddress(
+ possible_function_address, function_address_resolved)) {
+ target.GetImages().ResolveSymbolContextForAddress(
+ function_address_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+ }
+
+ auto get_name = [&first_template_parameter, &symbol]() {
+ // Given case 1:
+ //
+ // main::$_0
+ //
+ // we want to append ::operator()()
+ if (first_template_parameter.contains("$_"))
+ return llvm::Regex::escape(first_template_parameter.str()) +
+ R"(::operator\(\)\(.*\))";
+
+ if (symbol != NULL &&
+ symbol->GetName().GetStringRef().contains("__invoke")) {
+
+ llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
+ size_t pos2 = symbol_name.find_last_of(':');
+
+ // Given case 2:
+ //
+ // main::$_1::__invoke(...)
+ //
+ // We want to slice off __invoke(...) and append operator()()
+ std::string lambda_operator =
+ llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
+ R"(operator\(\)\(.*\))";
+
+ return lambda_operator;
+ }
+
+ // Case 3
+ return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
+ ;
+ };
+
+ std::string func_to_match = get_name();
+
+ SymbolContextList scl;
+
+ target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true,
+ true, scl);
+
+ // Case 1,2 or 3
+ if (scl.GetSize() >= 1) {
+ SymbolContext sc2 = scl[0];
+
+ AddressRange range;
+ sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
+
+ Address address = range.GetBaseAddress();
+
+ Address addr;
+ if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
+ addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+
+ if (first_template_parameter.contains("$_") ||
+ (symbol != nullptr &&
+ symbol->GetName().GetStringRef().contains("__invoke"))) {
+ // Case 1 and 2
+ optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
+ } else {
+ // Case 3
+ optional_info.callable_case =
+ LibCppStdFunctionCallableCase::CallableObject;
+ }
+
+ optional_info.callable_symbol = *symbol;
+ optional_info.callable_line_entry = line_entry;
+ optional_info.callable_address = addr;
+ return optional_info;
+ }
+ }
+
+ // Case 4 or 5
+ if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
+ optional_info.callable_case =
+ LibCppStdFunctionCallableCase::FreeOrMemberFunction;
+ optional_info.callable_address = function_address_resolved;
+ optional_info.callable_symbol = *symbol;
+
+ return optional_info;
+ }
+
+ return optional_info;
+}
+
+lldb::ThreadPlanSP
+CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others) {
+ ThreadPlanSP ret_plan_sp;
+
+ lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
+
+ TargetSP target_sp(thread.CalculateTarget());
+
+ if (target_sp->GetSectionLoadList().IsEmpty())
+ return ret_plan_sp;
+
+ Address pc_addr_resolved;
+ SymbolContext sc;
+ Symbol *symbol;
+
+ if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
+ pc_addr_resolved))
+ return ret_plan_sp;
+
+ target_sp->GetImages().ResolveSymbolContextForAddress(
+ pc_addr_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+
+ if (symbol == nullptr)
+ return ret_plan_sp;
+
+ llvm::StringRef function_name(symbol->GetName().GetCString());
+
+ // Handling the case where we are attempting to step into std::function.
+ // The behavior will be that we will attempt to obtain the wrapped
+ // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
+ // will return a ThreadPlanRunToAddress to the callable. Therefore we will
+ // step into the wrapped callable.
+ //
+ bool found_expected_start_string =
+ function_name.startswith("std::__1::function<");
+
+ if (!found_expected_start_string)
+ return ret_plan_sp;
+
+ AddressRange range_of_curr_func;
+ sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
+
+ StackFrameSP frame = thread.GetStackFrameAtIndex(0);
+
+ if (frame) {
+ ValueObjectSP value_sp = frame->FindVariable(ConstString("this"));
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
+ FindLibCppStdFunctionCallableInfo(value_sp);
+
+ if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
+ value_sp->GetValueIsValid()) {
+ // We found the std::function wrapped callable and we have its address.
+ // We now create a ThreadPlan to run to the callable.
+ ret_plan_sp.reset(new ThreadPlanRunToAddress(
+ thread, callable_info.callable_address, stop_others));
+ return ret_plan_sp;
+ } else {
+ // We are in std::function but we could not obtain the callable.
+ // We create a ThreadPlan to keep stepping through using the address range
+ // of the current function.
+ ret_plan_sp.reset(new ThreadPlanStepInRange(thread, range_of_curr_func,
+ sc, eOnlyThisThread,
+ eLazyBoolYes, eLazyBoolYes));
+ return ret_plan_sp;
+ }
+ }
+
+ return ret_plan_sp;
+}
diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp
index 73c64916cf1f..7f1f0331c922 100644
--- a/source/Target/ExecutionContext.cpp
+++ b/source/Target/ExecutionContext.cpp
@@ -7,17 +7,13 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
using namespace lldb_private;
diff --git a/source/Target/InstrumentationRuntime.cpp b/source/Target/InstrumentationRuntime.cpp
index ac8b5dfe4599..e948d43d50af 100644
--- a/source/Target/InstrumentationRuntime.cpp
+++ b/source/Target/InstrumentationRuntime.cpp
@@ -7,10 +7,6 @@
//
//===---------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
diff --git a/source/Target/JITLoader.cpp b/source/Target/JITLoader.cpp
index 77ce4add486f..ddadcfa87a0a 100644
--- a/source/Target/JITLoader.cpp
+++ b/source/Target/JITLoader.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/JITLoader.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/JITLoaderList.h"
diff --git a/source/Target/Language.cpp b/source/Target/Language.cpp
index cde6f8654aec..5c7a4097dd6f 100644
--- a/source/Target/Language.cpp
+++ b/source/Target/Language.cpp
@@ -77,7 +77,39 @@ Language *Language::FindPlugin(lldb::LanguageType language) {
return nullptr;
}
+Language *Language::FindPlugin(llvm::StringRef file_path) {
+ Language *result = nullptr;
+ ForEach([&result, file_path](Language *language) {
+ if (language->IsSourceFile(file_path)) {
+ result = language;
+ return false;
+ }
+ return true;
+ });
+ return result;
+}
+
+Language *Language::FindPlugin(LanguageType language,
+ llvm::StringRef file_path) {
+ Language *result = FindPlugin(language);
+ // Finding a language by file path is slower, we so we use this as the
+ // fallback.
+ if (!result)
+ result = FindPlugin(file_path);
+ return result;
+}
+
void Language::ForEach(std::function<bool(Language *)> callback) {
+ // If we want to iterate over all languages, we first have to complete the
+ // LanguagesMap.
+ static llvm::once_flag g_initialize;
+ llvm::call_once(g_initialize, [] {
+ for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;
+ ++lang) {
+ FindPlugin(static_cast<lldb::LanguageType>(lang));
+ }
+ });
+
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
LanguagesMap &map(GetLanguagesMap());
for (const auto &entry : map) {
@@ -353,11 +385,10 @@ bool Language::ImageListTypeScavenger::Find_Impl(
Target *target = exe_scope->CalculateTarget().get();
if (target) {
const auto &images(target->GetImages());
- SymbolContext null_sc;
ConstString cs_key(key);
llvm::DenseSet<SymbolFile *> searched_sym_files;
TypeList matches;
- images.FindTypes(null_sc, cs_key, false, UINT32_MAX, searched_sym_files,
+ images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files,
matches);
for (const auto &match : matches.Types()) {
if (match.get()) {
diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp
index bd02121f6a4d..ea6914fb076d 100644
--- a/source/Target/LanguageRuntime.cpp
+++ b/source/Target/LanguageRuntime.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/LanguageRuntime.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/PluginManager.h"
@@ -125,11 +121,11 @@ public:
return eCallbackReturnStop;
}
- Searcher::Depth GetDepth() override {
+ lldb::SearchDepth GetDepth() override {
if (SetActualResolver())
return m_actual_resolver_sp->GetDepth();
else
- return eDepthTarget;
+ return lldb::eSearchDepthTarget;
}
void GetDescription(Stream *s) override {
diff --git a/source/Target/Memory.cpp b/source/Target/Memory.cpp
index ad1b4093155d..190c5057e881 100644
--- a/source/Target/Memory.cpp
+++ b/source/Target/Memory.cpp
@@ -8,16 +8,12 @@
//===----------------------------------------------------------------------===//
#include "lldb/Target/Memory.h"
-// C Includes
#include <inttypes.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/RangeMap.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/MemoryHistory.cpp b/source/Target/MemoryHistory.cpp
index 627942796507..eae931482552 100644
--- a/source/Target/MemoryHistory.cpp
+++ b/source/Target/MemoryHistory.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Core/PluginManager.h"
diff --git a/source/Target/ModuleCache.cpp b/source/Target/ModuleCache.cpp
index 19adfbabe277..daf787b1fb22 100644
--- a/source/Target/ModuleCache.cpp
+++ b/source/Target/ModuleCache.cpp
@@ -76,7 +76,7 @@ FileSpec GetModuleDirectory(const FileSpec &root_dir_spec, const UUID &uuid) {
}
FileSpec GetSymbolFileSpec(const FileSpec &module_file_spec) {
- return FileSpec(module_file_spec.GetPath() + kSymFileExtension, false);
+ return FileSpec(module_file_spec.GetPath() + kSymFileExtension);
}
void DeleteExistingModule(const FileSpec &root_dir_spec,
@@ -133,7 +133,7 @@ Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
const auto sysroot_module_path_spec =
JoinPath(JoinPath(root_dir_spec, hostname),
platform_module_spec.GetPath().c_str());
- if (sysroot_module_path_spec.Exists()) {
+ if (FileSystem::Instance().Exists(sysroot_module_path_spec)) {
if (!delete_existing)
return Status();
@@ -141,7 +141,7 @@ Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
}
const auto error = MakeDirectory(
- FileSpec(sysroot_module_path_spec.GetDirectory().AsCString(), false));
+ FileSpec(sysroot_module_path_spec.GetDirectory().AsCString()));
if (error.Fail())
return error;
@@ -159,9 +159,10 @@ ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
return;
m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
- m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite |
- File::eOpenOptionCanCreate |
- File::eOpenOptionCloseOnExec);
+ FileSystem::Instance().Open(m_file, m_file_spec,
+ File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionCloseOnExec);
if (!m_file) {
error.SetErrorToErrno();
return;
@@ -225,9 +226,10 @@ Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
const auto module_file_path = JoinPath(
module_spec_dir, module_spec.GetFileSpec().GetFilename().AsCString());
- if (!module_file_path.Exists())
+ if (!FileSystem::Instance().Exists(module_file_path))
return Status("Module %s not found", module_file_path.GetPath().c_str());
- if (module_file_path.GetByteSize() != module_spec.GetObjectSize())
+ if (FileSystem::Instance().GetByteSize(module_file_path) !=
+ module_spec.GetObjectSize())
return Status("Module %s has invalid file size",
module_file_path.GetPath().c_str());
@@ -252,7 +254,7 @@ Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
return error;
FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
- if (symfile_spec.Exists())
+ if (FileSystem::Instance().Exists(symfile_spec))
cached_module_sp->SetSymbolFileFileSpec(symfile_spec);
m_loaded_modules.insert(
diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp
index b1fcee6db63b..8627da938ea3 100644
--- a/source/Target/ObjCLanguageRuntime.cpp
+++ b/source/Target/ObjCLanguageRuntime.cpp
@@ -108,14 +108,13 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
if (!module_sp)
return TypeSP();
- const SymbolContext null_sc;
const bool exact_match = true;
const uint32_t max_matches = UINT32_MAX;
TypeList types;
llvm::DenseSet<SymbolFile *> searched_symbol_files;
const uint32_t num_types = module_sp->FindTypes(
- null_sc, name, exact_match, max_matches, searched_symbol_files, types);
+ name, exact_match, max_matches, searched_symbol_files, types);
if (num_types) {
uint32_t i;
diff --git a/source/Target/OperatingSystem.cpp b/source/Target/OperatingSystem.cpp
index 7a1d9d619879..099bfd055ed1 100644
--- a/source/Target/OperatingSystem.cpp
+++ b/source/Target/OperatingSystem.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Thread.h"
diff --git a/source/Target/PathMappingList.cpp b/source/Target/PathMappingList.cpp
index 778728eebb09..c2249cce89b9 100644
--- a/source/Target/PathMappingList.cpp
+++ b/source/Target/PathMappingList.cpp
@@ -7,19 +7,16 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <climits>
#include <cstring>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-private-enumerations.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-private-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -37,7 +34,7 @@ namespace {
ConstString NormalizePath(const ConstString &path) {
// If we use "path" to construct a FileSpec, it will normalize the path for
// us. We then grab the string and turn it back into a ConstString.
- return ConstString(FileSpec(path.GetStringRef(), false).GetPath());
+ return ConstString(FileSpec(path.GetStringRef()).GetPath());
}
}
//----------------------------------------------------------------------
@@ -176,13 +173,13 @@ bool PathMappingList::RemapPath(llvm::StringRef path,
// We need to figure out if the "path" argument is relative. If it is,
// then we should remap, else skip this entry.
if (path_is_relative == eLazyBoolCalculate) {
- path_is_relative = FileSpec(path, false).IsRelative() ? eLazyBoolYes :
- eLazyBoolNo;
+ path_is_relative =
+ FileSpec(path).IsRelative() ? eLazyBoolYes : eLazyBoolNo;
}
if (!path_is_relative)
continue;
}
- FileSpec remapped(it.second.GetStringRef(), false);
+ FileSpec remapped(it.second.GetStringRef());
remapped.AppendPathComponent(path);
new_path = remapped.GetPath();
return true;
@@ -196,7 +193,7 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co
for (const auto &it : m_pairs) {
if (!path_ref.consume_front(it.second.GetStringRef()))
continue;
- fixed.SetFile(it.first.GetStringRef(), false, FileSpec::Style::native);
+ fixed.SetFile(it.first.GetStringRef(), FileSpec::Style::native);
fixed.AppendPathComponent(path_ref);
return true;
}
@@ -216,10 +213,9 @@ bool PathMappingList::FindFile(const FileSpec &orig_spec,
if (orig_path_len >= prefix_len) {
if (::strncmp(pos->first.GetCString(), orig_path, prefix_len) == 0) {
- new_spec.SetFile(pos->second.GetCString(), false,
- FileSpec::Style::native);
+ new_spec.SetFile(pos->second.GetCString(), FileSpec::Style::native);
new_spec.AppendPathComponent(orig_path + prefix_len);
- if (new_spec.Exists())
+ if (FileSystem::Instance().Exists(new_spec))
return true;
}
}
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 5ae556ecc02a..400b3c92b5ab 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <algorithm>
#include <csignal>
#include <fstream>
#include <vector>
-// Other libraries and framework includes
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-// Project includes
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
@@ -67,12 +63,11 @@ const char *Platform::GetHostPlatformName() { return "host"; }
namespace {
-PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"use-module-cache", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr, "Use module cache."},
+ {}, "Use module cache."},
{"module-cache-directory", OptionValue::eTypeFileSpec, true, 0, nullptr,
- nullptr, "Root directory for cached modules."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {}, "Root directory for cached modules."}};
enum { ePropertyUseModuleCache, ePropertyModuleCacheDirectory };
@@ -95,7 +90,7 @@ PlatformProperties::PlatformProperties() {
if (!llvm::sys::path::home_directory(user_home_dir))
return;
- module_cache_dir = FileSpec(user_home_dir.c_str(), false);
+ module_cache_dir = FileSpec(user_home_dir.c_str());
module_cache_dir.AppendPathComponent(".lldb");
module_cache_dir.AppendPathComponent("module_cache");
SetModuleCacheDirectory(module_cache_dir);
@@ -228,16 +223,35 @@ Status Platform::GetSharedModule(const ModuleSpec &module_spec,
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, false);
- return GetRemoteSharedModule(module_spec, process, module_sp,
- [&](const ModuleSpec &spec) {
- Status error = ModuleList::GetSharedModule(
- spec, module_sp, module_search_paths_ptr,
- old_module_sp_ptr, did_create_ptr, false);
- if (error.Success() && module_sp)
- module_sp->SetPlatformFileSpec(
- spec.GetFileSpec());
- return error;
- },
+ // Module resolver lambda.
+ auto resolver = [&](const ModuleSpec &spec) {
+ Status error(eErrorTypeGeneric);
+ ModuleSpec resolved_spec;
+ // Check if we have sysroot set.
+ if (m_sdk_sysroot) {
+ // Prepend sysroot to module spec.
+ resolved_spec = spec;
+ resolved_spec.GetFileSpec().PrependPathComponent(
+ m_sdk_sysroot.GetStringRef());
+ // Try to get shared module with resolved spec.
+ error = ModuleList::GetSharedModule(
+ resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
+ did_create_ptr, false);
+ }
+ // If we don't have sysroot or it didn't work then
+ // try original module spec.
+ if (!error.Success()) {
+ resolved_spec = spec;
+ error = ModuleList::GetSharedModule(
+ resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
+ did_create_ptr, false);
+ }
+ if (error.Success() && module_sp)
+ module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());
+ return error;
+ };
+
+ return GetRemoteSharedModule(module_spec, process, module_sp, resolver,
did_create_ptr);
}
@@ -518,9 +532,12 @@ FileSpec Platform::GetWorkingDirectory() {
if (IsHost()) {
llvm::SmallString<64> cwd;
if (llvm::sys::fs::current_path(cwd))
- return FileSpec{};
- else
- return FileSpec(cwd, true);
+ return {};
+ else {
+ FileSpec file_spec(cwd);
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
+ }
} else {
if (!m_working_dir)
m_working_dir = GetRemoteWorkingDirectory();
@@ -534,16 +551,17 @@ struct RecurseCopyBaton {
Status error;
};
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &src) {
+ llvm::StringRef path) {
RecurseCopyBaton *rc_baton = (RecurseCopyBaton *)baton;
+ FileSpec src(path);
namespace fs = llvm::sys::fs;
switch (ft) {
case fs::file_type::fifo_file:
case fs::file_type::socket_file:
// we have no way to copy pipes and sockets - ignore them and continue
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
break;
case fs::file_type::directory_file: {
@@ -556,7 +574,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
if (error.Fail()) {
rc_baton->error.SetErrorStringWithFormat(
"unable to setup directory %s on remote end", dst_dir.GetCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
// now recurse
@@ -568,13 +586,13 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,
Status()};
- FileSpec::EnumerateDirectory(src_dir_path, true, true, true,
- RecurseCopy_Callback, &rc_baton2);
+ FileSystem::Instance().EnumerateDirectory(src_dir_path, true, true, true,
+ RecurseCopy_Callback, &rc_baton2);
if (rc_baton2.error.Fail()) {
rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
case fs::file_type::symlink_file: {
@@ -585,18 +603,18 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
FileSpec src_resolved;
- rc_baton->error = FileSystem::Readlink(src, src_resolved);
+ rc_baton->error = FileSystem::Instance().Readlink(src, src_resolved);
if (rc_baton->error.Fail())
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
rc_baton->error =
rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);
if (rc_baton->error.Fail())
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
case fs::file_type::regular_file: {
@@ -607,15 +625,15 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
Status err = rc_baton->platform_ptr->PutFile(src, dst_file);
if (err.Fail()) {
rc_baton->error.SetErrorString(err.AsCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
default:
rc_baton->error.SetErrorStringWithFormat(
"invalid file detected during copy: %s", src.GetPath().c_str());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
break;
}
llvm_unreachable("Unhandled file_type!");
@@ -690,7 +708,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
switch (fs::get_file_type(src.GetPath(), false)) {
case fs::file_type::directory_file: {
llvm::sys::fs::remove(fixed_dst.GetPath());
- uint32_t permissions = src.GetPermissions();
+ uint32_t permissions = FileSystem::Instance().GetPermissions(src);
if (permissions == 0)
permissions = eFilePermissionsDirectoryDefault;
error = MakeDirectory(fixed_dst, permissions);
@@ -701,8 +719,8 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
recurse_dst.GetDirectory().SetCString(fixed_dst.GetCString());
std::string src_dir_path(src.GetPath());
RecurseCopyBaton baton = {recurse_dst, this, Status()};
- FileSpec::EnumerateDirectory(src_dir_path, true, true, true,
- RecurseCopy_Callback, &baton);
+ FileSystem::Instance().EnumerateDirectory(
+ src_dir_path, true, true, true, RecurseCopy_Callback, &baton);
return baton.error;
}
} break;
@@ -715,7 +733,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
case fs::file_type::symlink_file: {
llvm::sys::fs::remove(fixed_dst.GetPath());
FileSpec src_resolved;
- error = FileSystem::Readlink(src, src_resolved);
+ error = FileSystem::Instance().Readlink(src, src_resolved);
if (error.Success())
error = CreateSymlink(dst, src_resolved);
} break;
@@ -871,7 +889,7 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Status error;
- if (module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
if (module_spec.GetArchitecture().IsValid()) {
error = ModuleList::GetSharedModule(module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
@@ -902,7 +920,7 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
FileSpec &sym_file) {
Status error;
- if (sym_spec.GetSymbolFileSpec().Exists())
+ if (FileSystem::Instance().Exists(sym_spec.GetSymbolFileSpec()))
sym_file = sym_spec.GetSymbolFileSpec();
else
error.SetErrorString("unable to resolve symbol file");
@@ -912,7 +930,8 @@ Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
bool Platform::ResolveRemotePath(const FileSpec &platform_path,
FileSpec &resolved_platform_path) {
resolved_platform_path = platform_path;
- return resolved_platform_path.ResolvePath();
+ FileSystem::Instance().Resolve(resolved_platform_path);
+ return true;
}
const ArchSpec &Platform::GetSystemArchitecture() {
@@ -1257,8 +1276,9 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
if (fs::is_symlink_file(source.GetPath()))
source_open_options |= File::eOpenOptionDontFollowSymlinks;
- File source_file(source, source_open_options, lldb::eFilePermissionsUserRW);
- Status error;
+ File source_file;
+ Status error = FileSystem::Instance().Open(
+ source_file, source, source_open_options, lldb::eFilePermissionsUserRW);
uint32_t permissions = source_file.GetPermissions(error);
if (permissions == 0)
permissions = lldb::eFilePermissionsFileDefault;
@@ -1276,7 +1296,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
return error;
if (dest_file == UINT64_MAX)
return Status("unable to open target file");
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
uint64_t offset = 0;
for (;;) {
size_t bytes_read = buffer_sp->GetByteSize();
@@ -1378,32 +1398,32 @@ const char *Platform::GetLocalCacheDirectory() {
return m_local_cache_directory.c_str();
}
-static OptionDefinition g_rsync_option_table[] = {
+static constexpr OptionDefinition g_rsync_option_table[] = {
{LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Enable rsync."},
+ {}, 0, eArgTypeNone, "Enable rsync."},
{LLDB_OPT_SET_ALL, false, "rsync-opts", 'R',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific options required for rsync to work."},
{LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific rsync prefix put before the remote path."},
{LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Do not automatically fill in the remote hostname when composing the "
"rsync command."},
};
-static OptionDefinition g_ssh_option_table[] = {
+static constexpr OptionDefinition g_ssh_option_table[] = {
{LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Enable SSH."},
+ {}, 0, eArgTypeNone, "Enable SSH."},
{LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeCommandName,
+ nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific options required for SSH to work."},
};
-static OptionDefinition g_caching_option_table[] = {
+static constexpr OptionDefinition g_caching_option_table[] = {
{LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePath,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath,
"Path in which to store local copies of files."},
};
@@ -1566,14 +1586,14 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
if (process->GetModuleSpec(module_spec.GetFileSpec(),
module_spec.GetArchitecture(),
resolved_module_spec)) {
- if (module_spec.GetUUID().IsValid() == false ||
+ if (!module_spec.GetUUID().IsValid() ||
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
got_module_spec = true;
}
}
}
- if (module_spec.GetArchitecture().IsValid() == false) {
+ if (!module_spec.GetArchitecture().IsValid()) {
Status error;
// No valid architecture was specified, ask the platform for the
// architectures that we should be using (in the correct order) and see if
@@ -1596,7 +1616,7 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
// Get module information from a target.
if (!GetModuleSpec(module_spec.GetFileSpec(), module_spec.GetArchitecture(),
resolved_module_spec)) {
- if (module_spec.GetUUID().IsValid() == false ||
+ if (!module_spec.GetUUID().IsValid() ||
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
return module_resolver(module_spec);
}
@@ -1780,9 +1800,9 @@ uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,
{
FileSpec file_to_use;
if (remote_filename.IsAbsolute())
- file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
- false,
- remote_filename.GetPathStyle());
+ file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
+
+ remote_filename.GetPathStyle());
else
file_to_use = remote_filename;
@@ -1802,9 +1822,19 @@ lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,
error.Clear();
if (!target) {
+ ArchSpec arch;
+ if (target && target->GetArchitecture().IsValid())
+ arch = target->GetArchitecture();
+ else
+ arch = Target::GetDefaultArchitecture();
+
+ const char *triple = "";
+ if (arch.IsValid())
+ triple = arch.GetTriple().getTriple().c_str();
+
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- nullptr, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp);
target = new_target_sp.get();
}
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index c3d8abc9f78d..fb3b758912eb 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -7,25 +7,19 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <atomic>
#include <mutex>
-// Other libraries and framework includes
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Threading.h"
-// Project includes
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRDynamicChecks.h"
@@ -67,9 +61,11 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/SelectHelper.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -116,39 +112,38 @@ public:
}
};
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"disable-memory-cache", OptionValue::eTypeBoolean, false,
- DISABLE_MEM_CACHE_DEFAULT, nullptr, nullptr,
+ DISABLE_MEM_CACHE_DEFAULT, nullptr, {},
"Disable reading and caching of memory in fixed-size units."},
{"extra-startup-command", OptionValue::eTypeArray, false,
- OptionValue::eTypeString, nullptr, nullptr,
+ OptionValue::eTypeString, nullptr, {},
"A list containing extra commands understood by the particular process "
"plugin used. "
"For instance, to turn on debugserver logging set this to "
"\"QSetLogging:bitmask=LOG_DEFAULT;\""},
{"ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr,
+ nullptr, {},
"If true, breakpoints will be ignored during expression evaluation."},
{"unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr, "If true, errors in expression evaluation will unwind "
- "the stack back to the state before the call."},
+ nullptr, {}, "If true, errors in expression evaluation will unwind "
+ "the stack back to the state before the call."},
{"python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, nullptr,
- nullptr, "A path to a python OS plug-in module file that contains a "
- "OperatingSystemPlugIn class."},
+ {}, "A path to a python OS plug-in module file that contains a "
+ "OperatingSystemPlugIn class."},
{"stop-on-sharedlibrary-events", OptionValue::eTypeBoolean, true, false,
- nullptr, nullptr,
+ nullptr, {},
"If true, stop when a shared library is loaded or unloaded."},
{"detach-keeps-stopped", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, detach will attempt to keep the process stopped."},
+ {}, "If true, detach will attempt to keep the process stopped."},
{"memory-cache-line-size", OptionValue::eTypeUInt64, false, 512, nullptr,
- nullptr, "The memory cache line size"},
+ {}, "The memory cache line size"},
{"optimization-warnings", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "If true, warn when stopped in code that is optimized where "
- "stepping and variable availability may not behave as expected."},
+ {}, "If true, warn when stopped in code that is optimized where "
+ "stepping and variable availability may not behave as expected."},
{"stop-on-exec", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr,
- "If true, stop when a shared library is loaded or unloaded."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ nullptr, {},
+ "If true, stop when a shared library is loaded or unloaded."}};
enum {
ePropertyDisableMemCache,
@@ -431,7 +426,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'i': // STDIN for read only
{
FileAction action;
- if (action.Open(STDIN_FILENO, FileSpec{option_arg, false}, true, false))
+ if (action.Open(STDIN_FILENO, FileSpec(option_arg), true, false))
launch_info.AppendFileAction(action);
break;
}
@@ -439,7 +434,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'o': // Open STDOUT for write only
{
FileAction action;
- if (action.Open(STDOUT_FILENO, FileSpec{option_arg, false}, false, true))
+ if (action.Open(STDOUT_FILENO, FileSpec(option_arg), false, true))
launch_info.AppendFileAction(action);
break;
}
@@ -447,7 +442,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'e': // STDERR for write only
{
FileAction action;
- if (action.Open(STDERR_FILENO, FileSpec{option_arg, false}, false, true))
+ if (action.Open(STDERR_FILENO, FileSpec(option_arg), false, true))
launch_info.AppendFileAction(action);
break;
}
@@ -459,7 +454,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'n': // Disable STDIO
{
FileAction action;
- const FileSpec dev_null{FileSystem::DEV_NULL, false};
+ const FileSpec dev_null(FileSystem::DEV_NULL);
if (action.Open(STDIN_FILENO, dev_null, true, false))
launch_info.AppendFileAction(action);
if (action.Open(STDOUT_FILENO, dev_null, false, true))
@@ -470,7 +465,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
}
case 'w':
- launch_info.SetWorkingDirectory(FileSpec{option_arg, false});
+ launch_info.SetWorkingDirectory(FileSpec(option_arg));
break;
case 't': // Open process in new terminal window
@@ -516,7 +511,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'c':
if (!option_arg.empty())
- launch_info.SetShell(FileSpec(option_arg, false));
+ launch_info.SetShell(FileSpec(option_arg));
else
launch_info.SetShell(HostInfo::GetDefaultShell());
break;
@@ -533,52 +528,52 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
return error;
}
-static OptionDefinition g_process_launch_options[] = {
+static constexpr OptionDefinition g_process_launch_options[] = {
{LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Stop at the entry point of the program when launching a process."},
{LLDB_OPT_SET_ALL, false, "disable-aslr", 'A',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Set whether to disable address space layout randomization when launching "
"a process."},
{LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypePlugin,
+ nullptr, {}, 0, eArgTypePlugin,
"Name of the process plugin you want to use."},
{LLDB_OPT_SET_ALL, false, "working-dir", 'w',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0,
+ OptionParser::eRequiredArgument, nullptr, {}, 0,
eArgTypeDirectoryName,
"Set the current working directory to <path> when running the inferior."},
{LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeArchitecture,
+ nullptr, {}, 0, eArgTypeArchitecture,
"Set the architecture for the process to launch when ambiguous."},
{LLDB_OPT_SET_ALL, false, "environment", 'v',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone,
"Specify an environment variable name/value string (--environment "
"NAME=VALUE). Can be specified multiple times for subsequent environment "
"entries."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "shell", 'c',
- OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeFilename,
+ OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeFilename,
"Run the process in a shell (not supported on all platforms)."},
{LLDB_OPT_SET_1, false, "stdin", 'i', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stdin for the process to <filename>."},
{LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stdout for the process to <filename>."},
{LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stderr for the process to <filename>."},
{LLDB_OPT_SET_2, false, "tty", 't', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Start the process in a terminal (not supported on all platforms)."},
{LLDB_OPT_SET_3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Do not set up for terminal I/O to go to running process."},
{LLDB_OPT_SET_4, false, "shell-expand-args", 'X',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Set whether to shell expand arguments to the process when launching."},
};
@@ -1729,6 +1724,10 @@ void Process::SetRunningUserExpression(bool on) {
m_mod_id.SetRunningUserExpression(on);
}
+void Process::SetRunningUtilityFunction(bool on) {
+ m_mod_id.SetRunningUtilityFunction(on);
+}
+
addr_t Process::GetImageInfoAddress() { return LLDB_INVALID_ADDRESS; }
const lldb::ABISP &Process::GetABI() {
@@ -1921,7 +1920,7 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner,
owner->SetBreakpointSite(bp_site_sp);
return m_breakpoint_site_list.Add(bp_site_sp);
} else {
- if (show_error) {
+ if (show_error || use_hardware) {
// Report error for setting breakpoint...
GetTarget().GetDebugger().GetErrorFile()->Printf(
"warning: failed to set breakpoint site at 0x%" PRIx64
@@ -2731,7 +2730,7 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
sizeof(local_exec_file_path));
exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path,
sizeof(platform_exec_file_path));
- if (exe_module->GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(exe_module->GetFileSpec())) {
// Install anything that might need to be installed prior to launching.
// For host systems, this will do nothing, but if we are connected to a
// remote platform it will install any needed binaries
@@ -3211,7 +3210,8 @@ void Process::CompleteAttach() {
}
}
if (new_executable_module_sp) {
- GetTarget().SetExecutableModule(new_executable_module_sp, false);
+ GetTarget().SetExecutableModule(new_executable_module_sp,
+ eLoadDependentsNo);
if (log) {
ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
log->Printf(
@@ -3291,6 +3291,11 @@ Status Process::PrivateResume() {
m_thread_list.DidResume();
if (log)
log->Printf("Process thinks the process has resumed.");
+ } else {
+ if (log)
+ log->Printf(
+ "Process::PrivateResume() DoResume failed.");
+ return error;
}
}
} else {
@@ -4685,7 +4690,12 @@ bool Process::PushProcessIOHandler() {
log->Printf("Process::%s pushing IO handler", __FUNCTION__);
io_handler_sp->SetIsDone(false);
- GetTarget().GetDebugger().PushIOHandler(io_handler_sp);
+ // If we evaluate an utility function, then we don't cancel the current
+ // IOHandler. Our IOHandler is non-interactive and shouldn't disturb the
+ // existing IOHandler that potentially provides the user interface (e.g.
+ // the IOHandler for Editline).
+ bool cancel_top_handler = !m_mod_id.IsRunningUtilityFunction();
+ GetTarget().GetDebugger().PushIOHandler(io_handler_sp, cancel_top_handler);
return true;
}
return false;
@@ -4875,6 +4885,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
thread_plan_sp->SetIsMasterPlan(true);
thread_plan_sp->SetOkayToDiscard(false);
+ // If we are running some utility expression for LLDB, we now have to mark
+ // this in the ProcesModID of this process. This RAII takes care of marking
+ // and reverting the mark it once we are done running the expression.
+ UtilityFunctionScope util_scope(options.IsForUtilityExpr() ? this : nullptr);
+
if (m_private_state.GetValue() != eStateStopped) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
@@ -5842,7 +5857,7 @@ void Process::ModulesDidLoad(ModuleList &module_list) {
// that loaded.
// Iterate over a copy of this language runtime list in case the language
- // runtime ModulesDidLoad somehow causes the language riuntime to be
+ // runtime ModulesDidLoad somehow causes the language runtime to be
// unloaded.
LanguageRuntimeCollection language_runtimes(m_language_runtimes);
for (const auto &pair : language_runtimes) {
@@ -6020,7 +6035,7 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
}
Status
-Process::GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list) {
+Process::GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) {
Status error;
@@ -6028,17 +6043,17 @@ Process::GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list) {
region_list.clear();
do {
- lldb::MemoryRegionInfoSP region_info(new lldb_private::MemoryRegionInfo());
- error = GetMemoryRegionInfo(range_end, *region_info);
+ lldb_private::MemoryRegionInfo region_info;
+ error = GetMemoryRegionInfo(range_end, region_info);
// GetMemoryRegionInfo should only return an error if it is unimplemented.
if (error.Fail()) {
region_list.clear();
break;
}
- range_end = region_info->GetRange().GetRangeEnd();
- if (region_info->GetMapped() == MemoryRegionInfo::eYes) {
- region_list.push_back(region_info);
+ range_end = region_info.GetRange().GetRangeEnd();
+ if (region_info.GetMapped() == MemoryRegionInfo::eYes) {
+ region_list.push_back(std::move(region_info));
}
} while (range_end != LLDB_INVALID_ADDRESS);
@@ -6095,7 +6110,7 @@ void Process::MapSupportedStructuredDataPlugins(
// For each StructuredDataPlugin, if the plugin handles any of the types in
// the supported_type_names, map that type name to that plugin. Stop when
// we've consumed all the type names.
- // FIXME: should we return an error if there are type names nobody
+ // FIXME: should we return an error if there are type names nobody
// supports?
for (uint32_t plugin_index = 0; !const_type_names.empty(); plugin_index++) {
auto create_instance =
@@ -6103,7 +6118,7 @@ void Process::MapSupportedStructuredDataPlugins(
plugin_index);
if (!create_instance)
break;
-
+
// Create the plugin.
StructuredDataPluginSP plugin_sp = (*create_instance)(*this);
if (!plugin_sp) {
diff --git a/source/Target/ProcessInfo.cpp b/source/Target/ProcessInfo.cpp
index ac0350686706..1ada6123fa1e 100644
--- a/source/Target/ProcessInfo.cpp
+++ b/source/Target/ProcessInfo.cpp
@@ -9,12 +9,8 @@
#include "lldb/Target/ProcessInfo.h"
-// C Includes
-// C++ Includes
#include <climits>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/Stream.h"
@@ -29,8 +25,8 @@ ProcessInfo::ProcessInfo()
ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
lldb::pid_t pid)
- : m_executable(name, false), m_arguments(), m_environment(),
- m_uid(UINT32_MAX), m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {}
+ : m_executable(name), m_arguments(), m_environment(), m_uid(UINT32_MAX),
+ m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {}
void ProcessInfo::Clear() {
m_executable.Clear();
@@ -67,7 +63,7 @@ void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,
if (exe_file) {
m_executable = exe_file;
if (add_exe_file_as_first_arg) {
- llvm::SmallString<PATH_MAX> filename;
+ llvm::SmallString<128> filename;
exe_file.GetPath(filename);
if (!filename.empty())
m_arguments.InsertArgumentAtIndex(0, filename);
@@ -96,8 +92,7 @@ void ProcessInfo::SetArguments(char const **argv,
// Yes the first argument is an executable, set it as the executable in
// the launch options. Don't resolve the file path as the path could be a
// remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
+ m_executable.SetFile(first_arg, FileSpec::Style::native);
}
}
}
@@ -113,8 +108,7 @@ void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
// Yes the first argument is an executable, set it as the executable in
// the launch options. Don't resolve the file path as the path could be a
// remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
+ m_executable.SetFile(first_arg, FileSpec::Style::native);
}
}
}
diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp
index 9569750bc5fd..ac1eba04f0cb 100644
--- a/source/Target/ProcessLaunchInfo.cpp
+++ b/source/Target/ProcessLaunchInfo.cpp
@@ -7,19 +7,13 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <climits>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Debugger.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/ProcessLaunchInfo.h"
-#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -108,8 +102,7 @@ bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
bool ProcessLaunchInfo::AppendSuppressFileAction(int fd, bool read,
bool write) {
FileAction file_action;
- if (file_action.Open(fd, FileSpec{FileSystem::DEV_NULL, false}, read,
- write)) {
+ if (file_action.Open(fd, FileSpec(FileSystem::DEV_NULL), read, write)) {
AppendFileAction(file_action);
return true;
}
@@ -151,7 +144,7 @@ const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }
void ProcessLaunchInfo::SetShell(const FileSpec &shell) {
m_shell = shell;
if (m_shell) {
- m_shell.ResolveExecutableLocation();
+ FileSystem::Instance().ResolveExecutableLocation(m_shell);
m_flags.Set(lldb::eLaunchFlagLaunchInShell);
} else
m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
@@ -212,124 +205,38 @@ void ProcessLaunchInfo::SetDetachOnError(bool enable) {
m_flags.Clear(lldb::eLaunchFlagDetachOnError);
}
-void ProcessLaunchInfo::FinalizeFileActions(Target *target,
- bool default_to_use_pty) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // If nothing for stdin or stdout or stderr was specified, then check the
- // process for any default settings that were set with "settings set"
- if (GetFileActionForFD(STDIN_FILENO) == nullptr ||
- GetFileActionForFD(STDOUT_FILENO) == nullptr ||
- GetFileActionForFD(STDERR_FILENO) == nullptr) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr "
- "was not set, evaluating default handling",
- __FUNCTION__);
-
- if (m_flags.Test(eLaunchFlagLaunchInTTY)) {
- // Do nothing, if we are launching in a remote terminal no file actions
- // should be done at all.
- return;
- }
-
- if (m_flags.Test(eLaunchFlagDisableSTDIO)) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s eLaunchFlagDisableSTDIO set, adding "
- "suppression action for stdin, stdout and stderr",
- __FUNCTION__);
- AppendSuppressFileAction(STDIN_FILENO, true, false);
- AppendSuppressFileAction(STDOUT_FILENO, false, true);
- AppendSuppressFileAction(STDERR_FILENO, false, true);
- } else {
- // Check for any values that might have gotten set with any of: (lldb)
- // settings set target.input-path (lldb) settings set target.output-path
- // (lldb) settings set target.error-path
- FileSpec in_file_spec;
- FileSpec out_file_spec;
- FileSpec err_file_spec;
- if (target) {
- // Only override with the target settings if we don't already have an
- // action for in, out or error
- if (GetFileActionForFD(STDIN_FILENO) == nullptr)
- in_file_spec = target->GetStandardInputPath();
- if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
- out_file_spec = target->GetStandardOutputPath();
- if (GetFileActionForFD(STDERR_FILENO) == nullptr)
- err_file_spec = target->GetStandardErrorPath();
- }
-
- if (log)
- log->Printf("ProcessLaunchInfo::%s target stdin='%s', target "
- "stdout='%s', stderr='%s'",
- __FUNCTION__,
- in_file_spec ? in_file_spec.GetCString() : "<null>",
- out_file_spec ? out_file_spec.GetCString() : "<null>",
- err_file_spec ? err_file_spec.GetCString() : "<null>");
-
- if (in_file_spec) {
- AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stdin open file action for %s",
- __FUNCTION__, in_file_spec.GetCString());
- }
-
- if (out_file_spec) {
- AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stdout open file action for %s",
- __FUNCTION__, out_file_spec.GetCString());
- }
-
- if (err_file_spec) {
- AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stderr open file action for %s",
- __FUNCTION__, err_file_spec.GetCString());
- }
-
- if (default_to_use_pty &&
- (!in_file_spec || !out_file_spec || !err_file_spec)) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s default_to_use_pty is set, and at "
- "least one stdin/stderr/stdout is unset, so generating a "
- "pty to use for it",
- __FUNCTION__);
+llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS);
+ LLDB_LOG(log, "Generating a pty to use for stdin/out/err");
- int open_flags = O_RDWR | O_NOCTTY;
+ int open_flags = O_RDWR | O_NOCTTY;
#if !defined(_WIN32)
- // We really shouldn't be specifying platform specific flags that are
- // intended for a system call in generic code. But this will have to
- // do for now.
- open_flags |= O_CLOEXEC;
+ // We really shouldn't be specifying platform specific flags that are
+ // intended for a system call in generic code. But this will have to
+ // do for now.
+ open_flags |= O_CLOEXEC;
#endif
- if (m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
- const FileSpec slave_file_spec{m_pty->GetSlaveName(nullptr, 0),
- false};
-
- // Only use the slave tty if we don't have anything specified for
- // input and don't have an action for stdin
- if (!in_file_spec && GetFileActionForFD(STDIN_FILENO) == nullptr) {
- AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
- }
-
- // Only use the slave tty if we don't have anything specified for
- // output and don't have an action for stdout
- if (!out_file_spec && GetFileActionForFD(STDOUT_FILENO) == nullptr) {
- AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
- }
-
- // Only use the slave tty if we don't have anything specified for
- // error and don't have an action for stderr
- if (!err_file_spec && GetFileActionForFD(STDERR_FILENO) == nullptr) {
- AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
- }
- }
- }
- }
+ if (!m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "PTY::OpenFirstAvailableMaster failed");
}
+ const FileSpec slave_file_spec(m_pty->GetSlaveName(nullptr, 0));
+
+ // Only use the slave tty if we don't have anything specified for
+ // input and don't have an action for stdin
+ if (GetFileActionForFD(STDIN_FILENO) == nullptr)
+ AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
+
+ // Only use the slave tty if we don't have anything specified for
+ // output and don't have an action for stdout
+ if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
+ AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
+
+ // Only use the slave tty if we don't have anything specified for
+ // error and don't have an action for stderr
+ if (GetFileActionForFD(STDERR_FILENO) == nullptr)
+ AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
+ return llvm::Error::success();
}
bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
@@ -359,7 +266,7 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
// Add a modified PATH environment variable in case argv[0] is a
// relative path.
const char *argv0 = argv[0];
- FileSpec arg_spec(argv0, false);
+ FileSpec arg_spec(argv0);
if (arg_spec.IsRelative()) {
// We have a relative path to our executable which may not work if we
// just try to run "a.out" (without it being converted to "./a.out")
@@ -439,10 +346,3 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
}
return false;
}
-
-ListenerSP ProcessLaunchInfo::GetListenerForProcess(Debugger &debugger) {
- if (m_listener_sp)
- return m_listener_sp;
- else
- return debugger.GetListener();
-}
diff --git a/source/Target/Queue.cpp b/source/Target/Queue.cpp
index 45fdbea13db5..c0683d10b151 100644
--- a/source/Target/Queue.cpp
+++ b/source/Target/Queue.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Queue.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/QueueList.h"
diff --git a/source/Target/QueueItem.cpp b/source/Target/QueueItem.cpp
index fe58980c01c1..a20fa918a758 100644
--- a/source/Target/QueueItem.cpp
+++ b/source/Target/QueueItem.cpp
@@ -94,7 +94,7 @@ std::string QueueItem::GetQueueLabel() {
ProcessSP QueueItem::GetProcessSP() { return m_process_wp.lock(); }
void QueueItem::FetchEntireItem() {
- if (m_have_fetched_entire_item == true)
+ if (m_have_fetched_entire_item)
return;
ProcessSP process_sp = m_process_wp.lock();
if (process_sp) {
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
index eaec03d9b595..976f9e8b45e7 100644
--- a/source/Target/RegisterContext.cpp
+++ b/source/Target/RegisterContext.cpp
@@ -7,14 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Target/ExecutionContext.h"
@@ -24,6 +18,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/RegisterNumber.cpp b/source/Target/RegisterNumber.cpp
index d1bb8adf56e1..8b01bd103395 100644
--- a/source/Target/RegisterNumber.cpp
+++ b/source/Target/RegisterNumber.cpp
@@ -61,26 +61,15 @@ bool RegisterNumber::operator==(RegisterNumber &rhs) {
return false;
if (m_kind == rhs.m_kind) {
- if (m_regnum == rhs.m_regnum)
- return true;
- else
- return false;
+ return m_regnum == rhs.m_regnum;
}
uint32_t rhs_regnum = rhs.GetAsKind(m_kind);
if (rhs_regnum != LLDB_INVALID_REGNUM) {
- if (m_regnum == rhs_regnum)
- return true;
- else
- return false;
+ return m_regnum == rhs_regnum;
}
uint32_t lhs_regnum = GetAsKind(rhs.m_kind);
- {
- if (lhs_regnum == rhs.m_regnum)
- return true;
- else
- return false;
- }
+ { return lhs_regnum == rhs.m_regnum; }
return false;
}
diff --git a/source/Target/SectionLoadHistory.cpp b/source/Target/SectionLoadHistory.cpp
index 5844da5d41e9..1229933793ff 100644
--- a/source/Target/SectionLoadHistory.cpp
+++ b/source/Target/SectionLoadHistory.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/SectionLoadHistory.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp
index 6839aaccaa52..ea9f7ea9911c 100644
--- a/source/Target/SectionLoadList.cpp
+++ b/source/Target/SectionLoadList.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/SectionLoadList.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 2b9260f95f3f..3cea6444596c 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -7,17 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,8 +27,12 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -49,20 +48,19 @@ using namespace lldb_private;
StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
user_id_t unwind_frame_index, addr_t cfa,
- bool cfa_is_valid, addr_t pc, uint32_t stop_id,
- bool stop_id_is_valid, bool is_history_frame,
+ bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
const SymbolContext *sc_ptr)
: m_thread_wp(thread_sp), m_frame_index(frame_idx),
m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(),
m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
- m_stop_id(stop_id), m_stop_id_is_valid(stop_id_is_valid),
- m_is_history_frame(is_history_frame), m_variable_list_sp(),
- m_variable_list_value_objects(), m_disassembly(), m_mutex() {
+ m_stack_frame_kind(kind), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
+ m_mutex() {
// If we don't have a CFA value, use the frame index for our StackID so that
// recursive functions properly aren't confused with one another on a history
// stack.
- if (m_is_history_frame && !m_cfa_is_valid) {
+ if (IsHistorical() && !m_cfa_is_valid) {
m_id.SetCFA(m_frame_index);
}
@@ -80,9 +78,9 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
m_concrete_frame_index(unwind_frame_index),
m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),
m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
- m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0),
- m_stop_id_is_valid(false), m_is_history_frame(false),
- m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(),
+ m_frame_base_error(), m_cfa_is_valid(true),
+ m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
m_mutex() {
if (sc_ptr != nullptr) {
m_sc = *sc_ptr;
@@ -106,9 +104,9 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,
nullptr),
m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
- m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0),
- m_stop_id_is_valid(false), m_is_history_frame(false),
- m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(),
+ m_frame_base_error(), m_cfa_is_valid(true),
+ m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
m_mutex() {
if (sc_ptr != nullptr) {
m_sc = *sc_ptr;
@@ -210,7 +208,7 @@ const Address &StackFrame::GetFrameCodeAddress() {
bool StackFrame::ChangePC(addr_t pc) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// We can't change the pc value of a history stack frame - it is immutable.
- if (m_is_history_frame)
+ if (IsHistorical())
return false;
m_frame_code_addr.SetRawAddress(pc);
m_sc.Clear(false);
@@ -266,7 +264,8 @@ Block *StackFrame::GetFrameBlock() {
// StackFrame object, everyone will have as much information as possible and no
// one will ever have to look things up manually.
//----------------------------------------------------------------------
-const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
+const SymbolContext &
+StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// Copy our internal symbol context into "sc".
if ((m_flags.Get() & resolve_scope) != resolve_scope) {
@@ -318,7 +317,7 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
// haven't already tried to lookup one of those things. If we haven't
// then we will do the query.
- uint32_t actual_resolve_scope = 0;
+ SymbolContextItem actual_resolve_scope = SymbolContextItem(0);
if (resolve_scope & eSymbolContextCompUnit) {
if (m_flags.IsClear(eSymbolContextCompUnit)) {
@@ -456,7 +455,7 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
bool must_have_valid_location) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// We can't fetch variable information for a history stack frame.
- if (m_is_history_frame)
+ if (IsHistorical())
return VariableListSP();
VariableListSP var_list_sp(new VariableList);
@@ -490,7 +489,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
VariableSP &var_sp, Status &error) {
llvm::StringRef original_var_expr = var_expr;
// We can't fetch variable information for a history stack frame.
- if (m_is_history_frame)
+ if (IsHistorical())
return ValueObjectSP();
if (var_expr.empty()) {
@@ -1080,9 +1079,9 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
exe_ctx.GetTargetPtr());
- if (m_sc.function->GetFrameBaseExpression().Evaluate(
+ if (!m_sc.function->GetFrameBaseExpression().Evaluate(
&exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr,
- expr_value, &m_frame_base_error) == false) {
+ expr_value, &m_frame_base_error)) {
// We should really have an error if evaluate returns, but in case we
// don't, lets set the error to something at least.
if (m_frame_base_error.Success())
@@ -1135,7 +1134,7 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
DynamicValueType use_dynamic) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
ValueObjectSP valobj_sp;
- if (m_is_history_frame) {
+ if (IsHistorical()) {
return valobj_sp;
}
VariableList *var_list = GetVariableList(true);
@@ -1164,7 +1163,7 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp,
DynamicValueType use_dynamic) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_is_history_frame)
+ if (IsHistorical())
return ValueObjectSP();
// Check to make sure we aren't already tracking this variable?
@@ -1194,6 +1193,14 @@ bool StackFrame::IsInlined() {
return false;
}
+bool StackFrame::IsHistorical() const {
+ return m_stack_frame_kind == StackFrame::Kind::History;
+}
+
+bool StackFrame::IsArtificial() const {
+ return m_stack_frame_kind == StackFrame::Kind::Artificial;
+}
+
lldb::LanguageType StackFrame::GetLanguage() {
CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
if (cu)
@@ -1709,6 +1716,41 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
GetFrameCodeAddress());
}
+lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
+ ValueObjectSP value_sp;
+
+ if (!name)
+ return value_sp;
+
+ TargetSP target_sp = CalculateTarget();
+ ProcessSP process_sp = CalculateProcess();
+
+ if (!target_sp && !process_sp)
+ return value_sp;
+
+ VariableList variable_list;
+ VariableSP var_sp;
+ SymbolContext sc(GetSymbolContext(eSymbolContextBlock));
+
+ if (sc.block) {
+ const bool can_create = true;
+ const bool get_parent_variables = true;
+ const bool stop_if_block_is_inlined_function = true;
+
+ if (sc.block->AppendVariables(
+ can_create, get_parent_variables, stop_if_block_is_inlined_function,
+ [this](Variable *v) { return v->IsInScope(this); },
+ &variable_list)) {
+ var_sp = variable_list.FindVariable(name);
+ }
+
+ if (var_sp)
+ value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
+ }
+
+ return value_sp;
+}
+
TargetSP StackFrame::CalculateTarget() {
TargetSP target_sp;
ThreadSP thread_sp(GetThread());
@@ -1910,3 +1952,11 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
}
return true;
}
+
+RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
+ if (!m_recognized_frame_sp) {
+ m_recognized_frame_sp =
+ StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame());
+ }
+ return m_recognized_frame_sp;
+}
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 2380a91df41d..fc9fcec6c076 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackFrameList.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -27,6 +23,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
+#include "llvm/ADT/SmallPtrSet.h"
//#define DEBUG_STACK_FRAMES 1
@@ -81,127 +78,119 @@ uint32_t StackFrameList::GetCurrentInlinedDepth() {
}
void StackFrameList::ResetCurrentInlinedDepth() {
+ if (!m_show_inlined_frames)
+ return;
+
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_show_inlined_frames) {
- GetFramesUpTo(0);
- if (m_frames.empty())
- return;
- if (!m_frames[0]->IsInlined()) {
- m_current_inlined_depth = UINT32_MAX;
- m_current_inlined_pc = LLDB_INVALID_ADDRESS;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf(
- "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
- } else {
- // We only need to do something special about inlined blocks when we are
- // at the beginning of an inlined function:
- // FIXME: We probably also have to do something special if the PC is at
- // the END
- // of an inlined function, which coincides with the end of either its
- // containing function or another inlined function.
-
- lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
- Block *block_ptr = m_frames[0]->GetFrameBlock();
- if (block_ptr) {
- Address pc_as_address;
- pc_as_address.SetLoadAddress(curr_pc,
- &(m_thread.GetProcess()->GetTarget()));
- AddressRange containing_range;
- if (block_ptr->GetRangeContainingAddress(pc_as_address,
- containing_range)) {
- if (pc_as_address == containing_range.GetBaseAddress()) {
- // If we got here because of a breakpoint hit, then set the inlined
- // depth depending on where the breakpoint was set. If we got here
- // because of a crash, then set the inlined depth to the deepest
- // most block. Otherwise, we stopped here naturally as the result
- // of a step, so set ourselves in the containing frame of the whole
- // set of nested inlines, so the user can then "virtually" step
- // into the frames one by one, or next over the whole mess. Note:
- // We don't have to handle being somewhere in the middle of the
- // stack here, since ResetCurrentInlinedDepth doesn't get called if
- // there is a valid inlined depth set.
- StopInfoSP stop_info_sp = m_thread.GetStopInfo();
- if (stop_info_sp) {
- switch (stop_info_sp->GetStopReason()) {
- case eStopReasonWatchpoint:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonSignal:
- // In all these cases we want to stop in the deepest most
- // frame.
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = 0;
- break;
- case eStopReasonBreakpoint: {
- // FIXME: Figure out what this break point is doing, and set the
- // inline depth
- // appropriately. Be careful to take into account breakpoints
- // that implement step over prologue, since that should do the
- // default calculation. For now, if the breakpoints
- // corresponding to this hit are all internal,
- // I set the stop location to the top of the inlined stack,
- // since that will make
- // things like stepping over prologues work right. But if
- // there are any non-internal breakpoints I do to the bottom of
- // the stack, since that was the old behavior.
- uint32_t bp_site_id = stop_info_sp->GetValue();
- BreakpointSiteSP bp_site_sp(
- m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
- bp_site_id));
- bool all_internal = true;
- if (bp_site_sp) {
- uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
- for (uint32_t i = 0; i < num_owners; i++) {
- Breakpoint &bp_ref =
- bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
- if (!bp_ref.IsInternal()) {
- all_internal = false;
- }
- }
- }
- if (!all_internal) {
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = 0;
- break;
- }
- }
- LLVM_FALLTHROUGH;
- default: {
- // Otherwise, we should set ourselves at the container of the
- // inlining, so that the user can descend into them. So first
- // we check whether we have more than one inlined block sharing
- // this PC:
- int num_inlined_functions = 0;
-
- for (Block *container_ptr = block_ptr->GetInlinedParent();
- container_ptr != nullptr;
- container_ptr = container_ptr->GetInlinedParent()) {
- if (!container_ptr->GetRangeContainingAddress(
- pc_as_address, containing_range))
- break;
- if (pc_as_address != containing_range.GetBaseAddress())
- break;
-
- num_inlined_functions++;
- }
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = num_inlined_functions + 1;
- Log *log(
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf("ResetCurrentInlinedDepth: setting inlined "
- "depth: %d 0x%" PRIx64 ".\n",
- m_current_inlined_depth, curr_pc);
-
- } break;
- }
- }
- }
+ GetFramesUpTo(0);
+ if (m_frames.empty())
+ return;
+ if (!m_frames[0]->IsInlined()) {
+ m_current_inlined_depth = UINT32_MAX;
+ m_current_inlined_pc = LLDB_INVALID_ADDRESS;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf(
+ "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
+ return;
+ }
+
+ // We only need to do something special about inlined blocks when we are
+ // at the beginning of an inlined function:
+ // FIXME: We probably also have to do something special if the PC is at
+ // the END of an inlined function, which coincides with the end of either
+ // its containing function or another inlined function.
+
+ Block *block_ptr = m_frames[0]->GetFrameBlock();
+ if (!block_ptr)
+ return;
+
+ Address pc_as_address;
+ lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
+ pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget()));
+ AddressRange containing_range;
+ if (!block_ptr->GetRangeContainingAddress(pc_as_address, containing_range) ||
+ pc_as_address != containing_range.GetBaseAddress())
+ return;
+
+ // If we got here because of a breakpoint hit, then set the inlined depth
+ // depending on where the breakpoint was set. If we got here because of a
+ // crash, then set the inlined depth to the deepest most block. Otherwise,
+ // we stopped here naturally as the result of a step, so set ourselves in the
+ // containing frame of the whole set of nested inlines, so the user can then
+ // "virtually" step into the frames one by one, or next over the whole mess.
+ // Note: We don't have to handle being somewhere in the middle of the stack
+ // here, since ResetCurrentInlinedDepth doesn't get called if there is a
+ // valid inlined depth set.
+ StopInfoSP stop_info_sp = m_thread.GetStopInfo();
+ if (!stop_info_sp)
+ return;
+ switch (stop_info_sp->GetStopReason()) {
+ case eStopReasonWatchpoint:
+ case eStopReasonException:
+ case eStopReasonExec:
+ case eStopReasonSignal:
+ // In all these cases we want to stop in the deepest frame.
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = 0;
+ break;
+ case eStopReasonBreakpoint: {
+ // FIXME: Figure out what this break point is doing, and set the inline
+ // depth appropriately. Be careful to take into account breakpoints that
+ // implement step over prologue, since that should do the default
+ // calculation. For now, if the breakpoints corresponding to this hit are
+ // all internal, I set the stop location to the top of the inlined stack,
+ // since that will make things like stepping over prologues work right.
+ // But if there are any non-internal breakpoints I do to the bottom of the
+ // stack, since that was the old behavior.
+ uint32_t bp_site_id = stop_info_sp->GetValue();
+ BreakpointSiteSP bp_site_sp(
+ m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id));
+ bool all_internal = true;
+ if (bp_site_sp) {
+ uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
+ for (uint32_t i = 0; i < num_owners; i++) {
+ Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
+ if (!bp_ref.IsInternal()) {
+ all_internal = false;
}
}
}
+ if (!all_internal) {
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = 0;
+ break;
+ }
+ }
+ LLVM_FALLTHROUGH;
+ default: {
+ // Otherwise, we should set ourselves at the container of the inlining, so
+ // that the user can descend into them. So first we check whether we have
+ // more than one inlined block sharing this PC:
+ int num_inlined_functions = 0;
+
+ for (Block *container_ptr = block_ptr->GetInlinedParent();
+ container_ptr != nullptr;
+ container_ptr = container_ptr->GetInlinedParent()) {
+ if (!container_ptr->GetRangeContainingAddress(pc_as_address,
+ containing_range))
+ break;
+ if (pc_as_address != containing_range.GetBaseAddress())
+ break;
+
+ num_inlined_functions++;
+ }
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = num_inlined_functions + 1;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf("ResetCurrentInlinedDepth: setting inlined "
+ "depth: %d 0x%" PRIx64 ".\n",
+ m_current_inlined_depth, curr_pc);
+
+ break;
+ }
}
}
@@ -226,8 +215,202 @@ void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth) {
m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
}
+void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
+ Unwind *unwinder) {
+ assert(m_thread.IsValid() && "Expected valid thread");
+ assert(m_frames.size() <= end_idx && "Expected there to be frames to fill");
+
+ if (end_idx < m_concrete_frames_fetched)
+ return;
+
+ if (!unwinder)
+ return;
+
+ uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
+ if (num_frames <= end_idx + 1) {
+ // Done unwinding.
+ m_concrete_frames_fetched = UINT32_MAX;
+ }
+
+ // Don't create the frames eagerly. Defer this work to GetFrameAtIndex,
+ // which can lazily query the unwinder to create frames.
+ m_frames.resize(num_frames);
+}
+
+/// Find the unique path through the call graph from \p begin (with return PC
+/// \p return_pc) to \p end. On success this path is stored into \p path, and
+/// on failure \p path is unchanged.
+static void FindInterveningFrames(Function &begin, Function &end,
+ Target &target, addr_t return_pc,
+ std::vector<Function *> &path,
+ ModuleList &images, Log *log) {
+ LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
+ begin.GetDisplayName(), end.GetDisplayName(), return_pc);
+
+ // Find a non-tail calling edge with the correct return PC.
+ auto first_level_edges = begin.GetCallEdges();
+ if (log)
+ for (const CallEdge &edge : first_level_edges)
+ LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}",
+ edge.GetReturnPCAddress(begin, target));
+ auto first_edge_it = std::lower_bound(
+ first_level_edges.begin(), first_level_edges.end(), return_pc,
+ [&](const CallEdge &edge, addr_t target_pc) {
+ return edge.GetReturnPCAddress(begin, target) < target_pc;
+ });
+ if (first_edge_it == first_level_edges.end() ||
+ first_edge_it->GetReturnPCAddress(begin, target) != return_pc) {
+ LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}",
+ begin.GetDisplayName(), return_pc);
+ return;
+ }
+ CallEdge &first_edge = const_cast<CallEdge &>(*first_edge_it);
+
+ // The first callee may not be resolved, or there may be nothing to fill in.
+ Function *first_callee = first_edge.GetCallee(images);
+ if (!first_callee) {
+ LLDB_LOG(log, "Could not resolve callee");
+ return;
+ }
+ if (first_callee == &end) {
+ LLDB_LOG(log, "Not searching further, first callee is {0} (retn-PC: {1:x})",
+ end.GetDisplayName(), return_pc);
+ return;
+ }
+
+ // Run DFS on the tail-calling edges out of the first callee to find \p end.
+ // Fully explore the set of functions reachable from the first edge via tail
+ // calls in order to detect ambiguous executions.
+ struct DFS {
+ std::vector<Function *> active_path = {};
+ std::vector<Function *> solution_path = {};
+ llvm::SmallPtrSet<Function *, 2> visited_nodes = {};
+ bool ambiguous = false;
+ Function *end;
+ ModuleList &images;
+
+ DFS(Function *end, ModuleList &images) : end(end), images(images) {}
+
+ void search(Function *first_callee, std::vector<Function *> &path) {
+ dfs(first_callee);
+ if (!ambiguous)
+ path = std::move(solution_path);
+ }
+
+ void dfs(Function *callee) {
+ // Found a path to the target function.
+ if (callee == end) {
+ if (solution_path.empty())
+ solution_path = active_path;
+ else
+ ambiguous = true;
+ return;
+ }
+
+ // Terminate the search if tail recursion is found, or more generally if
+ // there's more than one way to reach a target. This errs on the side of
+ // caution: it conservatively stops searching when some solutions are
+ // still possible to save time in the average case.
+ if (!visited_nodes.insert(callee).second) {
+ ambiguous = true;
+ return;
+ }
+
+ // Search the calls made from this callee.
+ active_path.push_back(callee);
+ for (CallEdge &edge : callee->GetTailCallingEdges()) {
+ Function *next_callee = edge.GetCallee(images);
+ if (!next_callee)
+ continue;
+
+ dfs(next_callee);
+ if (ambiguous)
+ return;
+ }
+ active_path.pop_back();
+ }
+ };
+
+ DFS(&end, images).search(first_callee, path);
+}
+
+/// Given that \p next_frame will be appended to the frame list, synthesize
+/// tail call frames between the current end of the list and \p next_frame.
+/// If any frames are added, adjust the frame index of \p next_frame.
+///
+/// --------------
+/// | ... | <- Completed frames.
+/// --------------
+/// | prev_frame |
+/// --------------
+/// | ... | <- Artificial frames inserted here.
+/// --------------
+/// | next_frame |
+/// --------------
+/// | ... | <- Not-yet-visited frames.
+/// --------------
+void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
+ TargetSP target_sp = next_frame.CalculateTarget();
+ if (!target_sp)
+ return;
+
+ lldb::RegisterContextSP next_reg_ctx_sp = next_frame.GetRegisterContext();
+ if (!next_reg_ctx_sp)
+ return;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ assert(!m_frames.empty() && "Cannot synthesize frames in an empty stack");
+ StackFrame &prev_frame = *m_frames.back().get();
+
+ // Find the functions prev_frame and next_frame are stopped in. The function
+ // objects are needed to search the lazy call graph for intervening frames.
+ Function *prev_func =
+ prev_frame.GetSymbolContext(eSymbolContextFunction).function;
+ if (!prev_func) {
+ LLDB_LOG(log, "SynthesizeTailCallFrames: can't find previous function");
+ return;
+ }
+ Function *next_func =
+ next_frame.GetSymbolContext(eSymbolContextFunction).function;
+ if (!next_func) {
+ LLDB_LOG(log, "SynthesizeTailCallFrames: can't find next function");
+ return;
+ }
+
+ // Try to find the unique sequence of (tail) calls which led from next_frame
+ // to prev_frame.
+ std::vector<Function *> path;
+ addr_t return_pc = next_reg_ctx_sp->GetPC();
+ Target &target = *target_sp.get();
+ ModuleList &images = next_frame.CalculateTarget()->GetImages();
+ FindInterveningFrames(*next_func, *prev_func, target, return_pc, path, images,
+ log);
+
+ // Push synthetic tail call frames.
+ for (Function *callee : llvm::reverse(path)) {
+ uint32_t frame_idx = m_frames.size();
+ uint32_t concrete_frame_idx = next_frame.GetConcreteFrameIndex();
+ addr_t cfa = LLDB_INVALID_ADDRESS;
+ bool cfa_is_valid = false;
+ addr_t pc =
+ callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
+ SymbolContext sc;
+ callee->CalculateSymbolContext(&sc);
+ auto synth_frame = std::make_shared<StackFrame>(
+ m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
+ cfa_is_valid, pc, StackFrame::Kind::Artificial, &sc);
+ m_frames.push_back(synth_frame);
+ LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
+ }
+
+ // If any frames were created, adjust next_frame's index.
+ if (!path.empty())
+ next_frame.SetFrameIndex(m_frames.size());
+}
+
void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
- // this makes sure we do not fetch frames for an invalid thread
+ // Do not fetch frames for an invalid thread.
if (!m_thread.IsValid())
return;
@@ -238,201 +421,189 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
Unwind *unwinder = m_thread.GetUnwinder();
- if (m_show_inlined_frames) {
+ if (!m_show_inlined_frames) {
+ GetOnlyConcreteFramesUpTo(end_idx, unwinder);
+ return;
+ }
+
#if defined(DEBUG_STACK_FRAMES)
- StreamFile s(stdout, false);
+ StreamFile s(stdout, false);
#endif
- // If we are hiding some frames from the outside world, we need to add
- // those onto the total count of frames to fetch. However, we don't need
- // to do that if end_idx is 0 since in that case we always get the first
- // concrete frame and all the inlined frames below it... And of course, if
- // end_idx is UINT32_MAX that means get all, so just do that...
-
- uint32_t inlined_depth = 0;
- if (end_idx > 0 && end_idx != UINT32_MAX) {
- inlined_depth = GetCurrentInlinedDepth();
- if (inlined_depth != UINT32_MAX) {
- if (end_idx > 0)
- end_idx += inlined_depth;
- }
+ // If we are hiding some frames from the outside world, we need to add
+ // those onto the total count of frames to fetch. However, we don't need
+ // to do that if end_idx is 0 since in that case we always get the first
+ // concrete frame and all the inlined frames below it... And of course, if
+ // end_idx is UINT32_MAX that means get all, so just do that...
+
+ uint32_t inlined_depth = 0;
+ if (end_idx > 0 && end_idx != UINT32_MAX) {
+ inlined_depth = GetCurrentInlinedDepth();
+ if (inlined_depth != UINT32_MAX) {
+ if (end_idx > 0)
+ end_idx += inlined_depth;
}
+ }
- StackFrameSP unwind_frame_sp;
- do {
- uint32_t idx = m_concrete_frames_fetched++;
- lldb::addr_t pc = LLDB_INVALID_ADDRESS;
- lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
- if (idx == 0) {
- // We might have already created frame zero, only create it if we need
- // to
- if (m_frames.empty()) {
- RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
-
- if (reg_ctx_sp) {
- const bool success =
- unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- // There shouldn't be any way not to get the frame info for frame
- // 0. But if the unwinder can't make one, lets make one by hand
- // with the
- // SP as the CFA and see if that gets any further.
- if (!success) {
- cfa = reg_ctx_sp->GetSP();
- pc = reg_ctx_sp->GetPC();
- }
-
- unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
- m_frames.size(), idx,
- reg_ctx_sp, cfa, pc, nullptr));
- m_frames.push_back(unwind_frame_sp);
+ StackFrameSP unwind_frame_sp;
+ do {
+ uint32_t idx = m_concrete_frames_fetched++;
+ lldb::addr_t pc = LLDB_INVALID_ADDRESS;
+ lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
+ if (idx == 0) {
+ // We might have already created frame zero, only create it if we need
+ // to.
+ if (m_frames.empty()) {
+ RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
+
+ if (reg_ctx_sp) {
+ const bool success =
+ unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ // There shouldn't be any way not to get the frame info for frame
+ // 0. But if the unwinder can't make one, lets make one by hand
+ // with the SP as the CFA and see if that gets any further.
+ if (!success) {
+ cfa = reg_ctx_sp->GetSP();
+ pc = reg_ctx_sp->GetPC();
}
- } else {
- unwind_frame_sp = m_frames.front();
- cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
+
+ unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
+ m_frames.size(), idx, reg_ctx_sp,
+ cfa, pc, nullptr));
+ m_frames.push_back(unwind_frame_sp);
}
} else {
- const bool success =
- unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- if (!success) {
- // We've gotten to the end of the stack.
- SetAllFramesFetched();
- break;
- }
- const bool cfa_is_valid = true;
- const bool stop_id_is_valid = false;
- const bool is_history_frame = false;
- unwind_frame_sp.reset(new StackFrame(
- m_thread.shared_from_this(), m_frames.size(), idx, cfa,
- cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, nullptr));
- m_frames.push_back(unwind_frame_sp);
+ unwind_frame_sp = m_frames.front();
+ cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
}
+ } else {
+ const bool success =
+ unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ if (!success) {
+ // We've gotten to the end of the stack.
+ SetAllFramesFetched();
+ break;
+ }
+ const bool cfa_is_valid = true;
+ unwind_frame_sp.reset(
+ new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx, cfa,
+ cfa_is_valid, pc, StackFrame::Kind::Regular, nullptr));
- assert(unwind_frame_sp);
- SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
- eSymbolContextBlock | eSymbolContextFunction);
- Block *unwind_block = unwind_sc.block;
- if (unwind_block) {
- Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
- TargetSP target_sp = m_thread.CalculateTarget();
- // Be sure to adjust the frame address to match the address that was
- // used to lookup the symbol context above. If we are in the first
- // concrete frame, then we lookup using the current address, else we
- // decrement the address by one to get the correct location.
- if (idx > 0) {
- if (curr_frame_address.GetOffset() == 0) {
- // If curr_frame_address points to the first address in a section
- // then after adjustment it will point to an other section. In that
- // case resolve the address again to the correct section plus
- // offset form.
- addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
- target_sp.get(), AddressClass::eCode);
- curr_frame_address.SetOpcodeLoadAddress(
- load_addr - 1, target_sp.get(), AddressClass::eCode);
- } else {
- curr_frame_address.Slide(-1);
- }
- }
-
- SymbolContext next_frame_sc;
- Address next_frame_address;
+ // Create synthetic tail call frames between the previous frame and the
+ // newly-found frame. The new frame's index may change after this call,
+ // although its concrete index will stay the same.
+ SynthesizeTailCallFrames(*unwind_frame_sp.get());
- while (unwind_sc.GetParentOfInlinedScope(
- curr_frame_address, next_frame_sc, next_frame_address)) {
- next_frame_sc.line_entry.ApplyFileMappings(target_sp);
- StackFrameSP frame_sp(
- new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
- unwind_frame_sp->GetRegisterContextSP(), cfa,
- next_frame_address, &next_frame_sc));
+ m_frames.push_back(unwind_frame_sp);
+ }
- m_frames.push_back(frame_sp);
- unwind_sc = next_frame_sc;
- curr_frame_address = next_frame_address;
+ assert(unwind_frame_sp);
+ SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
+ eSymbolContextBlock | eSymbolContextFunction);
+ Block *unwind_block = unwind_sc.block;
+ if (unwind_block) {
+ Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
+ TargetSP target_sp = m_thread.CalculateTarget();
+ // Be sure to adjust the frame address to match the address that was
+ // used to lookup the symbol context above. If we are in the first
+ // concrete frame, then we lookup using the current address, else we
+ // decrement the address by one to get the correct location.
+ if (idx > 0) {
+ if (curr_frame_address.GetOffset() == 0) {
+ // If curr_frame_address points to the first address in a section
+ // then after adjustment it will point to an other section. In that
+ // case resolve the address again to the correct section plus
+ // offset form.
+ addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
+ target_sp.get(), AddressClass::eCode);
+ curr_frame_address.SetOpcodeLoadAddress(
+ load_addr - 1, target_sp.get(), AddressClass::eCode);
+ } else {
+ curr_frame_address.Slide(-1);
}
}
- } while (m_frames.size() - 1 < end_idx);
- // Don't try to merge till you've calculated all the frames in this stack.
- if (GetAllFramesFetched() && m_prev_frames_sp) {
- StackFrameList *prev_frames = m_prev_frames_sp.get();
- StackFrameList *curr_frames = this;
+ SymbolContext next_frame_sc;
+ Address next_frame_address;
+
+ while (unwind_sc.GetParentOfInlinedScope(
+ curr_frame_address, next_frame_sc, next_frame_address)) {
+ next_frame_sc.line_entry.ApplyFileMappings(target_sp);
+ StackFrameSP frame_sp(
+ new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
+ unwind_frame_sp->GetRegisterContextSP(), cfa,
+ next_frame_address, &next_frame_sc));
+
+ m_frames.push_back(frame_sp);
+ unwind_sc = next_frame_sc;
+ curr_frame_address = next_frame_address;
+ }
+ }
+ } while (m_frames.size() - 1 < end_idx);
-// curr_frames->m_current_inlined_depth = prev_frames->m_current_inlined_depth;
-// curr_frames->m_current_inlined_pc = prev_frames->m_current_inlined_pc;
-// printf ("GetFramesUpTo: Copying current inlined depth: %d 0x%" PRIx64 ".\n",
-// curr_frames->m_current_inlined_depth, curr_frames->m_current_inlined_pc);
+ // Don't try to merge till you've calculated all the frames in this stack.
+ if (GetAllFramesFetched() && m_prev_frames_sp) {
+ StackFrameList *prev_frames = m_prev_frames_sp.get();
+ StackFrameList *curr_frames = this;
#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\nprev_frames:\n");
- prev_frames->Dump(&s);
- s.PutCString("\ncurr_frames:\n");
- curr_frames->Dump(&s);
- s.EOL();
+ s.PutCString("\nprev_frames:\n");
+ prev_frames->Dump(&s);
+ s.PutCString("\ncurr_frames:\n");
+ curr_frames->Dump(&s);
+ s.EOL();
#endif
- size_t curr_frame_num, prev_frame_num;
+ size_t curr_frame_num, prev_frame_num;
- for (curr_frame_num = curr_frames->m_frames.size(),
- prev_frame_num = prev_frames->m_frames.size();
- curr_frame_num > 0 && prev_frame_num > 0;
- --curr_frame_num, --prev_frame_num) {
- const size_t curr_frame_idx = curr_frame_num - 1;
- const size_t prev_frame_idx = prev_frame_num - 1;
- StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
- StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
+ for (curr_frame_num = curr_frames->m_frames.size(),
+ prev_frame_num = prev_frames->m_frames.size();
+ curr_frame_num > 0 && prev_frame_num > 0;
+ --curr_frame_num, --prev_frame_num) {
+ const size_t curr_frame_idx = curr_frame_num - 1;
+ const size_t prev_frame_idx = prev_frame_num - 1;
+ StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
+ StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
- if (curr_frame_sp)
- curr_frame_sp->Dump(&s, true, false);
- else
- s.PutCString("NULL");
- s.Printf("\nPrev frame #%u ", prev_frame_idx);
- if (prev_frame_sp)
- prev_frame_sp->Dump(&s, true, false);
- else
- s.PutCString("NULL");
+ s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
+ if (curr_frame_sp)
+ curr_frame_sp->Dump(&s, true, false);
+ else
+ s.PutCString("NULL");
+ s.Printf("\nPrev frame #%u ", prev_frame_idx);
+ if (prev_frame_sp)
+ prev_frame_sp->Dump(&s, true, false);
+ else
+ s.PutCString("NULL");
#endif
- StackFrame *curr_frame = curr_frame_sp.get();
- StackFrame *prev_frame = prev_frame_sp.get();
+ StackFrame *curr_frame = curr_frame_sp.get();
+ StackFrame *prev_frame = prev_frame_sp.get();
- if (curr_frame == nullptr || prev_frame == nullptr)
- break;
+ if (curr_frame == nullptr || prev_frame == nullptr)
+ break;
- // Check the stack ID to make sure they are equal
- if (curr_frame->GetStackID() != prev_frame->GetStackID())
- break;
+ // Check the stack ID to make sure they are equal.
+ if (curr_frame->GetStackID() != prev_frame->GetStackID())
+ break;
- prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
- // Now copy the fixed up previous frame into the current frames so the
- // pointer doesn't change
- m_frames[curr_frame_idx] = prev_frame_sp;
-// curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
+ prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
+ // Now copy the fixed up previous frame into the current frames so the
+ // pointer doesn't change.
+ m_frames[curr_frame_idx] = prev_frame_sp;
#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\n Copying previous frame to current frame");
+ s.Printf("\n Copying previous frame to current frame");
#endif
- }
- // We are done with the old stack frame list, we can release it now
- m_prev_frames_sp.reset();
}
+ // We are done with the old stack frame list, we can release it now.
+ m_prev_frames_sp.reset();
+ }
#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\n\nNew frames:\n");
- Dump(&s);
- s.EOL();
+ s.PutCString("\n\nNew frames:\n");
+ Dump(&s);
+ s.EOL();
#endif
- } else {
- if (end_idx < m_concrete_frames_fetched)
- return;
-
- if (unwinder) {
- uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
- if (num_frames <= end_idx + 1) {
- // Done unwinding.
- m_concrete_frames_fetched = UINT32_MAX;
- }
- m_frames.resize(num_frames);
- }
- }
}
uint32_t StackFrameList::GetNumFrames(bool can_create) {
@@ -441,11 +612,7 @@ uint32_t StackFrameList::GetNumFrames(bool can_create) {
if (can_create)
GetFramesUpTo(UINT32_MAX);
- uint32_t inlined_depth = GetCurrentInlinedDepth();
- if (inlined_depth == UINT32_MAX)
- return m_frames.size();
- else
- return m_frames.size() - inlined_depth;
+ return GetVisibleStackFrameIndex(m_frames.size());
}
void StackFrameList::Dump(Stream *s) {
@@ -497,11 +664,9 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
addr_t pc, cfa;
if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
const bool cfa_is_valid = true;
- const bool stop_id_is_valid = false;
- const bool is_history_frame = false;
- frame_sp.reset(new StackFrame(
- m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, 0,
- stop_id_is_valid, is_history_frame, nullptr));
+ frame_sp.reset(new StackFrame(m_thread.shared_from_this(), idx, idx,
+ cfa, cfa_is_valid, pc,
+ StackFrame::Kind::Regular, nullptr));
Function *function =
frame_sp->GetSymbolContext(eSymbolContextFunction).function;
@@ -576,9 +741,6 @@ StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) {
if ((*pos)->GetStackID() == stack_id)
return *pos;
}
-
- // if (m_frames.back()->GetStackID() < stack_id)
- // frame_idx = m_frames.size();
}
do {
frame_sp = GetFrameAtIndex(frame_idx);
@@ -625,7 +787,6 @@ uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
return m_selected_frame_idx;
}
-// Mark a stack frame as the current frame using the frame index
bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
StackFrameSP frame_sp(GetFrameAtIndex(idx));
@@ -657,19 +818,6 @@ void StackFrameList::Clear() {
m_concrete_frames_fetched = 0;
}
-void StackFrameList::InvalidateFrames(uint32_t start_idx) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_show_inlined_frames) {
- Clear();
- } else {
- const size_t num_frames = m_frames.size();
- while (start_idx < num_frames) {
- m_frames[start_idx].reset();
- ++start_idx;
- }
- }
-}
-
void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_ap,
lldb::StackFrameListSP &prev_sp) {
std::unique_lock<std::recursive_mutex> current_lock, previous_lock;
diff --git a/source/Target/StackFrameRecognizer.cpp b/source/Target/StackFrameRecognizer.cpp
new file mode 100644
index 000000000000..152f4a198e20
--- /dev/null
+++ b/source/Target/StackFrameRecognizer.cpp
@@ -0,0 +1,191 @@
+//===-- StackFrameRecognizer.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+#include "lldb/Core/Module.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
+#include "lldb/Utility/RegularExpression.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#ifndef LLDB_DISABLE_PYTHON
+
+class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
+public:
+ ScriptedRecognizedStackFrame(ValueObjectListSP args) {
+ m_arguments = args;
+ }
+};
+
+ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
+ ScriptInterpreter *interpreter, const char *pclass)
+ : m_interpreter(interpreter), m_python_class(pclass) {
+ m_python_object_sp =
+ m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
+}
+
+RecognizedStackFrameSP
+ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
+ if (!m_python_object_sp || !m_interpreter)
+ return RecognizedStackFrameSP();
+
+ ValueObjectListSP args =
+ m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
+
+ return RecognizedStackFrameSP(new ScriptedRecognizedStackFrame(args));
+}
+
+#endif
+
+class StackFrameRecognizerManagerImpl {
+public:
+ void AddRecognizer(StackFrameRecognizerSP recognizer,
+ const ConstString &module, const ConstString &symbol,
+ bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(),
+ symbol, RegularExpressionSP(),
+ first_instruction_only});
+ }
+
+ void AddRecognizer(StackFrameRecognizerSP recognizer,
+ RegularExpressionSP module, RegularExpressionSP symbol,
+ bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), module,
+ ConstString(), symbol, first_instruction_only});
+ }
+
+ void ForEach(
+ std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
+ std::string symbol, bool regexp)> const &callback) {
+ for (auto entry : m_recognizers) {
+ if (entry.is_regexp) {
+ callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(),
+ entry.symbol_regexp->GetText(), true);
+ } else {
+ callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(),
+ entry.symbol.GetCString(), false);
+ }
+ }
+ }
+
+ bool RemoveRecognizerWithID(uint32_t recognizer_id) {
+ if (recognizer_id >= m_recognizers.size()) return false;
+ if (m_recognizers[recognizer_id].deleted) return false;
+ m_recognizers[recognizer_id].deleted = true;
+ return true;
+ }
+
+ void RemoveAllRecognizers() {
+ m_recognizers.clear();
+ }
+
+ StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) {
+ const SymbolContext &symctx =
+ frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction);
+ ConstString function_name = symctx.GetFunctionName();
+ ModuleSP module_sp = symctx.module_sp;
+ if (!module_sp) return StackFrameRecognizerSP();
+ ConstString module_name = module_sp->GetFileSpec().GetFilename();
+ Symbol *symbol = symctx.symbol;
+ if (!symbol) return StackFrameRecognizerSP();
+ Address start_addr = symbol->GetAddress();
+ Address current_addr = frame->GetFrameCodeAddress();
+
+ for (auto entry : m_recognizers) {
+ if (entry.deleted) continue;
+ if (entry.module)
+ if (entry.module != module_name) continue;
+
+ if (entry.module_regexp)
+ if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue;
+
+ if (entry.symbol)
+ if (entry.symbol != function_name) continue;
+
+ if (entry.symbol_regexp)
+ if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
+ continue;
+
+ if (entry.first_instruction_only)
+ if (start_addr != current_addr) continue;
+
+ return entry.recognizer;
+ }
+ return StackFrameRecognizerSP();
+ }
+
+ RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) {
+ auto recognizer = GetRecognizerForFrame(frame);
+ if (!recognizer) return RecognizedStackFrameSP();
+ return recognizer->RecognizeFrame(frame);
+ }
+
+ private:
+ struct RegisteredEntry {
+ uint32_t recognizer_id;
+ bool deleted;
+ StackFrameRecognizerSP recognizer;
+ bool is_regexp;
+ ConstString module;
+ RegularExpressionSP module_regexp;
+ ConstString symbol;
+ RegularExpressionSP symbol_regexp;
+ bool first_instruction_only;
+ };
+
+ std::deque<RegisteredEntry> m_recognizers;
+};
+
+StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() {
+ static StackFrameRecognizerManagerImpl instance =
+ StackFrameRecognizerManagerImpl();
+ return instance;
+}
+
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, const ConstString &module,
+ const ConstString &symbol, bool first_instruction_only) {
+ GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
+ first_instruction_only);
+}
+
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, RegularExpressionSP module,
+ RegularExpressionSP symbol, bool first_instruction_only) {
+ GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
+ first_instruction_only);
+}
+
+void StackFrameRecognizerManager::ForEach(
+ std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
+ std::string symbol, bool regexp)> const &callback) {
+ GetStackFrameRecognizerManagerImpl().ForEach(callback);
+}
+
+void StackFrameRecognizerManager::RemoveAllRecognizers() {
+ GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers();
+}
+
+bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) {
+ return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id);
+}
+
+RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame(
+ StackFrameSP frame) {
+ return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame);
+}
+
+StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame(
+ lldb::StackFrameSP frame) {
+ return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame);
+}
diff --git a/source/Target/StackID.cpp b/source/Target/StackID.cpp
index 341c902af995..d6640b24ad5c 100644
--- a/source/Target/StackID.cpp
+++ b/source/Target/StackID.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackID.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index f8b17dc10eca..4e13c588b484 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -333,6 +329,19 @@ protected:
// commands when we see the same breakpoint hit a second time.
m_should_stop_is_valid = true;
+
+ // It is possible that the user has a breakpoint at the same site
+ // as the completed plan had (e.g. user has a breakpoint
+ // on a module entry point, and `ThreadPlanCallFunction` ends
+ // also there). We can't find an internal breakpoint in the loop
+ // later because it was already removed on the plan completion.
+ // So check if the plan was completed, and stop if so.
+ if (thread_sp->CompletedPlanOverridesBreakpoint()) {
+ m_should_stop = true;
+ thread_sp->ResetStopInfo();
+ return;
+ }
+
if (log)
log->Printf("StopInfoBreakpoint::PerformAction - Hit a "
"breakpoint while running an expression,"
@@ -358,9 +367,8 @@ protected:
"continuing: %s.",
m_should_stop ? "true" : "false");
process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf(
- "Warning: hit breakpoint while "
- "running function, skipping commands and conditions to prevent "
- "recursion.");
+ "Warning: hit breakpoint while running function, skipping "
+ "commands and conditions to prevent recursion.\n");
return;
}
@@ -534,9 +542,9 @@ protected:
__FUNCTION__, m_value);
}
- if ((m_should_stop == false || internal_breakpoint)
- && thread_sp->CompletedPlanOverridesBreakpoint()) {
-
+ if ((!m_should_stop || internal_breakpoint) &&
+ thread_sp->CompletedPlanOverridesBreakpoint()) {
+
// Override should_stop decision when we have completed step plan
// additionally to the breakpoint
m_should_stop = true;
@@ -720,14 +728,18 @@ protected:
StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
assert(stored_stop_info_sp.get() == this);
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(
thread_sp->QueueThreadPlanForStepSingleInstruction(
- false, // step-over
- false, // abort_other_plans
- true)); // stop_other_threads
- new_plan_sp->SetIsMasterPlan(true);
- new_plan_sp->SetOkayToDiscard(false);
- new_plan_sp->SetPrivate(true);
+ false, // step-over
+ false, // abort_other_plans
+ true, // stop_other_threads
+ new_plan_status));
+ if (new_plan_sp && new_plan_status.Success()) {
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+ new_plan_sp->SetPrivate(true);
+ }
process_sp->GetThreadList().SetSelectedThreadByID(
thread_sp->GetID());
process_sp->ResumeSynchronous(nullptr);
diff --git a/source/Target/SystemRuntime.cpp b/source/Target/SystemRuntime.cpp
index 3fdf6daa6afa..574c01cb5ae1 100644
--- a/source/Target/SystemRuntime.cpp
+++ b/source/Target/SystemRuntime.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 3f70741713fb..437f92abdab3 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -7,11 +7,7 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-#include <mutex>
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Target/Target.h"
#include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
@@ -21,16 +17,17 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/SourceManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
@@ -52,14 +49,16 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SystemRuntime.h"
-#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
+#include <mutex>
using namespace lldb;
using namespace lldb_private;
@@ -195,6 +194,8 @@ void Target::DeleteCurrentProcess() {
const lldb::ProcessSP &Target::CreateProcess(ListenerSP listener_sp,
llvm::StringRef plugin_name,
const FileSpec *crash_file) {
+ if (!listener_sp)
+ listener_sp = GetDebugger().GetListener();
DeleteCurrentProcess();
m_process_sp = Process::FindPlugin(shared_from_this(), plugin_name,
listener_sp, crash_file);
@@ -322,7 +323,7 @@ BreakpointSP Target::CreateSourceRegexBreakpoint(
BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
const FileSpec &file, uint32_t line_no,
- lldb::addr_t offset,
+ uint32_t column, lldb::addr_t offset,
LazyBool check_inlines,
LazyBool skip_prologue, bool internal,
bool hardware,
@@ -366,8 +367,8 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(
- nullptr, remapped_file, line_no, offset, check_inlines, skip_prologue,
- !static_cast<bool>(move_to_nearest_code)));
+ nullptr, remapped_file, line_no, column, offset, check_inlines,
+ skip_prologue, !static_cast<bool>(move_to_nearest_code)));
return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}
@@ -412,12 +413,11 @@ Target::CreateAddressInModuleBreakpoint(lldb::addr_t file_addr, bool internal,
false);
}
-BreakpointSP
-Target::CreateBreakpoint(const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles,
- const char *func_name, uint32_t func_name_type_mask,
- LanguageType language, lldb::addr_t offset,
- LazyBool skip_prologue, bool internal, bool hardware) {
+BreakpointSP Target::CreateBreakpoint(
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles, const char *func_name,
+ FunctionNameType func_name_type_mask, LanguageType language,
+ lldb::addr_t offset, LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
if (func_name) {
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
@@ -440,9 +440,9 @@ lldb::BreakpointSP
Target::CreateBreakpoint(const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const std::vector<std::string> &func_names,
- uint32_t func_name_type_mask, LanguageType language,
- lldb::addr_t offset, LazyBool skip_prologue,
- bool internal, bool hardware) {
+ FunctionNameType func_name_type_mask,
+ LanguageType language, lldb::addr_t offset,
+ LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
size_t num_names = func_names.size();
if (num_names > 0) {
@@ -462,11 +462,13 @@ Target::CreateBreakpoint(const FileSpecList *containingModules,
return bp_sp;
}
-BreakpointSP Target::CreateBreakpoint(
- const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles, const char *func_names[],
- size_t num_names, uint32_t func_name_type_mask, LanguageType language,
- lldb::addr_t offset, LazyBool skip_prologue, bool internal, bool hardware) {
+BreakpointSP
+Target::CreateBreakpoint(const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ const char *func_names[], size_t num_names,
+ FunctionNameType func_name_type_mask,
+ LanguageType language, lldb::addr_t offset,
+ LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
if (num_names > 0) {
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
@@ -579,13 +581,56 @@ Target::CreateExceptionBreakpoint(enum lldb::LanguageType language,
return exc_bkpt_sp;
}
+lldb::BreakpointSP
+Target::CreateScriptedBreakpoint(const llvm::StringRef class_name,
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ bool internal,
+ bool request_hardware,
+ StructuredData::ObjectSP extra_args_sp,
+ Status *creation_error)
+{
+ SearchFilterSP filter_sp;
+
+ lldb::SearchDepth depth = lldb::eSearchDepthTarget;
+ bool has_files = containingSourceFiles && containingSourceFiles->GetSize() > 0;
+ bool has_modules = containingModules && containingModules->GetSize() > 0;
+
+ if (has_files && has_modules) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ containingModules, containingSourceFiles);
+ } else if (has_files) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ nullptr, containingSourceFiles);
+ } else if (has_modules) {
+ filter_sp = GetSearchFilterForModuleList(containingModules);
+ } else {
+ filter_sp.reset(new SearchFilterForUnconstrainedSearches(shared_from_this()));
+ }
+
+ StructuredDataImpl *extra_args_impl = new StructuredDataImpl();
+ if (extra_args_sp)
+ extra_args_impl->SetObjectSP(extra_args_sp);
+
+ BreakpointResolverSP resolver_sp(new
+ BreakpointResolverScripted(nullptr, class_name,
+ depth,
+ extra_args_impl,
+ *GetDebugger().GetCommandInterpreter()
+ .GetScriptInterpreter()));
+ return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true);
+
+}
+
+
BreakpointSP Target::CreateBreakpoint(SearchFilterSP &filter_sp,
BreakpointResolverSP &resolver_sp,
bool internal, bool request_hardware,
bool resolve_indirect_symbols) {
BreakpointSP bp_sp;
if (filter_sp && resolver_sp) {
- bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, request_hardware,
+ const bool hardware = request_hardware || GetRequireHardwareBreakpoints();
+ bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, hardware,
resolve_indirect_symbols));
resolver_sp->SetBreakpoint(bp_sp.get());
AddBreakpoint(bp_sp, internal);
@@ -719,17 +764,23 @@ void Target::GetBreakpointNames(std::vector<std::string> &names)
for (auto bp_name : m_breakpoint_names) {
names.push_back(bp_name.first.AsCString());
}
- std::sort(names.begin(), names.end());
+ llvm::sort(names.begin(), names.end());
}
bool Target::ProcessIsValid() {
return (m_process_sp && m_process_sp->IsAlive());
}
-static bool CheckIfWatchpointsExhausted(Target *target, Status &error) {
+static bool CheckIfWatchpointsSupported(Target *target, Status &error) {
uint32_t num_supported_hardware_watchpoints;
Status rc = target->GetProcessSP()->GetWatchpointSupportInfo(
num_supported_hardware_watchpoints);
+
+ // If unable to determine the # of watchpoints available,
+ // assume they are supported.
+ if (rc.Fail())
+ return true;
+
if (num_supported_hardware_watchpoints == 0) {
error.SetErrorStringWithFormat(
"Target supports (%u) hardware watchpoint slots.\n",
@@ -768,7 +819,7 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
error.SetErrorStringWithFormat("invalid watchpoint type: %d", kind);
}
- if (!CheckIfWatchpointsExhausted(this, error))
+ if (!CheckIfWatchpointsSupported(this, error))
return wp_sp;
// Currently we only support one watchpoint per address, with total number of
@@ -1377,7 +1428,7 @@ void Target::DidExec() {
}
void Target::SetExecutableModule(ModuleSP &executable_sp,
- bool get_dependent_files) {
+ LoadDependentFiles load_dependent_files) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
ClearModules(false);
@@ -1401,8 +1452,20 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
FileSpecList dependent_files;
ObjectFile *executable_objfile = executable_sp->GetObjectFile();
+ bool load_dependents = true;
+ switch (load_dependent_files) {
+ case eLoadDependentsDefault:
+ load_dependents = executable_sp->IsExecutable();
+ break;
+ case eLoadDependentsYes:
+ load_dependents = true;
+ break;
+ case eLoadDependentsNo:
+ load_dependents = false;
+ break;
+ }
- if (executable_objfile && get_dependent_files) {
+ if (executable_objfile && load_dependents) {
executable_objfile->GetDependentModules(dependent_files);
for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
FileSpec dependent_file_spec(
@@ -1426,13 +1489,33 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
}
}
-bool Target::SetArchitecture(const ArchSpec &arch_spec) {
+bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
bool missing_local_arch = !m_arch.GetSpec().IsValid();
bool replace_local_arch = true;
bool compatible_local_arch = false;
ArchSpec other(arch_spec);
+ // Changing the architecture might mean that the currently selected platform
+ // isn't compatible. Set the platform correctly if we are asked to do so,
+ // otherwise assume the user will set the platform manually.
+ if (set_platform) {
+ if (other.IsValid()) {
+ auto platform_sp = GetPlatform();
+ if (!platform_sp ||
+ !platform_sp->IsCompatibleArchitecture(other, false, nullptr)) {
+ ArchSpec platform_arch;
+ auto arch_platform_sp =
+ Platform::GetPlatformForArchitecture(other, &platform_arch);
+ if (arch_platform_sp) {
+ SetPlatform(arch_platform_sp);
+ if (platform_arch.IsValid())
+ other = platform_arch;
+ }
+ }
+ }
+ }
+
if (!missing_local_arch) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
other.MergeFrom(m_arch.GetSpec());
@@ -1487,7 +1570,7 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
nullptr, nullptr);
if (!error.Fail() && executable_sp) {
- SetExecutableModule(executable_sp, true);
+ SetExecutableModule(executable_sp, eLoadDependentsYes);
return true;
}
}
@@ -1495,11 +1578,18 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
}
bool Target::MergeArchitecture(const ArchSpec &arch_spec) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
if (arch_spec.IsValid()) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
// The current target arch is compatible with "arch_spec", see if we can
// improve our current architecture using bits from "arch_spec"
+ if (log)
+ log->Printf("Target::MergeArchitecture target has arch %s, merging with "
+ "arch %s",
+ m_arch.GetSpec().GetTriple().getTriple().c_str(),
+ arch_spec.GetTriple().getTriple().c_str());
+
// Merge bits from arch_spec into "merged_arch" and set our architecture
ArchSpec merged_arch(m_arch.GetSpec());
merged_arch.MergeFrom(arch_spec);
@@ -2057,7 +2147,7 @@ void Target::ImageSearchPathsChanged(const PathMappingList &path_list,
Target *target = (Target *)baton;
ModuleSP exe_module_sp(target->GetExecutableModule());
if (exe_module_sp)
- target->SetExecutableModule(exe_module_sp, true);
+ target->SetExecutableModule(exe_module_sp, eLoadDependentsYes);
}
TypeSystem *Target::GetScratchTypeSystemForLanguage(Status *error,
@@ -2351,249 +2441,22 @@ lldb::addr_t Target::GetPersistentSymbol(const ConstString &name) {
lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
AddressClass addr_class) const {
- addr_t code_addr = load_addr;
- switch (m_arch.GetSpec().GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eUnknown:
- case AddressClass::eInvalid:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- if ((code_addr & 2ull) || (addr_class == AddressClass::eCodeAlternateISA))
- code_addr |= 1ull;
- break;
- }
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eUnknown:
- case AddressClass::eInvalid:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- // Check if bit zero it no set?
- if ((code_addr & 1ull) == 0) {
- // Bit zero isn't set, check if the address is a multiple of 2?
- if (code_addr & 2ull) {
- // The address is a multiple of 2 so it must be thumb, set bit zero
- code_addr |= 1ull;
- } else if (addr_class == AddressClass::eCodeAlternateISA) {
- // We checked the address and the address claims to be the alternate
- // ISA which means thumb, so set bit zero.
- code_addr |= 1ull;
- }
- }
- break;
- }
- break;
-
- default:
- break;
- }
- return code_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetCallableLoadAddress(load_addr, addr_class) : load_addr;
}
lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr,
AddressClass addr_class) const {
- addr_t opcode_addr = load_addr;
- switch (m_arch.GetSpec().GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eInvalid:
- case AddressClass::eUnknown:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- opcode_addr &= ~(1ull);
- break;
- }
- break;
-
- default:
- break;
- }
- return opcode_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class) : load_addr;
}
lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
- addr_t breakable_addr = addr;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- switch (m_arch.GetSpec().GetMachine()) {
- default:
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el: {
- addr_t function_start = 0;
- addr_t current_offset = 0;
- uint32_t loop_count = 0;
- Address resolved_addr;
- uint32_t arch_flags = m_arch.GetSpec().GetFlags();
- bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
- bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
- SectionLoadList &section_load_list = GetSectionLoadList();
-
- if (section_load_list.IsEmpty())
- // No sections are loaded, so we must assume we are not running yet and
- // need to operate only on file address.
- m_images.ResolveFileAddress(addr, resolved_addr);
- else
- section_load_list.ResolveLoadAddress(addr, resolved_addr);
-
- // Get the function boundaries to make sure we don't scan back before the
- // beginning of the current function.
- ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
- if (temp_addr_module_sp) {
- SymbolContext sc;
- uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
- temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
- resolve_scope, sc);
- Address sym_addr;
- if (sc.function)
- sym_addr = sc.function->GetAddressRange().GetBaseAddress();
- else if (sc.symbol)
- sym_addr = sc.symbol->GetAddress();
-
- function_start = sym_addr.GetLoadAddress(this);
- if (function_start == LLDB_INVALID_ADDRESS)
- function_start = sym_addr.GetFileAddress();
-
- if (function_start)
- current_offset = addr - function_start;
- }
-
- // If breakpoint address is start of function then we dont have to do
- // anything.
- if (current_offset == 0)
- return breakable_addr;
- else
- loop_count = current_offset / 2;
-
- if (loop_count > 3) {
- // Scan previous 6 bytes
- if (IsMips16 | IsMicromips)
- loop_count = 3;
- // For mips-only, instructions are always 4 bytes, so scan previous 4
- // bytes only.
- else
- loop_count = 2;
- }
-
- // Create Disassembler Instance
- lldb::DisassemblerSP disasm_sp(
- Disassembler::FindPlugin(m_arch.GetSpec(), nullptr, nullptr));
-
- ExecutionContext exe_ctx;
- CalculateExecutionContext(exe_ctx);
- InstructionList instruction_list;
- InstructionSP prev_insn;
- bool prefer_file_cache = true; // Read from file
- uint32_t inst_to_choose = 0;
-
- for (uint32_t i = 1; i <= loop_count; i++) {
- // Adjust the address to read from.
- resolved_addr.Slide(-2);
- AddressRange range(resolved_addr, i * 2);
- uint32_t insn_size = 0;
-
- disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
-
- uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
- if (num_insns) {
- prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
- insn_size = prev_insn->GetOpcode().GetByteSize();
- if (i == 1 && insn_size == 2) {
- // This looks like a valid 2-byte instruction (but it could be a part
- // of upper 4 byte instruction).
- instruction_list.Append(prev_insn);
- inst_to_choose = 1;
- } else if (i == 2) {
- // Here we may get one 4-byte instruction or two 2-byte instructions.
- if (num_insns == 2) {
- // Looks like there are two 2-byte instructions above our
- // breakpoint target address. Now the upper 2-byte instruction is
- // either a valid 2-byte instruction or could be a part of it's
- // upper 4-byte instruction. In both cases we don't care because in
- // this case lower 2-byte instruction is definitely a valid
- // instruction and whatever i=1 iteration has found out is true.
- inst_to_choose = 1;
- break;
- } else if (insn_size == 4) {
- // This instruction claims its a valid 4-byte instruction. But it
- // could be a part of it's upper 4-byte instruction. Lets try
- // scanning upper 2 bytes to verify this.
- instruction_list.Append(prev_insn);
- inst_to_choose = 2;
- }
- } else if (i == 3) {
- if (insn_size == 4)
- // FIXME: We reached here that means instruction at [target - 4] has
- // already claimed to be a 4-byte instruction, and now instruction
- // at [target - 6] is also claiming that it's a 4-byte instruction.
- // This can not be true. In this case we can not decide the valid
- // previous instruction so we let lldb set the breakpoint at the
- // address given by user.
- inst_to_choose = 0;
- else
- // This is straight-forward
- inst_to_choose = 2;
- break;
- }
- } else {
- // Decode failed, bytes do not form a valid instruction. So whatever
- // previous iteration has found out is true.
- if (i > 1) {
- inst_to_choose = i - 1;
- break;
- }
- }
- }
-
- // Check if we are able to find any valid instruction.
- if (inst_to_choose) {
- if (inst_to_choose > instruction_list.GetSize())
- inst_to_choose--;
- prev_insn = instruction_list.GetInstructionAtIndex(inst_to_choose - 1);
-
- if (prev_insn->HasDelaySlot()) {
- uint32_t shift_size = prev_insn->GetOpcode().GetByteSize();
- // Adjust the breakable address
- breakable_addr = addr - shift_size;
- if (log)
- log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
- " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
- __FUNCTION__, addr, breakable_addr);
- }
- }
- break;
- }
- }
- return breakable_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetBreakableLoadAddress(addr, *this) : addr;
}
SourceManager &Target::GetSourceManager() {
@@ -2971,18 +2834,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
PlatformSP platform_sp(GetPlatform());
- // Finalize the file actions, and if none were given, default to opening up a
- // pseudo terminal
- const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
- if (log)
- log->Printf("Target::%s have platform=%s, platform_sp->IsHost()=%s, "
- "default_to_use_pty=%s",
- __FUNCTION__, platform_sp ? "true" : "false",
- platform_sp ? (platform_sp->IsHost() ? "true" : "false")
- : "n/a",
- default_to_use_pty ? "true" : "false");
-
- launch_info.FinalizeFileActions(this, default_to_use_pty);
+ FinalizeFileActions(launch_info);
if (state == eStateConnected) {
if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
@@ -3003,22 +2855,15 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
log->Printf("Target::%s asking the platform to debug the process",
__FUNCTION__);
- // Get a weak pointer to the previous process if we have one
- ProcessWP process_wp;
- if (m_process_sp)
- process_wp = m_process_sp;
+ // If there was a previous process, delete it before we make the new one.
+ // One subtle point, we delete the process before we release the reference
+ // to m_process_sp. That way even if we are the last owner, the process
+ // will get Finalized before it gets destroyed.
+ DeleteCurrentProcess();
+
m_process_sp =
GetPlatform()->DebugProcess(launch_info, debugger, this, error);
- // Cleanup the old process since someone might still have a strong
- // reference to this process and we would like to allow it to cleanup as
- // much as it can without the object being destroyed. We try to lock the
- // shared pointer and if that works, then someone else still has a strong
- // reference to the process.
-
- ProcessSP old_process_sp(process_wp.lock());
- if (old_process_sp)
- old_process_sp->Finalize();
} else {
if (log)
log->Printf("Target::%s the platform doesn't know how to debug a "
@@ -3030,8 +2875,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
} else {
// Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess(launch_info.GetListenerForProcess(debugger), plugin_name,
- nullptr);
+ CreateProcess(launch_info.GetListener(), plugin_name, nullptr);
}
// Since we didn't have a platform launch the process, launch it here.
@@ -3206,6 +3050,86 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
return error;
}
+void Target::FinalizeFileActions(ProcessLaunchInfo &info) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Finalize the file actions, and if none were given, default to opening up a
+ // pseudo terminal
+ PlatformSP platform_sp = GetPlatform();
+ const bool default_to_use_pty =
+ m_platform_sp ? m_platform_sp->IsHost() : false;
+ LLDB_LOG(
+ log,
+ "have platform={0}, platform_sp->IsHost()={1}, default_to_use_pty={2}",
+ bool(platform_sp),
+ platform_sp ? (platform_sp->IsHost() ? "true" : "false") : "n/a",
+ default_to_use_pty);
+
+ // If nothing for stdin or stdout or stderr was specified, then check the
+ // process for any default settings that were set with "settings set"
+ if (info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
+ info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
+ info.GetFileActionForFD(STDERR_FILENO) == nullptr) {
+ LLDB_LOG(log, "at least one of stdin/stdout/stderr was not set, evaluating "
+ "default handling");
+
+ if (info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
+ // Do nothing, if we are launching in a remote terminal no file actions
+ // should be done at all.
+ return;
+ }
+
+ if (info.GetFlags().Test(eLaunchFlagDisableSTDIO)) {
+ LLDB_LOG(log, "eLaunchFlagDisableSTDIO set, adding suppression action "
+ "for stdin, stdout and stderr");
+ info.AppendSuppressFileAction(STDIN_FILENO, true, false);
+ info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
+ info.AppendSuppressFileAction(STDERR_FILENO, false, true);
+ } else {
+ // Check for any values that might have gotten set with any of: (lldb)
+ // settings set target.input-path (lldb) settings set target.output-path
+ // (lldb) settings set target.error-path
+ FileSpec in_file_spec;
+ FileSpec out_file_spec;
+ FileSpec err_file_spec;
+ // Only override with the target settings if we don't already have an
+ // action for in, out or error
+ if (info.GetFileActionForFD(STDIN_FILENO) == nullptr)
+ in_file_spec = GetStandardInputPath();
+ if (info.GetFileActionForFD(STDOUT_FILENO) == nullptr)
+ out_file_spec = GetStandardOutputPath();
+ if (info.GetFileActionForFD(STDERR_FILENO) == nullptr)
+ err_file_spec = GetStandardErrorPath();
+
+ LLDB_LOG(log, "target stdin='{0}', target stdout='{1}', stderr='{1}'",
+ in_file_spec, out_file_spec, err_file_spec);
+
+ if (in_file_spec) {
+ info.AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
+ LLDB_LOG(log, "appended stdin open file action for {0}", in_file_spec);
+ }
+
+ if (out_file_spec) {
+ info.AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
+ LLDB_LOG(log, "appended stdout open file action for {0}",
+ out_file_spec);
+ }
+
+ if (err_file_spec) {
+ info.AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
+ LLDB_LOG(log, "appended stderr open file action for {0}",
+ err_file_spec);
+ }
+
+ if (default_to_use_pty &&
+ (!in_file_spec || !out_file_spec || !err_file_spec)) {
+ llvm::Error Err = info.SetUpPtyRedirection();
+ LLDB_LOG_ERROR(log, std::move(Err), "SetUpPtyRedirection failed: {0}");
+ }
+ }
+ }
+}
+
//--------------------------------------------------------------
// Target::StopHook
//--------------------------------------------------------------
@@ -3275,16 +3199,20 @@ void Target::StopHook::GetDescription(Stream *s,
// class TargetProperties
//--------------------------------------------------------------
-OptionEnumValueElement lldb_private::g_dynamic_value_types[] = {
+// clang-format off
+static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
{eNoDynamicValues, "no-dynamic-values",
"Don't calculate the dynamic type of values"},
{eDynamicCanRunTarget, "run-target", "Calculate the dynamic type of values "
"even if you have to run the target."},
{eDynamicDontRunTarget, "no-run-target",
- "Calculate the dynamic type of values, but don't run the target."},
- {0, nullptr, nullptr}};
+ "Calculate the dynamic type of values, but don't run the target."} };
+
+OptionEnumValues lldb_private::GetDynamicValueTypes() {
+ return OptionEnumValues(g_dynamic_value_types);
+}
-static OptionEnumValueElement g_inline_breakpoint_enums[] = {
+static constexpr OptionEnumValueElement g_inline_breakpoint_enums[] = {
{eInlineBreakpointsNever, "never", "Never look for inline breakpoint "
"locations (fastest). This setting "
"should only be used if you know that "
@@ -3295,8 +3223,7 @@ static OptionEnumValueElement g_inline_breakpoint_enums[] = {
"files (default)."},
{eInlineBreakpointsAlways, "always",
"Always look for inline breakpoint locations when setting file and line "
- "breakpoints (slower but most accurate)."},
- {0, nullptr, nullptr}};
+ "breakpoints (slower but most accurate)."} };
typedef enum x86DisassemblyFlavor {
eX86DisFlavorDefault,
@@ -3304,36 +3231,33 @@ typedef enum x86DisassemblyFlavor {
eX86DisFlavorATT
} x86DisassemblyFlavor;
-static OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
+static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
{eX86DisFlavorDefault, "default", "Disassembler default (currently att)."},
{eX86DisFlavorIntel, "intel", "Intel disassembler flavor."},
- {eX86DisFlavorATT, "att", "AT&T disassembler flavor."},
- {0, nullptr, nullptr}};
+ {eX86DisFlavorATT, "att", "AT&T disassembler flavor."} };
-static OptionEnumValueElement g_hex_immediate_style_values[] = {
+static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = {
{Disassembler::eHexStyleC, "c", "C-style (0xffff)."},
- {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."},
- {0, nullptr, nullptr}};
+ {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."} };
-static OptionEnumValueElement g_load_script_from_sym_file_values[] = {
+static constexpr OptionEnumValueElement g_load_script_from_sym_file_values[] = {
{eLoadScriptFromSymFileTrue, "true",
"Load debug scripts inside symbol files"},
{eLoadScriptFromSymFileFalse, "false",
"Do not load debug scripts inside symbol files."},
{eLoadScriptFromSymFileWarn, "warn",
- "Warn about debug scripts inside symbol files but do not load them."},
- {0, nullptr, nullptr}};
+ "Warn about debug scripts inside symbol files but do not load them."} };
-static OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = {
+static constexpr
+OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = {
{eLoadCWDlldbinitTrue, "true",
"Load .lldbinit files from current directory"},
{eLoadCWDlldbinitFalse, "false",
"Do not load .lldbinit files from current directory"},
{eLoadCWDlldbinitWarn, "warn",
- "Warn about loading .lldbinit files from current directory"},
- {0, nullptr, nullptr}};
+ "Warn about loading .lldbinit files from current directory"} };
-static OptionEnumValueElement g_memory_module_load_level_values[] = {
+static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = {
{eMemoryModuleLoadLevelMinimal, "minimal",
"Load minimal information when loading modules from memory. Currently "
"this setting loads sections only."},
@@ -3342,28 +3266,27 @@ static OptionEnumValueElement g_memory_module_load_level_values[] = {
"this setting loads sections and function bounds."},
{eMemoryModuleLoadLevelComplete, "complete",
"Load complete information when loading modules from memory. Currently "
- "this setting loads sections and all symbols."},
- {0, nullptr, nullptr}};
+ "this setting loads sections and all symbols."} };
-static PropertyDefinition g_properties[] = {
- {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, nullptr,
+static constexpr PropertyDefinition g_properties[] = {
+ {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, {},
"Default architecture to choose, when there's a choice."},
{"move-to-nearest-code", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Move breakpoints to nearest code."},
+ {}, "Move breakpoints to nearest code."},
{"language", OptionValue::eTypeLanguage, false, eLanguageTypeUnknown,
- nullptr, nullptr,
+ nullptr, {},
"The language to use when interpreting expressions entered in commands."},
- {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"Path to a file containing expressions to be prepended to all "
"expressions."},
{"prefer-dynamic-value", OptionValue::eTypeEnum, false,
- eDynamicDontRunTarget, nullptr, g_dynamic_value_types,
+ eDynamicDontRunTarget, nullptr, OptionEnumValues(g_dynamic_value_types),
"Should printed values be shown as their dynamic value."},
{"enable-synthetic-value", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Should synthetic values be used by default whenever available."},
- {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {}, "Should synthetic values be used by default whenever available."},
+ {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Skip function prologues when setting breakpoints by name."},
- {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, nullptr,
+ {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, {},
"Source path remappings are used to track the change of location between "
"a source file when built, and "
"where it exists on the current system. It consists of an array of "
@@ -3375,66 +3298,68 @@ static PropertyDefinition g_properties[] = {
"Each element of the array is checked in order and the first one that "
"results in a match wins."},
{"exec-search-paths", OptionValue::eTypeFileSpecList, false, 0, nullptr,
- nullptr, "Executable search paths to use when locating executable files "
- "whose paths don't match the local file system."},
+ {}, "Executable search paths to use when locating executable files "
+ "whose paths don't match the local file system."},
{"debug-file-search-paths", OptionValue::eTypeFileSpecList, false, 0,
- nullptr, nullptr,
- "List of directories to be searched when locating debug symbol files."},
+ nullptr, {},
+ "List of directories to be searched when locating debug symbol files. "
+ "See also symbols.enable-external-lookup."},
{"clang-module-search-paths", OptionValue::eTypeFileSpecList, false, 0,
- nullptr, nullptr,
+ nullptr, {},
"List of directories to be searched when locating modules for Clang."},
{"auto-import-clang-modules", OptionValue::eTypeBoolean, false, true,
- nullptr, nullptr,
+ nullptr, {},
"Automatically load Clang modules referred to by the program."},
{"auto-apply-fixits", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Automatically apply fix-it hints to expressions."},
+ {}, "Automatically apply fix-it hints to expressions."},
{"notify-about-fixits", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Print the fixed expression text."},
+ {}, "Print the fixed expression text."},
{"save-jit-objects", OptionValue::eTypeBoolean, false, false, nullptr,
- nullptr, "Save intermediate object files generated by the LLVM JIT"},
+ {}, "Save intermediate object files generated by the LLVM JIT"},
{"max-children-count", OptionValue::eTypeSInt64, false, 256, nullptr,
- nullptr, "Maximum number of children to expand in any level of depth."},
+ {}, "Maximum number of children to expand in any level of depth."},
{"max-string-summary-length", OptionValue::eTypeSInt64, false, 1024,
- nullptr, nullptr,
+ nullptr, {},
"Maximum number of characters to show when using %s in summary strings."},
{"max-memory-read-size", OptionValue::eTypeSInt64, false, 1024, nullptr,
- nullptr, "Maximum number of bytes that 'memory read' will fetch before "
- "--force must be specified."},
+ {}, "Maximum number of bytes that 'memory read' will fetch before "
+ "--force must be specified."},
{"breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean, false,
- true, nullptr, nullptr, "Consult the platform module avoid list when "
- "setting non-module specific breakpoints."},
- {"arg0", OptionValue::eTypeString, false, 0, nullptr, nullptr,
+ true, nullptr, {}, "Consult the platform module avoid list when "
+ "setting non-module specific breakpoints."},
+ {"arg0", OptionValue::eTypeString, false, 0, nullptr, {},
"The first argument passed to the program in the argument array which can "
"be different from the executable itself."},
- {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, nullptr,
+ {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, {},
"A list containing all the arguments to be passed to the executable when "
"it is run. Note that this does NOT include the argv[0] which is in "
"target.arg0."},
{"env-vars", OptionValue::eTypeDictionary, false, OptionValue::eTypeString,
- nullptr, nullptr, "A list of all the environment variables to be passed "
- "to the executable's environment, and their values."},
- {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ nullptr, {}, "A list of all the environment variables to be passed "
+ "to the executable's environment, and their values."},
+ {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Inherit the environment from the process that is running LLDB."},
- {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for reading its "
"standard input."},
- {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for writing its "
"standard output."},
- {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for writing its "
"standard error."},
{"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "debugserver will detach (rather than killing) a process if it "
+ {}, "debugserver will detach (rather than killing) a process if it "
"loses connection with lldb."},
- {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Enable loading of symbol tables before they are needed."},
- {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Disable Address Space Layout Randomization (ASLR)"},
- {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
+ {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, {},
"Disable stdin/stdout for process (e.g. for a GUI application)"},
{"inline-breakpoint-strategy", OptionValue::eTypeEnum, false,
- eInlineBreakpointsAlways, nullptr, g_inline_breakpoint_enums,
+ eInlineBreakpointsAlways, nullptr,
+ OptionEnumValues(g_inline_breakpoint_enums),
"The strategy to use when settings breakpoints by file and line. "
"Breakpoint locations can end up being inlined by the compiler, so that a "
"compile unit 'a.c' might contain an inlined function from another source "
@@ -3454,25 +3379,29 @@ static PropertyDefinition g_properties[] = {
// FIXME: This is the wrong way to do per-architecture settings, but we
// don't have a general per architecture settings system in place yet.
{"x86-disassembly-flavor", OptionValue::eTypeEnum, false,
- eX86DisFlavorDefault, nullptr, g_x86_dis_flavor_value_types,
+ eX86DisFlavorDefault, nullptr,
+ OptionEnumValues(g_x86_dis_flavor_value_types),
"The default disassembly flavor to use for x86 or x86-64 targets."},
{"use-hex-immediates", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Show immediates in disassembly as hexadecimal."},
+ {}, "Show immediates in disassembly as hexadecimal."},
{"hex-immediate-style", OptionValue::eTypeEnum, false,
- Disassembler::eHexStyleC, nullptr, g_hex_immediate_style_values,
+ Disassembler::eHexStyleC, nullptr,
+ OptionEnumValues(g_hex_immediate_style_values),
"Which style to use for printing hexadecimal disassembly values."},
{"use-fast-stepping", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Use a fast stepping algorithm based on running from branch to "
- "branch rather than instruction single-stepping."},
+ {}, "Use a fast stepping algorithm based on running from branch to "
+ "branch rather than instruction single-stepping."},
{"load-script-from-symbol-file", OptionValue::eTypeEnum, false,
- eLoadScriptFromSymFileWarn, nullptr, g_load_script_from_sym_file_values,
+ eLoadScriptFromSymFileWarn, nullptr,
+ OptionEnumValues(g_load_script_from_sym_file_values),
"Allow LLDB to load scripting resources embedded in symbol files when "
"available."},
{"load-cwd-lldbinit", OptionValue::eTypeEnum, false, eLoadCWDlldbinitWarn,
- nullptr, g_load_current_working_dir_lldbinit_values,
+ nullptr, OptionEnumValues(g_load_current_working_dir_lldbinit_values),
"Allow LLDB to .lldbinit files from the current directory automatically."},
{"memory-module-load-level", OptionValue::eTypeEnum, false,
- eMemoryModuleLoadLevelComplete, nullptr, g_memory_module_load_level_values,
+ eMemoryModuleLoadLevelComplete, nullptr,
+ OptionEnumValues(g_memory_module_load_level_values),
"Loading modules from memory can be slow as reading the symbol tables and "
"other data can take a long time depending on your connection to the "
"debug target. "
@@ -3488,20 +3417,23 @@ static PropertyDefinition g_properties[] = {
"symbols, but should rarely be used as stack frames in these memory "
"regions will be inaccurate and not provide any context (fastest). "},
{"display-expression-in-crashlogs", OptionValue::eTypeBoolean, false, false,
- nullptr, nullptr, "Expressions that crash will show up in crash logs if "
- "the host system supports executable specific crash log "
- "strings and this setting is set to true."},
+ nullptr, {}, "Expressions that crash will show up in crash logs if "
+ "the host system supports executable specific crash log "
+ "strings and this setting is set to true."},
{"trap-handler-names", OptionValue::eTypeArray, true,
- OptionValue::eTypeString, nullptr, nullptr,
+ OptionValue::eTypeString, nullptr, {},
"A list of trap handler function names, e.g. a common Unix user process "
"one is _sigtramp."},
{"display-runtime-support-values", OptionValue::eTypeBoolean, false, false,
- nullptr, nullptr, "If true, LLDB will show variables that are meant to "
- "support the operation of a language's runtime "
- "support."},
- {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, nullptr,
+ nullptr, {}, "If true, LLDB will show variables that are meant to "
+ "support the operation of a language's runtime support."},
+ {"display-recognized-arguments", OptionValue::eTypeBoolean, false, false,
+ nullptr, {}, "Show recognized arguments in variable listings by default."},
+ {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, {},
"Disable lock-step debugging, instead control threads independently."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {"require-hardware-breakpoint", OptionValue::eTypeBoolean, false, 0,
+ nullptr, {}, "Require all breakpoints to be hardware breakpoints."}};
+// clang-format on
enum {
ePropertyDefaultArch,
@@ -3545,8 +3477,10 @@ enum {
ePropertyDisplayExpressionsInCrashlogs,
ePropertyTrapHandlerNames,
ePropertyDisplayRuntimeSupportValues,
+ ePropertyDisplayRecognizedArguments,
ePropertyNonStopModeEnabled,
- ePropertyExperimental
+ ePropertyRequireHardwareBreakpoints,
+ ePropertyExperimental,
};
class TargetOptionValueProperties : public OptionValueProperties {
@@ -3623,16 +3557,15 @@ protected:
//----------------------------------------------------------------------
// TargetProperties
//----------------------------------------------------------------------
-static PropertyDefinition g_experimental_properties[]{
+static constexpr PropertyDefinition g_experimental_properties[]{
{"inject-local-vars", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, inject local variables explicitly into the expression text. "
"This will fix symbol resolution when there are name collisions between "
"ivars and local variables. "
"But it can make expressions run much more slowly."},
{"use-modern-type-lookup", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, use Clang's modern type lookup infrastructure."},
- {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
+ {}, "If true, use Clang's modern type lookup infrastructure."}};
enum { ePropertyInjectLocalVars = 0, ePropertyUseModernTypeLookup };
@@ -4104,6 +4037,16 @@ void TargetProperties::SetDisplayRuntimeSupportValues(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
+bool TargetProperties::GetDisplayRecognizedArguments() const {
+ const uint32_t idx = ePropertyDisplayRecognizedArguments;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
+}
+
+void TargetProperties::SetDisplayRecognizedArguments(bool b) {
+ const uint32_t idx = ePropertyDisplayRecognizedArguments;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
bool TargetProperties::GetNonStopModeEnabled() const {
const uint32_t idx = ePropertyNonStopModeEnabled;
return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
@@ -4145,6 +4088,17 @@ void TargetProperties::SetProcessLaunchInfo(
SetDisableSTDIO(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableSTDIO));
}
+bool TargetProperties::GetRequireHardwareBreakpoints() const {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
void TargetProperties::Arg0ValueChangedCallback(void *target_property_ptr,
OptionValue *) {
TargetProperties *this_ =
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index b9c852b414e2..5b262509cae7 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "lldb/Target/TargetList.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -22,10 +18,12 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "lldb/Utility/Timer.h"
-// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
@@ -58,27 +56,27 @@ TargetList::~TargetList() {
Status TargetList::CreateTarget(Debugger &debugger,
llvm::StringRef user_exe_path,
llvm::StringRef triple_str,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
TargetSP &target_sp) {
return CreateTargetInternal(debugger, user_exe_path, triple_str,
- get_dependent_files, platform_options, target_sp,
+ load_dependent_files, platform_options, target_sp,
false);
}
Status TargetList::CreateTarget(Debugger &debugger,
llvm::StringRef user_exe_path,
const ArchSpec &specified_arch,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
PlatformSP &platform_sp, TargetSP &target_sp) {
return CreateTargetInternal(debugger, user_exe_path, specified_arch,
- get_dependent_files, platform_sp, target_sp,
+ load_dependent_files, platform_sp, target_sp,
false);
}
Status TargetList::CreateTargetInternal(
Debugger &debugger, llvm::StringRef user_exe_path,
- llvm::StringRef triple_str, bool get_dependent_files,
+ llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options, TargetSP &target_sp,
bool is_dummy_target) {
Status error;
@@ -120,8 +118,8 @@ Status TargetList::CreateTargetInternal(
if (!user_exe_path.empty()) {
ModuleSpecList module_specs;
ModuleSpec module_spec;
- module_spec.GetFileSpec().SetFile(user_exe_path, true,
- FileSpec::Style::native);
+ module_spec.GetFileSpec().SetFile(user_exe_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
// Resolve the executable in case we are given a path to a application
// bundle like a .app bundle on MacOSX
@@ -236,7 +234,7 @@ Status TargetList::CreateTargetInternal(
// All platforms for all modules in the executable match, so we can
// select this platform
platform_sp = platforms.front();
- } else if (more_than_one_platforms == false) {
+ } else if (!more_than_one_platforms) {
// No platforms claim to support this file
error.SetErrorString("No matching platforms found for this file, "
"specify one with the --platform option");
@@ -292,7 +290,7 @@ Status TargetList::CreateTargetInternal(
platform_arch = arch;
error = TargetList::CreateTargetInternal(
- debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
+ debugger, user_exe_path, platform_arch, load_dependent_files, platform_sp,
target_sp, is_dummy_target);
return error;
}
@@ -315,14 +313,14 @@ Status TargetList::CreateDummyTarget(Debugger &debugger,
lldb::TargetSP &target_sp) {
PlatformSP host_platform_sp(Platform::GetHostPlatform());
return CreateTargetInternal(
- debugger, (const char *)nullptr, specified_arch_name, false,
+ debugger, (const char *)nullptr, specified_arch_name, eLoadDependentsNo,
(const OptionGroupPlatform *)nullptr, target_sp, true);
}
Status TargetList::CreateTargetInternal(Debugger &debugger,
llvm::StringRef user_exe_path,
const ArchSpec &specified_arch,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
lldb::PlatformSP &platform_sp,
lldb::TargetSP &target_sp,
bool is_dummy_target) {
@@ -346,8 +344,8 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
if (!arch.IsValid())
arch = specified_arch;
- FileSpec file(user_exe_path, false);
- if (!file.Exists() && user_exe_path.startswith("~")) {
+ FileSpec file(user_exe_path);
+ if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) {
// we want to expand the tilde but we don't want to resolve any symbolic
// links so we can't use the FileSpec constructor's resolve flag
llvm::SmallString<64> unglobbed_path;
@@ -355,24 +353,24 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
if (unglobbed_path.empty())
- file = FileSpec(user_exe_path, false);
+ file = FileSpec(user_exe_path);
else
- file = FileSpec(unglobbed_path.c_str(), false);
+ file = FileSpec(unglobbed_path.c_str());
}
bool user_exe_path_is_bundle = false;
char resolved_bundle_exe_path[PATH_MAX];
resolved_bundle_exe_path[0] = '\0';
if (file) {
- if (llvm::sys::fs::is_directory(file.GetPath()))
+ if (FileSystem::Instance().IsDirectory(file))
user_exe_path_is_bundle = true;
if (file.IsRelative() && !user_exe_path.empty()) {
llvm::SmallString<64> cwd;
if (! llvm::sys::fs::current_path(cwd)) {
- FileSpec cwd_file(cwd.c_str(), false);
+ FileSpec cwd_file(cwd.c_str());
cwd_file.AppendPathComponent(file);
- if (cwd_file.Exists())
+ if (FileSystem::Instance().Exists(cwd_file))
file = cwd_file;
}
}
@@ -401,7 +399,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
return error;
}
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
- target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
+ target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
if (user_exe_path_is_bundle)
exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
sizeof(resolved_bundle_exe_path));
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 5ac1de7ae01b..569d7a0a0f9e 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h"
@@ -18,7 +14,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
@@ -28,8 +23,10 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
@@ -49,6 +46,7 @@
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"
@@ -64,30 +62,31 @@ const ThreadPropertiesSP &Thread::GetGlobalProperties() {
return *g_settings_sp_ptr;
}
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, step-in will not stop in functions with no debug information."},
{"step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, when step-in/step-out/step-over leave the current "
- "frame, they will continue to step out till they come to a "
- "function with "
- "debug information. Passing a frame argument to step-out will "
- "override this option."},
- {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", nullptr,
+ {}, "If true, when step-in/step-out/step-over leave the current frame, "
+ "they will continue to step out till they come to a function with "
+ "debug information. Passing a frame argument to step-out will "
+ "override this option."},
+ {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", {},
"A regular expression defining functions step-in won't stop in."},
{"step-avoid-libraries", OptionValue::eTypeFileSpecList, true, 0, nullptr,
- nullptr, "A list of libraries that source stepping won't stop in."},
- {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
+ {}, "A list of libraries that source stepping won't stop in."},
+ {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, {},
"If true, this thread will single-step and log execution."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {"max-backtrace-depth", OptionValue::eTypeUInt64, false, 300000, nullptr,
+ {}, "Maximum number of frames to backtrace."}};
enum {
ePropertyStepInAvoidsNoDebug,
ePropertyStepOutAvoidsNoDebug,
ePropertyStepAvoidRegex,
ePropertyStepAvoidLibraries,
- ePropertyEnableThreadTrace
+ ePropertyEnableThreadTrace,
+ ePropertyMaxBacktraceDepth
};
class ThreadOptionValueProperties : public OptionValueProperties {
@@ -165,6 +164,12 @@ bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
nullptr, idx, g_properties[idx].default_uint_value != 0);
}
+uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
+ const uint32_t idx = ePropertyMaxBacktraceDepth;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------
@@ -259,6 +264,7 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id)
static_cast<void *>(this), GetID());
CheckInWithManager();
+
QueueFundamentalPlan(true);
}
@@ -392,13 +398,14 @@ lldb::StopInfoSP Thread::GetStopInfo() {
m_stop_info_sp ->IsValid() &&
m_stop_info_stop_id == stop_id;
bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
+ bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
bool plan_overrides_trace =
have_valid_stop_info && have_valid_completed_plan
&& (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
- if (have_valid_stop_info && !plan_overrides_trace) {
+ if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
return m_stop_info_sp;
- } else if (have_valid_completed_plan) {
+ } else if (completed_plan_sp) {
return StopInfo::CreateStopReasonWithPlan(
completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
} else {
@@ -1031,9 +1038,11 @@ void Thread::PushPlan(ThreadPlanSP &thread_plan_sp) {
if (thread_plan_sp) {
// If the thread plan doesn't already have a tracer, give it its parent's
// tracer:
- if (!thread_plan_sp->GetThreadPlanTracer())
+ if (!thread_plan_sp->GetThreadPlanTracer()) {
+ assert(!m_plan_stack.empty());
thread_plan_sp->SetThreadPlanTracer(
m_plan_stack.back()->GetThreadPlanTracer());
+ }
m_plan_stack.push_back(thread_plan_sp);
thread_plan_sp->DidPush();
@@ -1170,12 +1179,34 @@ ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) {
return nullptr;
}
-void Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
- bool abort_other_plans) {
+Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
+ bool abort_other_plans) {
+ Status status;
+ StreamString s;
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
if (abort_other_plans)
DiscardThreadPlans(true);
PushPlan(thread_plan_sp);
+
+ // This seems a little funny, but I don't want to have to split up the
+ // constructor and the DidPush in the scripted plan, that seems annoying.
+ // That means the constructor has to be in DidPush. So I have to validate the
+ // plan AFTER pushing it, and then take it off again...
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
+ return status;
}
void Thread::EnableTracer(bool value, bool single_stepping) {
@@ -1340,23 +1371,24 @@ ThreadPlanSP Thread::QueueFundamentalPlan(bool abort_other_plans) {
}
ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads) {
+ bool step_over, bool abort_other_plans, bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
- LazyBool step_out_avoids_code_withoug_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
ThreadPlanSP thread_plan_sp;
thread_plan_sp.reset(new ThreadPlanStepOverRange(
*this, range, addr_context, stop_other_threads,
step_out_avoids_code_withoug_debug_info));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1365,17 +1397,17 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
- LazyBool step_out_avoids_code_withoug_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
return QueueThreadPlanForStepOverRange(
abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
- addr_context, stop_other_threads,
+ addr_context, stop_other_threads, status,
step_out_avoids_code_withoug_debug_info);
}
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(
@@ -1388,7 +1420,7 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
if (step_in_target)
plan->SetStepInTarget(step_in_target);
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1396,12 +1428,12 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
return QueueThreadPlanForStepInRange(
abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
- addr_context, step_in_target, stop_other_threads,
+ addr_context, step_in_target, stop_other_threads, status,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
}
@@ -1409,23 +1441,19 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
ThreadPlanSP Thread::QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
frame_idx, step_out_avoids_code_without_debug_info));
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- bool continue_to_next_branch) {
+ Status &status, bool continue_to_next_branch) {
const bool calculate_return_value =
false; // No need to calculate the return value here.
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
@@ -1436,59 +1464,51 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
new_plan->ClearShouldStopHereCallbacks();
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
bool abort_other_plans,
- bool stop_other_threads) {
+ bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
return ThreadPlanSP();
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
Address &target_addr,
- bool stop_other_threads) {
+ bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForStepUntil(bool abort_other_plans,
- lldb::addr_t *address_list,
- size_t num_addresses,
- bool stop_other_threads,
- uint32_t frame_idx) {
+ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
+ bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
+ bool stop_other_threads, uint32_t frame_idx, Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
*this, address_list, num_addresses, stop_other_threads, frame_idx));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
- bool abort_other_plans, const char *class_name, bool stop_other_threads) {
+ bool abort_other_plans, const char *class_name, bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- // This seems a little funny, but I don't want to have to split up the
- // constructor and the DidPush in the scripted plan, that seems annoying.
- // That means the constructor has to be in DidPush. So I have to validate the
- // plan AFTER pushing it, and then take it off again...
- if (!thread_plan_sp->ValidatePlan(nullptr)) {
- DiscardThreadPlansUpToPlan(thread_plan_sp);
- return ThreadPlanSP();
- } else
- return thread_plan_sp;
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
uint32_t Thread::GetIndexID() const { return m_index_id; }
@@ -2107,12 +2127,12 @@ Status Thread::StepIn(bool source_step,
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepInRange(
- abort_other_plans, sc.line_entry, sc, nullptr, run_mode,
+ abort_other_plans, sc.line_entry, sc, nullptr, run_mode, error,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, run_mode);
+ false, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2141,11 +2161,11 @@ Status Thread::StepOver(bool source_step,
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepOverRange(
- abort_other_plans, sc.line_entry, sc, run_mode,
+ abort_other_plans, sc.line_entry, sc, run_mode, error,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, run_mode);
+ true, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2170,7 +2190,7 @@ Status Thread::StepOut() {
ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
abort_other_plans, nullptr, first_instruction, stop_other_threads,
- eVoteYes, eVoteNoOpinion, 0));
+ eVoteYes, eVoteNoOpinion, 0, error));
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
@@ -2183,3 +2203,32 @@ Status Thread::StepOut() {
}
return error;
}
+
+ValueObjectSP Thread::GetCurrentException() {
+ if (auto frame_sp = GetStackFrameAtIndex(0))
+ if (auto recognized_frame = frame_sp->GetRecognizedFrame())
+ if (auto e = recognized_frame->GetExceptionObject())
+ return e;
+
+ // FIXME: For now, only ObjC exceptions are supported. This should really
+ // iterate over all language runtimes and ask them all to give us the current
+ // exception.
+ if (auto runtime = GetProcess()->GetObjCLanguageRuntime())
+ if (auto e = runtime->GetExceptionObjectForThread(shared_from_this()))
+ return e;
+
+ return ValueObjectSP();
+}
+
+ThreadSP Thread::GetCurrentExceptionBacktrace() {
+ ValueObjectSP exception = GetCurrentException();
+ if (!exception) return ThreadSP();
+
+ // FIXME: For now, only ObjC exceptions are supported. This should really
+ // iterate over all language runtimes and ask them all to give us the current
+ // exception.
+ auto runtime = GetProcess()->GetObjCLanguageRuntime();
+ if (!runtime) return ThreadSP();
+
+ return runtime->GetBacktraceThreadFromException(exception);
+}
diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp
index ee57a401f742..20c285963882 100644
--- a/source/Target/ThreadList.cpp
+++ b/source/Target/ThreadList.cpp
@@ -7,15 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdlib.h>
-// C++ Includes
#include <algorithm>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
@@ -23,6 +18,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/ThreadPlan.cpp b/source/Target/ThreadPlan.cpp
index 31ee1e922494..1f2c69c6e8a6 100644
--- a/source/Target/ThreadPlan.cpp
+++ b/source/Target/ThreadPlan.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -29,6 +25,7 @@ using namespace lldb_private;
ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
Vote stop_vote, Vote run_vote)
: m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
+ m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
m_kind(kind), m_name(name), m_plan_complete_mutex(),
m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp
index 65b114584177..058d1468e241 100644
--- a/source/Target/ThreadPlanBase.cpp
+++ b/source/Target/ThreadPlanBase.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/ThreadPlanBase.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
//
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -61,10 +57,7 @@ bool ThreadPlanBase::ValidatePlan(Stream *error) { return true; }
bool ThreadPlanBase::DoPlanExplainsStop(Event *event_ptr) {
// The base plan should defer to its tracer, since by default it always
// handles the stop.
- if (TracerExplainsStop())
- return false;
- else
- return true;
+ return !TracerExplainsStop();
}
Vote ThreadPlanBase::ShouldReportStop(Event *event_ptr) {
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index 18beda42fb64..1131ec939b89 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
diff --git a/source/Target/ThreadPlanCallFunctionUsingABI.cpp b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
index b90fd9edd766..08604d2c411a 100644
--- a/source/Target/ThreadPlanCallFunctionUsingABI.cpp
+++ b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
#include "lldb/Core/Address.h"
#include "lldb/Target/Process.h"
diff --git a/source/Target/ThreadPlanCallOnFunctionExit.cpp b/source/Target/ThreadPlanCallOnFunctionExit.cpp
index e8ea73f3c6a0..2ea083dac45e 100644
--- a/source/Target/ThreadPlanCallOnFunctionExit.cpp
+++ b/source/Target/ThreadPlanCallOnFunctionExit.cpp
@@ -27,17 +27,18 @@ void ThreadPlanCallOnFunctionExit::DidPush() {
// completes.
// Set stop vote to eVoteNo.
+ Status status;
m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
false, // abort other plans
nullptr, // addr_context
true, // first instruction
true, // stop other threads
eVoteNo, // do not say "we're stopping"
- eVoteNoOpinion, // don't care about
- // run state broadcasting
+ eVoteNoOpinion, // don't care about run state broadcasting
0, // frame_idx
+ status, // status
eLazyBoolCalculate // avoid code w/o debinfo
- );
+ );
}
// -------------------------------------------------------------------------
diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp
index 7bf0dd39993e..1fbd346feeea 100644
--- a/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/source/Target/ThreadPlanCallUserExpression.cpp
@@ -9,11 +9,7 @@
#include "lldb/Target/ThreadPlanCallUserExpression.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
diff --git a/source/Target/ThreadPlanPython.cpp b/source/Target/ThreadPlanPython.cpp
index 7796b8a0ab20..84b93bdc6583 100644
--- a/source/Target/ThreadPlanPython.cpp
+++ b/source/Target/ThreadPlanPython.cpp
@@ -9,12 +9,7 @@
#include "lldb/Target/ThreadPlan.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
@@ -24,6 +19,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanPython.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -35,7 +31,7 @@ using namespace lldb_private;
ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
: ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_class_name(class_name) {
+ m_class_name(class_name), m_did_push(false) {
SetIsMasterPlan(true);
SetOkayToDiscard(true);
SetPrivate(false);
@@ -47,20 +43,22 @@ ThreadPlanPython::~ThreadPlanPython() {
}
bool ThreadPlanPython::ValidatePlan(Stream *error) {
- // I have to postpone setting up the implementation till after the constructor
- // because I need to call
- // shared_from_this, which you can't do in the constructor. So I'll do it
- // here.
- if (m_implementation_sp)
+ if (!m_did_push)
return true;
- else
+
+ if (!m_implementation_sp) {
+ if (error)
+ error->Printf("Python thread plan does not have an implementation");
return false;
+ }
+
+ return true;
}
void ThreadPlanPython::DidPush() {
// We set up the script side in DidPush, so that it can push other plans in
// the constructor, and doesn't have to care about the details of DidPush.
-
+ m_did_push = true;
if (!m_class_name.empty()) {
ScriptInterpreter *script_interp = m_thread.GetProcess()
->GetTarget()
diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp
index 6d1a8b5c27ff..bd11f8b82f78 100644
--- a/source/Target/ThreadPlanRunToAddress.cpp
+++ b/source/Target/ThreadPlanRunToAddress.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -73,6 +69,8 @@ void ThreadPlanRunToAddress::SetInitialBreakpoints() {
->CreateBreakpoint(m_addresses[i], true, false)
.get();
if (breakpoint != nullptr) {
+ if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
m_break_ids[i] = breakpoint->GetID();
breakpoint->SetThreadID(m_thread.GetID());
breakpoint->SetBreakpointKind("run-to-address");
@@ -85,6 +83,7 @@ ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
for (size_t i = 0; i < num_break_ids; i++) {
m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
}
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanRunToAddress::GetDescription(Stream *s,
@@ -133,10 +132,15 @@ void ThreadPlanRunToAddress::GetDescription(Stream *s,
}
bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->Printf("Could not set hardware breakpoint(s)");
+ return false;
+ }
+
// If we couldn't set the breakpoint for some reason, then this won't work.
bool all_bps_good = true;
size_t num_break_ids = m_break_ids.size();
-
for (size_t i = 0; i < num_break_ids; i++) {
if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
all_bps_good = false;
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp
index c7afe0d9a8a7..8062d8059c14 100644
--- a/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/source/Target/ThreadPlanShouldStopHere.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanShouldStopHere.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/RegisterContext.h"
@@ -43,11 +39,11 @@ ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(
ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;
bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
- FrameComparison operation) {
+ FrameComparison operation, Status &status) {
bool should_stop_here = true;
if (m_callbacks.should_stop_here_callback) {
should_stop_here = m_callbacks.should_stop_here_callback(
- m_owner, m_flags, operation, m_baton);
+ m_owner, m_flags, operation, status, m_baton);
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
if (log) {
lldb::addr_t current_addr =
@@ -63,7 +59,7 @@ bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
if (!frame)
@@ -100,7 +96,7 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
const bool stop_others = false;
const size_t frame_index = 0;
ThreadPlanSP return_plan_sp;
@@ -137,8 +133,8 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
"Queueing StepInRange plan to step through line 0 code.");
return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
- eLazyBoolNo);
+ false, range, sc, NULL, eOnlyDuringStepping, status,
+ eLazyBoolCalculate, eLazyBoolNo);
}
}
@@ -146,24 +142,25 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
return_plan_sp =
current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(
false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,
- frame_index, true);
+ frame_index, status, true);
return return_plan_sp;
}
ThreadPlanSP ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(
- lldb_private::Flags &flags, lldb::FrameComparison operation) {
+ lldb_private::Flags &flags, lldb::FrameComparison operation,
+ Status &status) {
ThreadPlanSP return_plan_sp;
if (m_callbacks.step_from_here_callback) {
- return_plan_sp =
- m_callbacks.step_from_here_callback(m_owner, flags, operation, m_baton);
+ return_plan_sp = m_callbacks.step_from_here_callback(
+ m_owner, flags, operation, status, m_baton);
}
return return_plan_sp;
}
lldb::ThreadPlanSP ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut(
- lldb::FrameComparison operation) {
- if (!InvokeShouldStopHereCallback(operation))
- return QueueStepOutFromHerePlan(m_flags, operation);
+ lldb::FrameComparison operation, Status &status) {
+ if (!InvokeShouldStopHereCallback(operation, status))
+ return QueueStepOutFromHerePlan(m_flags, operation, status);
else
return ThreadPlanSP();
}
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index 6405c135a33e..8f9889a9d68c 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Core/Architecture.h"
#include "lldb/Core/Module.h"
@@ -112,8 +108,16 @@ void ThreadPlanStepInRange::SetupAvoidNoDebug(
void ThreadPlanStepInRange::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
s->Printf("step in");
+ PrintFailureIfAny();
return;
}
@@ -134,6 +138,8 @@ void ThreadPlanStepInRange::GetDescription(Stream *s,
DumpRanges(s);
}
+ PrintFailureIfAny();
+
s->PutChar('.');
}
@@ -166,7 +172,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// ShouldStopHere plan, and otherwise we're done.
// FIXME - This can be both a step in and a step out. Probably should
// record which in the m_virtual_step.
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
+ m_sub_plan_sp =
+ CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger, m_status);
} else {
// Stepping through should be done running other threads in general, since
// we're setting a breakpoint and continuing. So only stop others if we
@@ -185,11 +192,12 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// I'm going to make the assumption that you wouldn't RETURN to a
// trampoline. So if we are in a trampoline we think the frame is older
// because the trampoline confused the backtracer.
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
if (!m_sub_plan_sp) {
// Otherwise check the ShouldStopHere for step out:
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ m_sub_plan_sp =
+ CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
if (log) {
if (m_sub_plan_sp)
log->Printf("ShouldStopHere found plan to step out of this frame.");
@@ -227,8 +235,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// We may have set the plan up above in the FrameIsOlder section:
if (!m_sub_plan_sp)
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
if (log) {
if (m_sub_plan_sp)
@@ -240,7 +248,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// If not, give the "should_stop" callback a chance to push a plan to get
// us out of here. But only do that if we actually have stepped in.
if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
// If we've stepped in and we are going to stop here, check to see if we
// were asked to run past the prologue, and if so do that.
@@ -288,7 +296,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
log->Printf("Pushing past prologue ");
m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(
- false, func_start_address, true);
+ false, func_start_address, true, m_status);
}
}
}
@@ -384,7 +392,7 @@ bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() {
bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -392,7 +400,7 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
// First see if the ThreadPlanShouldStopHere default implementation thinks we
// should get out of here:
should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
- current_plan, flags, operation, baton);
+ current_plan, flags, operation, status, baton);
if (!should_stop_here)
return should_stop_here;
diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp
index dd8f129a935b..7707454c9798 100644
--- a/source/Target/ThreadPlanStepInstruction.cpp
+++ b/source/Target/ThreadPlanStepInstruction.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -57,11 +53,19 @@ void ThreadPlanStepInstruction::SetUpState() {
void ThreadPlanStepInstruction::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
if (m_step_over)
s->Printf("instruction step over");
else
s->Printf("instruction step into");
+
+ PrintFailureIfAny();
} else {
s->Printf("Stepping one instruction past ");
s->Address(m_instruction_addr, sizeof(addr_t));
@@ -72,6 +76,8 @@ void ThreadPlanStepInstruction::GetDescription(Stream *s,
s->Printf(" stepping over calls");
else
s->Printf(" stepping into calls");
+
+ PrintFailureIfAny();
}
}
@@ -192,7 +198,8 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
// for now it is safer to run others.
const bool stop_others = false;
m_thread.QueueThreadPlanForStepOutNoShouldStop(
- false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0);
+ false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
+ m_status);
return false;
} else {
if (log) {
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index f2db6e4b6f42..378de53fafd7 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Value.h"
@@ -48,18 +44,36 @@ ThreadPlanStepOut::ThreadPlanStepOut(
m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
m_immediate_step_from_function(nullptr),
m_calculate_return_value(gather_return_value) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
SetFlagsToDefault();
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
- StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1));
+ uint32_t return_frame_index = frame_idx + 1;
+ StackFrameSP return_frame_sp(
+ m_thread.GetStackFrameAtIndex(return_frame_index));
StackFrameSP immediate_return_from_sp(
m_thread.GetStackFrameAtIndex(frame_idx));
if (!return_frame_sp || !immediate_return_from_sp)
return; // we can't do anything here. ValidatePlan() will return false.
+ // While stepping out, behave as-if artificial frames are not present.
+ while (return_frame_sp->IsArtificial()) {
+ m_stepped_past_frames.push_back(return_frame_sp);
+
+ ++return_frame_index;
+ return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index);
+
+ // We never expect to see an artificial frame without a regular ancestor.
+ // If this happens, log the issue and defensively refuse to step out.
+ if (!return_frame_sp) {
+ LLDB_LOG(log, "Can't step out of frame with artificial ancestors");
+ return;
+ }
+ }
+
m_step_out_to_id = return_frame_sp->GetStackID();
m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
@@ -67,7 +81,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
// have to be a little more careful. It is non-trivial to determine the real
// "return code address" for an inlined frame, so we have to work our way to
// that frame and then step out.
- if (immediate_return_from_sp && immediate_return_from_sp->IsInlined()) {
+ if (immediate_return_from_sp->IsInlined()) {
if (frame_idx > 0) {
// First queue a plan that gets us to this inlined frame, and when we get
// there we'll queue a second plan that walks us out of this frame.
@@ -82,7 +96,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
// just do that now.
QueueInlinedStepPlan(false);
}
- } else if (return_frame_sp) {
+ } else {
// Find the return address and set a breakpoint there:
// FIXME - can we do this more securely if we know first_insn?
@@ -115,7 +129,10 @@ ThreadPlanStepOut::ThreadPlanStepOut(
Breakpoint *return_bp = m_thread.CalculateTarget()
->CreateBreakpoint(m_return_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-out");
@@ -198,19 +215,35 @@ void ThreadPlanStepOut::GetDescription(Stream *s,
s->Printf(" using breakpoint site %d", m_return_bp_id);
}
}
+
+ s->Printf("\n");
+ for (StackFrameSP frame_sp : m_stepped_past_frames) {
+ s->Printf("Stepped out past: ");
+ frame_sp->DumpUsingSettingsFormat(s);
+ }
}
bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
if (m_step_out_to_inline_plan_sp)
return m_step_out_to_inline_plan_sp->ValidatePlan(error);
- else if (m_step_through_inline_plan_sp)
+
+ if (m_step_through_inline_plan_sp)
return m_step_through_inline_plan_sp->ValidatePlan(error);
- else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
if (error)
error->PutCString("Could not create return address breakpoint.");
return false;
- } else
- return true;
+ }
+
+ return true;
}
bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
@@ -257,7 +290,7 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
}
if (done) {
- if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+ if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
CalculateReturnValue();
SetPlanComplete();
}
@@ -319,12 +352,12 @@ bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
// is consult the ShouldStopHere, and we are done.
if (done) {
- if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+ if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
CalculateReturnValue();
SetPlanComplete();
} else {
m_step_out_further_plan_sp =
- QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+ QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status);
done = false;
}
}
diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp
index 7497dbff1729..8b24bf94973b 100644
--- a/source/Target/ThreadPlanStepOverBreakpoint.cpp
+++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index b88d25b707eb..129f30371f8d 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepOverRange.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -51,10 +47,18 @@ ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
void ThreadPlanStepOverRange::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
s->Printf("step over");
+ PrintFailureIfAny();
return;
}
+
s->Printf("Stepping over");
bool printed_line_info = false;
if (m_addr_context.line_entry.IsValid()) {
@@ -68,6 +72,8 @@ void ThreadPlanStepOverRange::GetDescription(Stream *s,
DumpRanges(s);
}
+ PrintFailureIfAny();
+
s->PutChar('.');
}
@@ -117,10 +123,7 @@ bool ThreadPlanStepOverRange::IsEquivalentContext(
}
}
// Fall back to symbol if we have no decision from comp_unit/function/block.
- if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
- return true;
- }
- return false;
+ return m_addr_context.symbol && m_addr_context.symbol == context.symbol;
}
bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
@@ -151,8 +154,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// because the trampoline confused the backtracer. As below, we step
// through first, and then try to figure out how to get back out again.
- new_plan_sp =
- m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
+ stop_others, m_status);
if (new_plan_sp && log)
log->Printf(
@@ -173,11 +176,11 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (IsEquivalentContext(older_context)) {
new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
- true);
+ m_status, true);
break;
} else {
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
// If we found a way through, then we should stop recursing.
if (new_plan_sp)
break;
@@ -196,8 +199,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// we are in a stub then it's likely going to be hard to get out from
// here. It is probably easiest to step into the stub, and then it will
// be straight-forward to step out.
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
} else {
// The current clang (at least through 424) doesn't always get the
// address range for the DW_TAG_inlined_subroutines right, so that when
@@ -287,8 +290,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
cur_pc);
new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
- abort_other_plans, step_range, sc,
- stop_other_threads);
+ abort_other_plans, step_range, sc, stop_other_threads,
+ m_status);
break;
}
look_ahead_step++;
@@ -309,7 +312,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// If we haven't figured out something to do yet, then ask the ShouldStopHere
// callback:
if (!new_plan_sp) {
- new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
}
if (!new_plan_sp)
@@ -323,7 +326,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (!new_plan_sp) {
// For efficiencies sake, we know we're done here so we don't have to do
// this calculation again in MischiefManaged.
- SetPlanComplete();
+ SetPlanComplete(m_status.Success());
return true;
} else
return false;
diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp
index 5a71119015eb..7ba68ee84981 100644
--- a/source/Target/ThreadPlanStepRange.cpp
+++ b/source/Target/ThreadPlanStepRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
@@ -61,7 +57,15 @@ void ThreadPlanStepRange::DidPush() {
SetNextBranchBreakpoint();
}
-bool ThreadPlanStepRange::ValidatePlan(Stream *error) { return true; }
+bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+ return true;
+}
Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -285,6 +289,7 @@ void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
m_next_branch_bp_sp->GetID());
GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
m_next_branch_bp_sp.reset();
+ m_could_not_resolve_hw_bp = false;
}
}
@@ -335,6 +340,11 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
m_next_branch_bp_sp =
GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
if (m_next_branch_bp_sp) {
+
+ if (m_next_branch_bp_sp->IsHardware() &&
+ !m_next_branch_bp_sp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
+
if (log) {
lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
BreakpointLocationSP bp_loc =
@@ -351,8 +361,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
run_to_address.GetLoadAddress(
&m_thread.GetProcess()->GetTarget()));
}
+
m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
+
return true;
} else
return false;
diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp
index c039a32f5515..d1f3c2219f6d 100644
--- a/source/Target/ThreadPlanStepThrough.cpp
+++ b/source/Target/ThreadPlanStepThrough.cpp
@@ -7,12 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepThrough.h"
#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -61,7 +58,10 @@ ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
->GetTarget()
.CreateBreakpoint(m_backstop_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_backstop_bkpt_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-through-backstop");
@@ -95,6 +95,15 @@ void ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() {
if (objc_runtime)
m_sub_plan_sp =
objc_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
+
+ CPPLanguageRuntime *cpp_runtime =
+ m_thread.GetProcess()->GetCPPLanguageRuntime();
+
+ // If the ObjC runtime did not provide us with a step though plan then if we
+ // have it check the C++ runtime for a step though plan.
+ if (!m_sub_plan_sp.get() && cpp_runtime)
+ m_sub_plan_sp =
+ cpp_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
}
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -129,7 +138,26 @@ void ThreadPlanStepThrough::GetDescription(Stream *s,
}
bool ThreadPlanStepThrough::ValidatePlan(Stream *error) {
- return m_sub_plan_sp.get() != nullptr;
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_backstop_bkpt_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create backstop breakpoint.");
+ return false;
+ }
+
+ if (!m_sub_plan_sp.get()) {
+ if (error)
+ error->PutCString("Does not have a subplan.");
+ return false;
+ }
+
+ return true;
}
bool ThreadPlanStepThrough::DoPlanExplainsStop(Event *event_ptr) {
@@ -205,6 +233,7 @@ void ThreadPlanStepThrough::ClearBackstopBreakpoint() {
if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
m_thread.GetProcess()->GetTarget().RemoveBreakpointByID(m_backstop_bkpt_id);
m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
+ m_could_not_resolve_hw_bp = false;
}
}
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
index 9984ee925c86..1335c62ba94c 100644
--- a/source/Target/ThreadPlanStepUntil.cpp
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepUntil.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -57,7 +53,10 @@ ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread,
m_return_addr = return_frame_sp->GetStackID().GetPC();
Breakpoint *return_bp =
target_sp->CreateBreakpoint(m_return_addr, true, false).get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(thread_id);
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("until-return-backstop");
@@ -97,6 +96,7 @@ void ThreadPlanStepUntil::Clear() {
}
}
m_until_points.clear();
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanStepUntil::GetDescription(Stream *s,
@@ -127,9 +127,16 @@ void ThreadPlanStepUntil::GetDescription(Stream *s,
}
bool ThreadPlanStepUntil::ValidatePlan(Stream *error) {
- if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ } else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create return breakpoint.");
return false;
- else {
+ } else {
until_collection::iterator pos, end = m_until_points.end();
for (pos = m_until_points.begin(); pos != end; pos++) {
if (!LLDB_BREAK_ID_IS_VALID((*pos).second))
diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp
index acbbd4d8bcc2..04e29fd26080 100644
--- a/source/Target/ThreadPlanTracer.cpp
+++ b/source/Target/ThreadPlanTracer.cpp
@@ -7,15 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <cstring>
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/TypeList.h"
@@ -30,6 +27,7 @@
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/ThreadSpec.cpp b/source/Target/ThreadSpec.cpp
index 444a5a5b262a..bae3d0b2238f 100644
--- a/source/Target/ThreadSpec.cpp
+++ b/source/Target/ThreadSpec.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp
index 9cfb1b74adee..1448535b8be4 100644
--- a/source/Target/UnixSignals.cpp
+++ b/source/Target/UnixSignals.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnixSignals.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
@@ -88,7 +84,7 @@ void UnixSignals::Reset() {
AddSignal(10, "SIGBUS", false, true, true, "bus error");
AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation");
AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call");
- AddSignal(13, "SIGPIPE", false, true, true,
+ AddSignal(13, "SIGPIPE", false, false, false,
"write on a pipe with no one to read it");
AddSignal(14, "SIGALRM", false, false, false, "alarm clock");
AddSignal(15, "SIGTERM", false, true, true,
diff --git a/source/Target/UnwindAssembly.cpp b/source/Target/UnwindAssembly.cpp
index 3b2b7bf17025..06b6aef28da7 100644
--- a/source/Target/UnwindAssembly.cpp
+++ b/source/Target/UnwindAssembly.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnwindAssembly.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"