Add the ability to set breakpoints with conditions, commands, etc,

in the "dummy-target".  The dummy target breakpoints prime all future
targets.  Breakpoints set before any target is created (e.g. breakpoints
in ~/.lldbinit) automatically get set in the dummy target.  You can also
list, add & delete breakpoints from the dummy target using the "-D" flag,
which is supported by most of the breakpoint commands.

This removes a long-standing wart in lldb...

<rdar://problem/10881487>

llvm-svn: 223565
This commit is contained in:
Jim Ingham 2014-12-06 01:28:03 +00:00
parent da41af9e94
commit 33df7cd345
28 changed files with 506 additions and 116 deletions

View File

@ -553,10 +553,19 @@ public:
/// This breakpoint's Target.
//------------------------------------------------------------------
Target &
GetTarget ();
GetTarget ()
{
return m_target;
}
const Target &
GetTarget () const;
GetTarget () const
{
return m_target;
}
const lldb::TargetSP
GetTargetSP ();
void
GetResolverDescription (Stream *s);
@ -615,6 +624,18 @@ public:
return m_hardware;
}
lldb::BreakpointResolverSP
GetResolver()
{
return m_resolver_sp;
}
lldb::SearchFilterSP
GetSearchFilter()
{
return m_filter_sp;
}
protected:
friend class Target;
//------------------------------------------------------------------
@ -665,6 +686,11 @@ protected:
IgnoreCountShouldStop ();
private:
// This one should only be used by Target to copy breakpoints from target to target - primarily from the dummy
// target to prime new targets.
Breakpoint (Target &new_target,
Breakpoint &bp_to_copy_from);
//------------------------------------------------------------------
// For Breakpoint only
//------------------------------------------------------------------

View File

@ -44,6 +44,8 @@ namespace lldb_private {
class BreakpointResolver :
public Searcher
{
friend class Breakpoint;
public:
//------------------------------------------------------------------
/// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint
@ -122,7 +124,8 @@ public:
AddressResolver, // This is an instance of BreakpointResolverAddress
NameResolver, // This is an instance of BreakpointResolverName
FileRegexResolver,
ExceptionResolver
ExceptionResolver,
LastKnownResolverType = ExceptionResolver
};
//------------------------------------------------------------------
@ -133,6 +136,9 @@ public:
return SubclassID;
}
virtual lldb::BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) = 0;
protected:
//------------------------------------------------------------------
/// SetSCMatchesByLine - Takes a symbol context list of matches which supposedly represent the same file and

View File

@ -62,6 +62,9 @@ public:
return V->getResolverID() == BreakpointResolver::AddressResolver;
}
lldb::BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override;
protected:
Address m_addr;

View File

@ -58,6 +58,9 @@ public:
return V->getResolverID() == BreakpointResolver::FileLineResolver;
}
lldb::BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override;
protected:
friend class Breakpoint;
FileSpec m_file_spec; // This is the file spec we are looking for.

View File

@ -55,6 +55,9 @@ public:
return V->getResolverID() == BreakpointResolver::FileRegexResolver;
}
lldb::BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override;
protected:
friend class Breakpoint;
RegularExpression m_regex; // This is the line expression that we are looking for.

View File

@ -85,7 +85,12 @@ public:
return V->getResolverID() == BreakpointResolver::NameResolver;
}
lldb::BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override;
protected:
BreakpointResolverName(const BreakpointResolverName &rhs);
struct LookupInfo
{
ConstString name;
@ -113,8 +118,6 @@ protected:
void
AddNameLookup (const ConstString &name, uint32_t name_type_mask);
private:
DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName);
};
} // namespace lldb_private

View File

@ -383,7 +383,7 @@ public:
// This is for use in the command interpreter, when you either want the selected target, or if no target
// is present you want to prime the dummy target with entities that will be copied over to new targets.
Target *GetSelectedOrDummyTarget();
Target *GetSelectedOrDummyTarget(bool prefer_dummy = false);
Target *GetDummyTarget();
protected:

View File

@ -225,8 +225,10 @@ public:
virtual void
Dump (Stream *s) const;
protected:
lldb::SearchFilterSP
CopyForBreakpoint (Breakpoint &breakpoint);
protected:
// These are utility functions to assist with the search iteration. They are used by the
// default Search method.
@ -248,26 +250,40 @@ protected:
const SymbolContext &context,
Searcher &searcher);
virtual lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) = 0;
void
SetTarget(lldb::TargetSP &target_sp)
{
m_target_sp = target_sp;
}
lldb::TargetSP m_target_sp; // Every filter has to be associated with a target for
// now since you need a starting place for the search.
};
//----------------------------------------------------------------------
/// @class SearchFilterForNonModuleSpecificSearches SearchFilter.h "lldb/Core/SearchFilter.h"
/// @brief This is a SearchFilter that searches through all modules. It also consults the Target::ModuleIsExcludedForNonModuleSpecificSearches.
/// @class SearchFilterForUnconstrainedSearches SearchFilter.h "lldb/Core/SearchFilter.h"
/// @brief This is a SearchFilter that searches through all modules. It also consults the Target::ModuleIsExcludedForUnconstrainedSearches.
//----------------------------------------------------------------------
class SearchFilterForNonModuleSpecificSearches :
class SearchFilterForUnconstrainedSearches :
public SearchFilter
{
public:
SearchFilterForNonModuleSpecificSearches (const lldb::TargetSP &targetSP) : SearchFilter(targetSP) {}
~SearchFilterForNonModuleSpecificSearches () {}
SearchFilterForUnconstrainedSearches (const lldb::TargetSP &target_sp) : SearchFilter(target_sp) {}
~SearchFilterForUnconstrainedSearches () {}
virtual bool
ModulePasses (const FileSpec &module_spec);
virtual bool
ModulePasses (const lldb::ModuleSP &module_sp);
protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
};
//----------------------------------------------------------------------
@ -328,6 +344,10 @@ public:
virtual void
Search (Searcher &searcher);
protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
private:
FileSpec m_module_spec;
};
@ -385,6 +405,10 @@ public:
virtual void
Search (Searcher &searcher);
protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
private:
FileSpecList m_module_spec_list;
};
@ -436,6 +460,10 @@ public:
virtual void
Search (Searcher &searcher);
protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
private:
FileSpecList m_module_spec_list;

View File

@ -527,7 +527,7 @@ protected:
// This is for use in the command interpreter, when you either want the selected target, or if no target
// is present you want to prime the dummy target with entities that will be copied over to new targets.
Target *GetSelectedOrDummyTarget();
Target *GetSelectedOrDummyTarget(bool prefer_dummy = false);
Target *GetDummyTarget();
//------------------------------------------------------------------

View File

@ -581,7 +581,7 @@ namespace lldb_private {
// The platform will return "true" from this call if the passed in module happens to be one of these.
virtual bool
ModuleIsExcludedForNonModuleSpecificSearches (Target &target, const lldb::ModuleSP &module_sp)
ModuleIsExcludedForUnconstrainedSearches (Target &target, const lldb::ModuleSP &module_sp)
{
return false;
}

View File

@ -566,6 +566,9 @@ private:
void
PrimeFromDummyTarget(Target *dummy_target);
void
AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal);
public:
~Target();
@ -960,9 +963,9 @@ public:
//------------------------------------------------------------------
/// Return whether this FileSpec corresponds to a module that should be considered for general searches.
///
/// This API will be consulted by the SearchFilterForNonModuleSpecificSearches
/// This API will be consulted by the SearchFilterForUnconstrainedSearches
/// and any module that returns \b true will not be searched. Note the
/// SearchFilterForNonModuleSpecificSearches is the search filter that
/// SearchFilterForUnconstrainedSearches is the search filter that
/// gets used in the CreateBreakpoint calls when no modules is provided.
///
/// The target call at present just consults the Platform's call of the
@ -974,14 +977,14 @@ public:
/// @return \b true if the module should be excluded, \b false otherwise.
//------------------------------------------------------------------
bool
ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_spec);
ModuleIsExcludedForUnconstrainedSearches (const FileSpec &module_spec);
//------------------------------------------------------------------
/// Return whether this module should be considered for general searches.
///
/// This API will be consulted by the SearchFilterForNonModuleSpecificSearches
/// This API will be consulted by the SearchFilterForUnconstrainedSearches
/// and any module that returns \b true will not be searched. Note the
/// SearchFilterForNonModuleSpecificSearches is the search filter that
/// SearchFilterForUnconstrainedSearches is the search filter that
/// gets used in the CreateBreakpoint calls when no modules is provided.
///
/// The target call at present just consults the Platform's call of the
@ -996,7 +999,7 @@ public:
/// @return \b true if the module should be excluded, \b false otherwise.
//------------------------------------------------------------------
bool
ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp);
ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp);
ArchSpec &
GetArchitecture ()

View File

@ -65,6 +65,19 @@ Breakpoint::Breakpoint(Target &target,
m_being_created = false;
}
Breakpoint::Breakpoint (Target &new_target, Breakpoint &source_bp) :
m_being_created(true),
m_hardware(source_bp.m_hardware),
m_target(new_target),
m_options (source_bp.m_options),
m_locations(*this),
m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols)
{
// Now go through and copy the filter & resolver:
m_resolver_sp = source_bp.m_resolver_sp->CopyForBreakpoint(*this);
m_filter_sp = source_bp.m_filter_sp->CopyForBreakpoint(*this);
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@ -72,26 +85,18 @@ Breakpoint::~Breakpoint()
{
}
const lldb::TargetSP
Breakpoint::GetTargetSP ()
{
return m_target.shared_from_this();
}
bool
Breakpoint::IsInternal () const
{
return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
}
Target&
Breakpoint::GetTarget ()
{
return m_target;
}
const Target&
Breakpoint::GetTarget () const
{
return m_target;
}
BreakpointLocationSP
Breakpoint::AddLocation (const Address &addr, bool *new_location)
{

View File

@ -109,3 +109,11 @@ BreakpointResolverAddress::Dump (Stream *s) const
{
}
lldb::BreakpointResolverSP
BreakpointResolverAddress::CopyForBreakpoint (Breakpoint &breakpoint)
{
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverAddress(&breakpoint, m_addr));
return ret_sp;
}

View File

@ -110,3 +110,14 @@ BreakpointResolverFileLine::Dump (Stream *s) const
}
lldb::BreakpointResolverSP
BreakpointResolverFileLine::CopyForBreakpoint (Breakpoint &breakpoint)
{
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(&breakpoint,
m_file_spec,
m_line_number,
m_inlines,
m_skip_prologue));
return ret_sp;
}

View File

@ -95,3 +95,10 @@ BreakpointResolverFileRegex::Dump (Stream *s) const
}
lldb::BreakpointResolverSP
BreakpointResolverFileRegex::CopyForBreakpoint (Breakpoint &breakpoint)
{
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(&breakpoint, m_regex));
return ret_sp;
}

View File

@ -121,6 +121,17 @@ BreakpointResolverName::~BreakpointResolverName ()
{
}
BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs) :
BreakpointResolver(rhs.m_breakpoint, BreakpointResolver::NameResolver),
m_lookups(rhs.m_lookups),
m_class_name(rhs.m_class_name),
m_regex(rhs.m_regex),
m_match_type (rhs.m_match_type),
m_skip_prologue (rhs.m_skip_prologue)
{
}
void
BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask)
{
@ -371,3 +382,10 @@ BreakpointResolverName::Dump (Stream *s) const
}
lldb::BreakpointResolverSP
BreakpointResolverName::CopyForBreakpoint (Breakpoint &breakpoint)
{
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverName(*this));
ret_sp->SetBreakpoint(&breakpoint);
return ret_sp;
}

View File

@ -112,7 +112,7 @@ CommandCompletions::SourceFiles
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
SearchFilter null_searcher (target_sp);
SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else
@ -375,7 +375,7 @@ CommandCompletions::Modules
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
SearchFilter null_searcher (target_sp);
SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else
@ -406,7 +406,7 @@ CommandCompletions::Symbols
if (searcher == NULL)
{
lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
SearchFilter null_searcher (target_sp);
SearchFilterForUnconstrainedSearches null_searcher (target_sp);
completer.DoCompletion (&null_searcher);
}
else

View File

@ -145,6 +145,10 @@ public:
m_condition.assign(option_arg);
break;
case 'D':
m_use_dummy = true;
break;
case 'E':
{
LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
@ -324,6 +328,7 @@ public:
m_language = eLanguageTypeUnknown;
m_skip_prologue = eLazyBoolCalculate;
m_one_shot = false;
m_use_dummy = false;
}
const OptionDefinition*
@ -359,15 +364,17 @@ public:
lldb::LanguageType m_language;
LazyBool m_skip_prologue;
bool m_one_shot;
bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command,
CommandReturnObject &result)
CommandReturnObject &result)
{
Target *target = GetSelectedOrDummyTarget();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == nullptr)
{
result.AppendError ("Invalid target. Must set target before setting breakpoints (see 'target create' command).");
@ -709,6 +716,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{ LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." },
{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@ -766,7 +776,8 @@ public:
m_name_passed (false),
m_queue_passed (false),
m_condition_passed (false),
m_one_shot_passed (false)
m_one_shot_passed (false),
m_use_dummy (false)
{
}
@ -792,6 +803,9 @@ public:
m_enable_passed = true;
m_enable_value = false;
break;
case 'D':
m_use_dummy = true;
break;
case 'e':
m_enable_passed = true;
m_enable_value = true;
@ -888,6 +902,7 @@ public:
m_name_passed = false;
m_condition_passed = false;
m_one_shot_passed = false;
m_use_dummy = false;
}
const OptionDefinition*
@ -918,6 +933,7 @@ public:
bool m_queue_passed;
bool m_condition_passed;
bool m_one_shot_passed;
bool m_use_dummy;
};
@ -925,7 +941,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = GetSelectedOrDummyTarget();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@ -1024,6 +1040,8 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
{ LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
{ LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@ -1293,7 +1311,8 @@ public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter),
m_level (lldb::eDescriptionLevelBrief) // Breakpoint List defaults to brief descriptions
m_level (lldb::eDescriptionLevelBrief),
m_use_dummy(false)
{
}
@ -1311,6 +1330,9 @@ public:
case 'b':
m_level = lldb::eDescriptionLevelBrief;
break;
case 'D':
m_use_dummy = true;
break;
case 'f':
m_level = lldb::eDescriptionLevelFull;
break;
@ -1333,6 +1355,7 @@ public:
{
m_level = lldb::eDescriptionLevelFull;
m_internal = false;
m_use_dummy = false;
}
const OptionDefinition *
@ -1350,13 +1373,15 @@ public:
lldb::DescriptionLevel m_level;
bool m_internal;
bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = GetSelectedOrDummyTarget();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
result.AppendError ("Invalid target. No current target or breakpoints.");
@ -1438,6 +1463,9 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Explain everything we know about the breakpoint (for debugging debugger bugs)." },
{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@ -1656,7 +1684,8 @@ public:
CommandObjectParsed (interpreter,
"breakpoint delete",
"Delete the specified breakpoint(s). If no breakpoints are specified, delete them all.",
NULL)
NULL),
m_options (interpreter)
{
CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
@ -1667,11 +1696,78 @@ public:
virtual
~CommandObjectBreakpointDelete () {}
virtual Options *
GetOptions ()
{
return &m_options;
}
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter),
m_use_dummy (false),
m_force (false)
{
}
virtual
~CommandOptions () {}
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
case 'f':
m_force = true;
break;
case 'D':
m_use_dummy = true;
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_use_dummy = false;
m_force = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
bool m_use_dummy;
bool m_force;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = GetSelectedOrDummyTarget();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
result.AppendError ("Invalid target. No existing target or breakpoints.");
@ -1695,7 +1791,7 @@ protected:
if (command.GetArgumentCount() == 0)
{
if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
{
result.AppendMessage("Operation cancelled...");
}
@ -1748,6 +1844,20 @@ protected:
}
return result.Succeeded();
}
private:
CommandOptions m_options;
};
OptionDefinition
CommandObjectBreakpointDelete::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Delete all breakpoints without querying for confirmation."},
{ LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------

View File

@ -389,6 +389,10 @@ one command per line.\n" );
}
break;
case 'D':
m_use_dummy = true;
break;
default:
break;
}
@ -405,6 +409,7 @@ one command per line.\n" );
m_stop_on_error = true;
m_one_liner.clear();
m_function_name.clear();
m_use_dummy = false;
}
const OptionDefinition*
@ -428,13 +433,14 @@ one command per line.\n" );
std::string m_one_liner;
bool m_stop_on_error;
std::string m_function_name;
bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
@ -580,6 +586,9 @@ CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
"Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@ -594,7 +603,8 @@ public:
CommandObjectParsed (interpreter,
"delete",
"Delete the set of commands from a breakpoint.",
NULL)
NULL),
m_options (interpreter)
{
CommandArgumentEntry arg;
CommandArgumentData bp_id_arg;
@ -614,11 +624,70 @@ public:
virtual
~CommandObjectBreakpointCommandDelete () {}
virtual Options *
GetOptions ()
{
return &m_options;
}
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter),
m_use_dummy (false)
{
}
virtual
~CommandOptions () {}
virtual Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
case 'D':
m_use_dummy = true;
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_use_dummy = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
bool m_use_dummy;
};
protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
{
@ -679,8 +748,20 @@ protected:
}
return result.Succeeded();
}
private:
CommandOptions m_options;
};
OptionDefinition
CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
"Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandList
//-------------------------------------------------------------------------

View File

@ -421,7 +421,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (start_file, 0, show_inlines);
SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
SearchFilterForUnconstrainedSearches target_search_filter (m_exe_ctx.GetTargetSP());
target_search_filter.Search (m_breakpoint_locations);
}
@ -682,7 +682,7 @@ protected:
m_breakpoint_locations.Clear();
const bool show_inlines = true;
m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
SearchFilter target_search_filter (target->shared_from_this());
SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
@ -743,7 +743,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines);
SearchFilter target_search_filter (target->shared_from_this());
SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
}
@ -846,7 +846,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines);
SearchFilter target_search_filter (target->shared_from_this());
SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this());
target_search_filter.Search (m_breakpoint_locations);
}
else

View File

@ -3418,12 +3418,16 @@ Debugger::GetDummyTarget()
}
Target *
Debugger::GetSelectedOrDummyTarget()
Debugger::GetSelectedOrDummyTarget(bool prefer_dummy)
{
Target *return_target = m_target_list.GetSelectedTarget().get();
if (return_target)
return return_target;
Target *target = nullptr;
if (!prefer_dummy)
{
target = m_target_list.GetSelectedTarget().get();
if (target)
return target;
}
return GetDummyTarget();
}

View File

@ -119,6 +119,15 @@ SearchFilter::Dump (Stream *s) const
}
lldb::SearchFilterSP
SearchFilter::CopyForBreakpoint (Breakpoint &breakpoint)
{
SearchFilterSP ret_sp = DoCopyForBreakpoint (breakpoint);
TargetSP target_sp = breakpoint.GetTargetSP();
ret_sp->SetTarget(target_sp);
return ret_sp;
}
//----------------------------------------------------------------------
// UTILITY Functions to help iterate down through the elements of the
// SymbolContext.
@ -281,29 +290,36 @@ SearchFilter::DoFunctionIteration (Function *function, const SymbolContext &cont
}
//----------------------------------------------------------------------
// SearchFilterForNonModuleSpecificSearches:
// SearchFilterForUnconstrainedSearches:
// Selects a shared library matching a given file spec, consulting the targets "black list".
//----------------------------------------------------------------------
bool
SearchFilterForNonModuleSpecificSearches::ModulePasses (const FileSpec &module_spec)
{
if (m_target_sp->ModuleIsExcludedForNonModuleSpecificSearches (module_spec))
return false;
else
return true;
}
bool
SearchFilterForNonModuleSpecificSearches::ModulePasses (const lldb::ModuleSP &module_sp)
{
if (!module_sp)
return true;
else if (m_target_sp->ModuleIsExcludedForNonModuleSpecificSearches (module_sp))
return false;
else
return true;
}
bool
SearchFilterForUnconstrainedSearches::ModulePasses (const FileSpec &module_spec)
{
if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_spec))
return false;
else
return true;
}
bool
SearchFilterForUnconstrainedSearches::ModulePasses (const lldb::ModuleSP &module_sp)
{
if (!module_sp)
return true;
else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_sp))
return false;
else
return true;
}
lldb::SearchFilterSP
SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint (Breakpoint &breakpoint)
{
SearchFilterSP ret_sp(new SearchFilterForUnconstrainedSearches(*this));
return ret_sp;
}
//----------------------------------------------------------------------
// SearchFilterByModule:
@ -449,6 +465,14 @@ SearchFilterByModule::Dump (Stream *s) const
{
}
lldb::SearchFilterSP
SearchFilterByModule::DoCopyForBreakpoint (Breakpoint &breakpoint)
{
SearchFilterSP ret_sp(new SearchFilterByModule(*this));
return ret_sp;
}
//----------------------------------------------------------------------
// SearchFilterByModuleList:
// Selects a shared library matching a given file spec
@ -458,7 +482,8 @@ SearchFilterByModule::Dump (Stream *s) const
// SearchFilterByModuleList constructors
//----------------------------------------------------------------------
SearchFilterByModuleList::SearchFilterByModuleList (const lldb::TargetSP &target_sp, const FileSpecList &module_list) :
SearchFilterByModuleList::SearchFilterByModuleList (const lldb::TargetSP &target_sp,
const FileSpecList &module_list) :
SearchFilter (target_sp),
m_module_spec_list (module_list)
{
@ -623,6 +648,14 @@ SearchFilterByModuleList::Dump (Stream *s) const
}
lldb::SearchFilterSP
SearchFilterByModuleList::DoCopyForBreakpoint (Breakpoint &breakpoint)
{
SearchFilterSP ret_sp(new SearchFilterByModuleList(*this));
return ret_sp;
}
//----------------------------------------------------------------------
// SearchFilterByModuleListAndCU:
// Selects a shared library matching a given file spec
@ -814,3 +847,10 @@ SearchFilterByModuleListAndCU::Dump (Stream *s) const
}
lldb::SearchFilterSP
SearchFilterByModuleListAndCU::DoCopyForBreakpoint (Breakpoint &breakpoint)
{
SearchFilterSP ret_sp(new SearchFilterByModuleListAndCU(*this));
return ret_sp;
}

View File

@ -1025,9 +1025,9 @@ CommandObject::GetDummyTarget()
}
Target *
CommandObject::GetSelectedOrDummyTarget()
CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy)
{
return m_interpreter.GetDebugger().GetSelectedOrDummyTarget();
return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
}
bool

View File

@ -666,7 +666,7 @@ PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
}
bool
PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
{
if (!module_sp)
return false;

View File

@ -66,7 +66,7 @@ public:
lldb_private::ProcessInstanceInfoList &process_infos) override;
bool
ModuleIsExcludedForNonModuleSpecificSearches(lldb_private::Target &target,
ModuleIsExcludedForUnconstrainedSearches(lldb_private::Target &target,
const lldb::ModuleSP &module_sp) override;
bool

View File

@ -10,6 +10,7 @@
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/SearchFilter.h"
using namespace lldb;
using namespace lldb_private;
@ -19,15 +20,20 @@ class ExceptionSearchFilter : public SearchFilter
{
public:
ExceptionSearchFilter (const lldb::TargetSP &target_sp,
lldb::LanguageType language) :
lldb::LanguageType language,
bool update_module_list = true) :
SearchFilter (target_sp),
m_language (language),
m_language_runtime (NULL),
m_filter_sp ()
{
UpdateModuleListIfNeeded ();
if (update_module_list)
UpdateModuleListIfNeeded ();
}
virtual
~ExceptionSearchFilter() {};
virtual bool
ModulePasses (const lldb::ModuleSP &module_sp)
{
@ -68,6 +74,12 @@ protected:
LanguageRuntime *m_language_runtime;
SearchFilterSP m_filter_sp;
SearchFilterSP
DoCopyForBreakpoint(Breakpoint &breakpoint) override
{
return SearchFilterSP(new ExceptionSearchFilter(TargetSP(), m_language, false));
}
void
UpdateModuleListIfNeeded ()
{
@ -174,6 +186,12 @@ public:
return V->getResolverID() == BreakpointResolver::ExceptionResolver;
}
protected:
BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override
{
return BreakpointResolverSP(new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
}
bool
SetActualResolver()
{

View File

@ -100,9 +100,6 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
CheckInWithManager();
if (!m_is_dummy_target)
PrimeFromDummyTarget(m_debugger.GetDummyTarget());
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
log->Printf ("%p Target::Target()", static_cast<void*>(this));
@ -119,7 +116,15 @@ Target::PrimeFromDummyTarget(Target *target)
return;
m_stop_hooks = target->m_stop_hooks;
for (BreakpointSP breakpoint_sp : target->m_breakpoint_list.Breakpoints())
{
if (breakpoint_sp->IsInternal())
continue;
BreakpointSP new_bp (new Breakpoint (*this, *breakpoint_sp.get()));
AddBreakpoint (new_bp, false);
}
}
//----------------------------------------------------------------------
@ -346,7 +351,7 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
BreakpointSP
Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
{
SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this()));
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false);
}
@ -446,7 +451,7 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule)
else
{
if (m_search_filter_sp.get() == NULL)
m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
return filter_sp;
@ -465,7 +470,7 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules)
else
{
if (m_search_filter_sp.get() == NULL)
m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
return filter_sp;
@ -526,29 +531,35 @@ Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resol
{
bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware, resolve_indirect_symbols));
resolver_sp->SetBreakpoint (bp_sp.get());
if (internal)
m_internal_breakpoint_list.Add (bp_sp, false);
else
m_breakpoint_list.Add (bp_sp, true);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
if (log)
{
StreamString s;
bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData());
}
bp_sp->ResolveBreakpoint();
AddBreakpoint (bp_sp, internal);
}
if (!internal && bp_sp)
return bp_sp;
}
void
Target::AddBreakpoint (lldb::BreakpointSP bp_sp, bool internal)
{
if (!bp_sp)
return;
if (internal)
m_internal_breakpoint_list.Add (bp_sp, false);
else
m_breakpoint_list.Add (bp_sp, true);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
if (log)
{
StreamString s;
bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, bp_sp->IsInternal() ? "yes" : "no", s.GetData());
}
bp_sp->ResolveBreakpoint();
if (!internal)
{
m_last_created_breakpoint = bp_sp;
}
return bp_sp;
}
bool
@ -1238,7 +1249,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
}
bool
Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_file_spec)
Target::ModuleIsExcludedForUnconstrainedSearches (const FileSpec &module_file_spec)
{
if (GetBreakpointsConsultPlatformAvoidList())
{
@ -1252,7 +1263,7 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil
{
for (size_t i = 0; i < num_modules; i++)
{
if (!ModuleIsExcludedForNonModuleSpecificSearches (matchingModules.GetModuleAtIndex(i)))
if (!ModuleIsExcludedForUnconstrainedSearches (matchingModules.GetModuleAtIndex(i)))
return false;
}
return true;
@ -1262,12 +1273,12 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil
}
bool
Target::ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp)
Target::ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp)
{
if (GetBreakpointsConsultPlatformAvoidList())
{
if (m_platform_sp)
return m_platform_sp->ModuleIsExcludedForNonModuleSpecificSearches (*this, module_sp);
return m_platform_sp->ModuleIsExcludedForUnconstrainedSearches (*this, module_sp);
}
return false;
}

View File

@ -501,6 +501,8 @@ TargetList::CreateTargetInternal (Debugger &debugger,
Mutex::Locker locker(m_target_list_mutex);
m_selected_target_idx = m_target_list.size();
m_target_list.push_back(target_sp);
// Now prime this from the dummy target:
target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
}
else
{