summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBBreakpoint.h6
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h14
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointOptions.h44
-rw-r--r--lldb/scripts/Python/interface/SBBreakpoint.i6
-rw-r--r--lldb/source/API/SBBreakpoint.cpp27
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp12
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp35
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp208
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp71
-rw-r--r--lldb/source/Target/StopInfo.cpp48
-rw-r--r--lldb/test/functionalities/abbreviation/TestAbbreviations.py1
11 files changed, 339 insertions, 133 deletions
diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h
index aa0a2e4df4c..87aada6ac24 100644
--- a/lldb/include/lldb/API/SBBreakpoint.h
+++ b/lldb/include/lldb/API/SBBreakpoint.h
@@ -64,6 +64,12 @@ public:
bool
IsEnabled ();
+ void
+ SetOneShot (bool one_shot);
+
+ bool
+ IsOneShot () const;
+
bool
IsInternal ();
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index 16a6ec8288d..66bea54237a 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -356,6 +356,20 @@ public:
//------------------------------------------------------------------
+ /// 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
/// If this thread hits the breakpoint, we stop, otherwise not.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index 510249ab515..b4ccfac0630 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -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)
+ {
+ 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
- SetEnabled (bool enabled);
+ 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.
diff --git a/lldb/scripts/Python/interface/SBBreakpoint.i b/lldb/scripts/Python/interface/SBBreakpoint.i
index 414936fa52f..cf566d2ac51 100644
--- a/lldb/scripts/Python/interface/SBBreakpoint.i
+++ b/lldb/scripts/Python/interface/SBBreakpoint.i
@@ -119,6 +119,12 @@ public:
bool
IsEnabled ();
+ void
+ SetOneShot (bool one_shot);
+
+ bool
+ IsOneShot ();
+
bool
IsInternal ();
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 8be67046ef4..b0b1e2a042b 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -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 ()
{
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index e90a827fdba..0fbf9a7ff4e 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -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)
{
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 5de137bf153..60679c94a76 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -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)
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 0bc02d8b53f..7c673f7fe67 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -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,59 +144,116 @@ public:
m_condition.assign(option_arg);
break;
+ case 'E':
+ {
+ LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
+
+ switch (language)
+ {
+ case eLanguageTypeC89:
+ case eLanguageTypeC:
+ case eLanguageTypeC99:
+ m_language = eLanguageTypeC;
+ break;
+ case eLanguageTypeC_plus_plus:
+ m_language = eLanguageTypeC_plus_plus;
+ break;
+ case eLanguageTypeObjC:
+ m_language = eLanguageTypeObjC;
+ break;
+ case eLanguageTypeObjC_plus_plus:
+ error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
+ break;
+ case eLanguageTypeUnknown:
+ error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg);
+ }
+ }
+ break;
+
case 'f':
m_filenames.AppendIfUnique (FileSpec(option_arg, false));
break;
- case 'l':
- m_line_num = Args::StringToUInt32 (option_arg, 0);
+ case 'F':
+ m_func_names.push_back (option_arg);
+ m_func_name_type_mask |= eFunctionNameTypeFull;
break;
- case 'b':
- m_func_names.push_back (option_arg);
- m_func_name_type_mask |= eFunctionNameTypeBase;
+ case 'h':
+ {
+ bool success;
+ m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
+ 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 'n':
- m_func_names.push_back (option_arg);
- m_func_name_type_mask |= eFunctionNameTypeAuto;
+ case 'K':
+ {
+ bool success;
+ bool value;
+ value = Args::StringToBoolean (option_arg, true, &success);
+ if (value)
+ m_skip_prologue = eLazyBoolYes;
+ else
+ m_skip_prologue = eLazyBoolNo;
+
+ if (!success)
+ 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 'F':
+ case 'M':
m_func_names.push_back (option_arg);
- m_func_name_type_mask |= eFunctionNameTypeFull;
+ m_func_name_type_mask |= eFunctionNameTypeMethod;
break;
- case 'S':
+ case 'n':
m_func_names.push_back (option_arg);
- m_func_name_type_mask |= eFunctionNameTypeSelector;
+ m_func_name_type_mask |= eFunctionNameTypeAuto;
break;
- case 'M':
- m_func_names.push_back (option_arg);
- m_func_name_type_mask |= eFunctionNameTypeMethod;
+ 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 '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);
+ m_modules.AppendIfUnique (FileSpec (option_arg, false));
+ break;
}
- 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);
@@ -198,48 +261,11 @@ public:
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);
- switch (language)
- {
- case eLanguageTypeC89:
- case eLanguageTypeC:
- case eLanguageTypeC99:
- m_language = eLanguageTypeC;
- break;
- case eLanguageTypeC_plus_plus:
- m_language = eLanguageTypeC_plus_plus;
- break;
- case eLanguageTypeObjC:
- m_language = eLanguageTypeObjC;
- break;
- case eLanguageTypeObjC_plus_plus:
- error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
- break;
- case eLanguageTypeUnknown:
- error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg);
- break;
- default:
- error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg);
- }
- }
- break;
case 'w':
{
bool success;
@@ -248,27 +274,16 @@ public:
error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
}
break;
- case 'h':
- {
- bool success;
- m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
- }
- case 'K':
+
+ case 'x':
{
- bool success;
- bool value;
- value = Args::StringToBoolean (option_arg, true, &success);
- if (value)
- m_skip_prologue = eLazyBoolYes;
- else
- m_skip_prologue = eLazyBoolNo;
-
- if (!success)
- error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg);
+ 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 }
};
//-------------------------------------------------------------------------
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index c387c3d03a1..6db59ac2569 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -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,21 +380,34 @@ 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;
@@ -388,6 +415,34 @@ CommandInterpreter::LoadCommandDictionary ()
}
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",
"Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 26c2cf5e663..c5c9c7051f4 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -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;
};
diff --git a/lldb/test/functionalities/abbreviation/TestAbbreviations.py b/lldb/test/functionalities/abbreviation/TestAbbreviations.py
index 9eeeb80b0aa..e79aa8edc17 100644
--- a/lldb/test/functionalities/abbreviation/TestAbbreviations.py
+++ b/lldb/test/functionalities/abbreviation/TestAbbreviations.py
@@ -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:",
OpenPOWER on IntegriCloud