aboutsummaryrefslogtreecommitdiff
path: root/source/Target/Target.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/Target.cpp')
-rw-r--r--source/Target/Target.cpp708
1 files changed, 331 insertions, 377 deletions
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_ =