forked from OSchip/llvm-project
Add one-shot breakpoints (-o option to "break set") and a tbreak alias for our gdb friends.
llvm-svn: 165328
This commit is contained in:
parent
874f43cadc
commit
ca36cd16e4
|
@ -64,6 +64,12 @@ public:
|
|||
bool
|
||||
IsEnabled ();
|
||||
|
||||
void
|
||||
SetOneShot (bool one_shot);
|
||||
|
||||
bool
|
||||
IsOneShot () const;
|
||||
|
||||
bool
|
||||
IsInternal ();
|
||||
|
||||
|
|
|
@ -355,6 +355,20 @@ public:
|
|||
GetHitCount () const;
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// If \a one_shot is \b true, breakpoint will be deleted on first hit.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
SetOneShot (bool one_shot);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check the OneShot state.
|
||||
/// @return
|
||||
/// \b true if the breakpoint is one shot, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
IsOneShot () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the valid thread to be checked when the breakpoint is hit.
|
||||
/// @param[in] thread_id
|
||||
|
|
|
@ -67,7 +67,8 @@ public:
|
|||
void *baton,
|
||||
bool enabled = true,
|
||||
int32_t ignore = 0,
|
||||
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
|
||||
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID,
|
||||
bool one_shot = false);
|
||||
|
||||
virtual ~BreakpointOptions();
|
||||
|
||||
|
@ -195,13 +196,39 @@ public:
|
|||
/// \b true if the breakpoint is enabled, \b false if disabled.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
IsEnabled () const;
|
||||
IsEnabled () const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// If \a enable is \b true, enable the breakpoint, if \b false disable it.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
SetEnabled (bool enabled);
|
||||
SetEnabled (bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check the One-shot state.
|
||||
/// @return
|
||||
/// \b true if the breakpoint is one-shot, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
IsOneShot () const
|
||||
{
|
||||
return m_one_shot;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// If \a enable is \b true, enable the breakpoint, if \b false disable it.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
SetOneShot (bool one_shot)
|
||||
{
|
||||
m_one_shot = one_shot;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the breakpoint to ignore the next \a count breakpoint hits.
|
||||
|
@ -210,7 +237,10 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
|
||||
void
|
||||
SetIgnoreCount (uint32_t n);
|
||||
SetIgnoreCount (uint32_t n)
|
||||
{
|
||||
m_ignore_count = n;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the current Ignore Count.
|
||||
|
@ -218,7 +248,10 @@ public:
|
|||
/// The number of breakpoint hits to be ignored.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
GetIgnoreCount () const;
|
||||
GetIgnoreCount () const
|
||||
{
|
||||
return m_ignore_count;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the current thread spec for this option. This will return NULL if the no thread
|
||||
|
@ -314,6 +347,7 @@ private:
|
|||
lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback
|
||||
bool m_callback_is_synchronous;
|
||||
bool m_enabled;
|
||||
bool m_one_shot;
|
||||
uint32_t m_ignore_count; // Number of times to ignore this breakpoint
|
||||
std::auto_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this breakpoint will take
|
||||
std::auto_ptr<ClangUserExpression> m_condition_ap; // The condition to test.
|
||||
|
|
|
@ -119,6 +119,12 @@ public:
|
|||
bool
|
||||
IsEnabled ();
|
||||
|
||||
void
|
||||
SetOneShot (bool one_shot);
|
||||
|
||||
bool
|
||||
IsOneShot ();
|
||||
|
||||
bool
|
||||
IsInternal ();
|
||||
|
||||
|
|
|
@ -234,6 +234,33 @@ SBBreakpoint::IsEnabled ()
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SBBreakpoint::SetOneShot (bool one_shot)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
|
||||
if (log)
|
||||
log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)", m_opaque_sp.get(), one_shot);
|
||||
|
||||
if (m_opaque_sp)
|
||||
{
|
||||
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
|
||||
m_opaque_sp->SetOneShot (one_shot);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SBBreakpoint::IsOneShot () const
|
||||
{
|
||||
if (m_opaque_sp)
|
||||
{
|
||||
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
|
||||
return m_opaque_sp->IsOneShot();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SBBreakpoint::IsInternal ()
|
||||
{
|
||||
|
|
|
@ -189,6 +189,18 @@ Breakpoint::GetHitCount () const
|
|||
return m_locations.GetHitCount();
|
||||
}
|
||||
|
||||
bool
|
||||
Breakpoint::IsOneShot () const
|
||||
{
|
||||
return m_options.IsOneShot();
|
||||
}
|
||||
|
||||
void
|
||||
Breakpoint::SetOneShot (bool one_shot)
|
||||
{
|
||||
m_options.SetOneShot (one_shot);
|
||||
}
|
||||
|
||||
void
|
||||
Breakpoint::SetThreadID (lldb::tid_t thread_id)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@ BreakpointOptions::BreakpointOptions() :
|
|||
m_callback_baton_sp (),
|
||||
m_callback_is_synchronous (false),
|
||||
m_enabled (true),
|
||||
m_one_shot (false),
|
||||
m_ignore_count (0),
|
||||
m_thread_spec_ap (NULL),
|
||||
m_condition_ap()
|
||||
|
@ -53,6 +54,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
|
|||
m_callback_baton_sp (rhs.m_callback_baton_sp),
|
||||
m_callback_is_synchronous (rhs.m_callback_is_synchronous),
|
||||
m_enabled (rhs.m_enabled),
|
||||
m_one_shot (rhs.m_one_shot),
|
||||
m_ignore_count (rhs.m_ignore_count),
|
||||
m_thread_spec_ap (NULL),
|
||||
m_condition_ap (NULL)
|
||||
|
@ -73,6 +75,7 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs)
|
|||
m_callback_baton_sp = rhs.m_callback_baton_sp;
|
||||
m_callback_is_synchronous = rhs.m_callback_is_synchronous;
|
||||
m_enabled = rhs.m_enabled;
|
||||
m_one_shot = rhs.m_one_shot;
|
||||
m_ignore_count = rhs.m_ignore_count;
|
||||
if (rhs.m_thread_spec_ap.get() != NULL)
|
||||
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
|
||||
|
@ -179,33 +182,6 @@ BreakpointOptions::GetConditionText () const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Enabled/Ignore Count
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
BreakpointOptions::IsEnabled () const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointOptions::SetEnabled (bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
BreakpointOptions::GetIgnoreCount () const
|
||||
{
|
||||
return m_ignore_count;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointOptions::SetIgnoreCount (uint32_t n)
|
||||
{
|
||||
m_ignore_count = n;
|
||||
}
|
||||
|
||||
const ThreadSpec *
|
||||
BreakpointOptions::GetThreadSpecNoCreate () const
|
||||
{
|
||||
|
@ -234,7 +210,7 @@ BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) cons
|
|||
// Figure out if there are any options not at their default value, and only print
|
||||
// anything if there are:
|
||||
|
||||
if (m_ignore_count != 0 || !m_enabled || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
|
||||
if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
|
||||
{
|
||||
if (level == lldb::eDescriptionLevelVerbose)
|
||||
{
|
||||
|
@ -252,6 +228,9 @@ BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) cons
|
|||
s->Printf("ignore: %d ", m_ignore_count);
|
||||
s->Printf("%sabled ", m_enabled ? "en" : "dis");
|
||||
|
||||
if (m_one_shot)
|
||||
s->Printf ("one-shot ");
|
||||
|
||||
if (m_thread_spec_ap.get())
|
||||
m_thread_spec_ap->GetDescription (s, level);
|
||||
else if (level == eDescriptionLevelBrief)
|
||||
|
|
|
@ -105,7 +105,8 @@ public:
|
|||
m_catch_bp (false),
|
||||
m_throw_bp (true),
|
||||
m_language (eLanguageTypeUnknown),
|
||||
m_skip_prologue (eLazyBoolCalculate)
|
||||
m_skip_prologue (eLazyBoolCalculate),
|
||||
m_one_shot (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -130,6 +131,11 @@ public:
|
|||
error.SetErrorStringWithFormat ("invalid address string '%s'", option_arg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeBase;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
m_column = Args::StringToUInt32 (option_arg, 0);
|
||||
break;
|
||||
|
@ -138,80 +144,6 @@ public:
|
|||
m_condition.assign(option_arg);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
m_filenames.AppendIfUnique (FileSpec(option_arg, false));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
m_line_num = Args::StringToUInt32 (option_arg, 0);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeBase;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeAuto;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeFull;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeSelector;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeMethod;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
m_source_text_regexp.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
m_func_regexp.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
{
|
||||
m_modules.AppendIfUnique (FileSpec (option_arg, false));
|
||||
break;
|
||||
}
|
||||
case 'i':
|
||||
{
|
||||
m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
|
||||
if (m_ignore_count == UINT32_MAX)
|
||||
error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
case 't' :
|
||||
{
|
||||
m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
|
||||
if (m_thread_id == LLDB_INVALID_THREAD_ID)
|
||||
error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
m_thread_name.assign (option_arg);
|
||||
break;
|
||||
case 'q':
|
||||
m_queue_name.assign (option_arg);
|
||||
break;
|
||||
case 'x':
|
||||
{
|
||||
m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
|
||||
if (m_thread_id == UINT32_MAX)
|
||||
error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
|
||||
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
{
|
||||
LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
|
||||
|
@ -240,14 +172,16 @@ public:
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
{
|
||||
bool success;
|
||||
m_throw_bp = Args::StringToBoolean (option_arg, true, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
m_filenames.AppendIfUnique (FileSpec(option_arg, false));
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeFull;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
{
|
||||
bool success;
|
||||
|
@ -255,6 +189,15 @@ public:
|
|||
if (!success)
|
||||
error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
|
||||
if (m_ignore_count == UINT32_MAX)
|
||||
error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'K':
|
||||
{
|
||||
bool success;
|
||||
|
@ -269,6 +212,78 @@ public:
|
|||
error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
m_line_num = Args::StringToUInt32 (option_arg, 0);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeMethod;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeAuto;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
m_one_shot = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
m_source_text_regexp.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
m_queue_name.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
m_func_regexp.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
{
|
||||
m_modules.AppendIfUnique (FileSpec (option_arg, false));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'S':
|
||||
m_func_names.push_back (option_arg);
|
||||
m_func_name_type_mask |= eFunctionNameTypeSelector;
|
||||
break;
|
||||
|
||||
case 't' :
|
||||
{
|
||||
m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
|
||||
if (m_thread_id == LLDB_INVALID_THREAD_ID)
|
||||
error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
m_thread_name.assign (option_arg);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
{
|
||||
bool success;
|
||||
m_throw_bp = Args::StringToBoolean (option_arg, true, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
{
|
||||
m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
|
||||
if (m_thread_id == UINT32_MAX)
|
||||
error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
|
||||
break;
|
||||
|
@ -298,6 +313,7 @@ public:
|
|||
m_throw_bp = true;
|
||||
m_language = eLanguageTypeUnknown;
|
||||
m_skip_prologue = eLazyBoolCalculate;
|
||||
m_one_shot = false;
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
|
@ -331,6 +347,7 @@ public:
|
|||
bool m_throw_bp;
|
||||
lldb::LanguageType m_language;
|
||||
LazyBool m_skip_prologue;
|
||||
bool m_one_shot;
|
||||
|
||||
};
|
||||
|
||||
|
@ -511,6 +528,8 @@ protected:
|
|||
|
||||
if (!m_options.m_condition.empty())
|
||||
bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
|
||||
|
||||
bp->SetOneShot (m_options.m_one_shot);
|
||||
}
|
||||
|
||||
if (bp)
|
||||
|
@ -591,6 +610,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
|
|||
{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount,
|
||||
"Set the number of times this breakpoint is skipped before stopping." },
|
||||
|
||||
{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', no_argument, NULL, 0, eArgTypeNone,
|
||||
"The breakpoint is deleted the first time it stop causes a stop." },
|
||||
|
||||
{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression,
|
||||
"The breakpoint stops only if this condition expression evaluates to true."},
|
||||
|
||||
|
@ -707,11 +729,13 @@ public:
|
|||
m_thread_name(),
|
||||
m_queue_name(),
|
||||
m_condition (),
|
||||
m_one_shot (false),
|
||||
m_enable_passed (false),
|
||||
m_enable_value (false),
|
||||
m_name_passed (false),
|
||||
m_queue_passed (false),
|
||||
m_condition_passed (false)
|
||||
m_condition_passed (false),
|
||||
m_one_shot_passed (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -748,6 +772,19 @@ public:
|
|||
error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
{
|
||||
bool value, success;
|
||||
value = Args::StringToBoolean(option_arg, false, &success);
|
||||
if (success)
|
||||
{
|
||||
m_one_shot_passed = true;
|
||||
m_one_shot = value;
|
||||
}
|
||||
else
|
||||
error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg);
|
||||
}
|
||||
break;
|
||||
case 't' :
|
||||
{
|
||||
if (option_arg[0] == '\0')
|
||||
|
@ -814,10 +851,12 @@ public:
|
|||
m_thread_name.clear();
|
||||
m_queue_name.clear();
|
||||
m_condition.clear();
|
||||
m_one_shot = false;
|
||||
m_enable_passed = false;
|
||||
m_queue_passed = false;
|
||||
m_name_passed = false;
|
||||
m_condition_passed = false;
|
||||
m_one_shot_passed = false;
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
|
@ -841,11 +880,13 @@ public:
|
|||
std::string m_thread_name;
|
||||
std::string m_queue_name;
|
||||
std::string m_condition;
|
||||
bool m_one_shot;
|
||||
bool m_enable_passed;
|
||||
bool m_enable_value;
|
||||
bool m_name_passed;
|
||||
bool m_queue_passed;
|
||||
bool m_condition_passed;
|
||||
bool m_one_shot_passed;
|
||||
|
||||
};
|
||||
|
||||
|
@ -944,6 +985,7 @@ OptionDefinition
|
|||
CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
|
||||
{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', required_argument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
|
||||
{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument."},
|
||||
{ LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
|
||||
{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
|
||||
|
@ -951,7 +993,7 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
|
|||
{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
|
||||
{ LLDB_OPT_SET_1, false, "enable", 'e', no_argument, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
|
||||
{ LLDB_OPT_SET_2, false, "disable", 'd', no_argument, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
|
||||
{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
|
||||
{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
|
@ -156,6 +156,14 @@ CommandInterpreter::Initialize ()
|
|||
if (cmd_obj_sp)
|
||||
AddAlias ("b", cmd_obj_sp);
|
||||
|
||||
cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
|
||||
if (cmd_obj_sp)
|
||||
AddAlias ("tbreak", cmd_obj_sp);
|
||||
|
||||
cmd_obj_sp = GetCommandSPExact ("thread backtrace", false);
|
||||
if (cmd_obj_sp)
|
||||
AddAlias ("bt", cmd_obj_sp);
|
||||
|
||||
cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
|
||||
if (cmd_obj_sp)
|
||||
{
|
||||
|
@ -196,6 +204,12 @@ CommandInterpreter::Initialize ()
|
|||
AddAlias ("f", cmd_obj_sp);
|
||||
}
|
||||
|
||||
cmd_obj_sp = GetCommandSPExact ("thread select", false);
|
||||
if (cmd_obj_sp)
|
||||
{
|
||||
AddAlias ("t", cmd_obj_sp);
|
||||
}
|
||||
|
||||
cmd_obj_sp = GetCommandSPExact ("source list", false);
|
||||
if (cmd_obj_sp)
|
||||
{
|
||||
|
@ -366,27 +380,68 @@ CommandInterpreter::LoadCommandDictionary ()
|
|||
m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
|
||||
m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
|
||||
|
||||
const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
|
||||
{"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
|
||||
{"^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
|
||||
{"^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
|
||||
{"^(-.*)$", "breakpoint set %1"},
|
||||
{"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
|
||||
{"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
|
||||
|
||||
size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
|
||||
|
||||
std::auto_ptr<CommandObjectRegexCommand>
|
||||
break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
|
||||
"_regexp-break",
|
||||
"Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
|
||||
"_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
|
||||
|
||||
if (break_regex_cmd_ap.get())
|
||||
{
|
||||
if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'") &&
|
||||
break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < num_regexes; i++)
|
||||
{
|
||||
success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
|
||||
if (!success)
|
||||
break;
|
||||
}
|
||||
success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
|
||||
|
||||
if (success)
|
||||
{
|
||||
CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
|
||||
m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
|
||||
}
|
||||
}
|
||||
|
||||
std::auto_ptr<CommandObjectRegexCommand>
|
||||
tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
|
||||
"_regexp-tbreak",
|
||||
"Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
|
||||
"_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
|
||||
|
||||
if (tbreak_regex_cmd_ap.get())
|
||||
{
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < num_regexes; i++)
|
||||
{
|
||||
// If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
|
||||
char buffer[1024];
|
||||
int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
|
||||
assert (num_printed < 1024);
|
||||
success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
|
||||
if (!success)
|
||||
break;
|
||||
}
|
||||
success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
|
||||
|
||||
if (success)
|
||||
{
|
||||
CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
|
||||
m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
|
||||
}
|
||||
}
|
||||
|
||||
std::auto_ptr<CommandObjectRegexCommand>
|
||||
attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
|
||||
"_regexp-attach",
|
||||
|
|
|
@ -99,13 +99,11 @@ public:
|
|||
m_should_stop (false),
|
||||
m_should_stop_is_valid (false),
|
||||
m_should_perform_action (true),
|
||||
m_address (LLDB_INVALID_ADDRESS)
|
||||
m_address (LLDB_INVALID_ADDRESS),
|
||||
m_break_id(LLDB_INVALID_BREAK_ID),
|
||||
m_was_one_shot (false)
|
||||
{
|
||||
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
|
||||
if (bp_site_sp)
|
||||
{
|
||||
m_address = bp_site_sp->GetLoadAddress();
|
||||
}
|
||||
StoreBPInfo();
|
||||
}
|
||||
|
||||
StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
|
||||
|
@ -114,12 +112,28 @@ public:
|
|||
m_should_stop (should_stop),
|
||||
m_should_stop_is_valid (true),
|
||||
m_should_perform_action (true),
|
||||
m_address (LLDB_INVALID_ADDRESS)
|
||||
m_address (LLDB_INVALID_ADDRESS),
|
||||
m_break_id(LLDB_INVALID_BREAK_ID),
|
||||
m_was_one_shot (false)
|
||||
{
|
||||
StoreBPInfo();
|
||||
}
|
||||
|
||||
void StoreBPInfo ()
|
||||
{
|
||||
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
|
||||
if (bp_site_sp)
|
||||
{
|
||||
m_address = bp_site_sp->GetLoadAddress();
|
||||
if (bp_site_sp->GetNumberOfOwners() == 1)
|
||||
{
|
||||
BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
|
||||
if (bp_loc_sp)
|
||||
{
|
||||
m_break_id = bp_loc_sp->GetBreakpoint().GetID();
|
||||
m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot();
|
||||
}
|
||||
}
|
||||
m_address = bp_site_sp->GetLoadAddress();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,6 +312,12 @@ public:
|
|||
|
||||
if (callback_says_stop)
|
||||
m_should_stop = true;
|
||||
|
||||
// If we are going to stop for this breakpoint, then remove the breakpoint.
|
||||
if (callback_says_stop && bp_loc_sp && bp_loc_sp->GetBreakpoint().IsOneShot())
|
||||
{
|
||||
m_thread.GetProcess()->GetTarget().RemoveBreakpointByID (bp_loc_sp->GetBreakpoint().GetID());
|
||||
}
|
||||
|
||||
// Also make sure that the callback hasn't continued the target.
|
||||
// If it did, when we'll set m_should_start to false and get out of here.
|
||||
|
@ -362,10 +382,18 @@ public:
|
|||
else
|
||||
{
|
||||
StreamString strm;
|
||||
if (m_address == LLDB_INVALID_ADDRESS)
|
||||
if (m_break_id != LLDB_INVALID_BREAK_ID)
|
||||
{
|
||||
if (m_was_one_shot)
|
||||
strm.Printf ("one-shot breakpoint %d", m_break_id);
|
||||
else
|
||||
strm.Printf ("breakpoint %d which has been deleted.", m_break_id);
|
||||
}
|
||||
else if (m_address == LLDB_INVALID_ADDRESS)
|
||||
strm.Printf("breakpoint site %lli which has been deleted - unknown address", m_value);
|
||||
else
|
||||
strm.Printf("breakpoint site %lli which has been deleted - was at 0x%llx", m_value, m_address);
|
||||
|
||||
m_description.swap (strm.GetString());
|
||||
}
|
||||
}
|
||||
|
@ -381,6 +409,8 @@ private:
|
|||
lldb::addr_t m_address; // We use this to capture the breakpoint site address when we create the StopInfo,
|
||||
// in case somebody deletes it between the time the StopInfo is made and the
|
||||
// description is asked for.
|
||||
lldb::break_id_t m_break_id;
|
||||
bool m_was_one_shot;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class AbbreviationsTestCase(TestBase):
|
|||
startstr = "The following is a list of built-in, permanent debugger commands:")
|
||||
|
||||
# Several matching commands: list them and error out.
|
||||
self.runCmd("command unalias t")
|
||||
self.expect("t",
|
||||
COMMAND_FAILED_AS_EXPECTED, error = True,
|
||||
substrs = ["Ambiguous command 't'. Possible matches:",
|
||||
|
|
Loading…
Reference in New Issue