Add a new breakpoint type "break by source regular expression".
Fix the RegularExpression class so it has a real copy constructor.
Fix the breakpoint setting with multiple shared libraries so it makes
one breakpoint not one per shared library.
Add SBFileSpecList, to be used to expose the above to the SB interface (not done yet.)
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@140225 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index 5c96a7f..cc2051d 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -56,6 +56,7 @@
m_func_name (),
m_func_name_type_mask (0),
m_func_regexp (),
+ m_source_text_regexp(),
m_modules (),
m_load_addr(),
m_ignore_count (0),
@@ -91,7 +92,7 @@
{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName,
"The breakpoint stops only for threads in the queue whose name is given by this argument."},
- { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_9, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Set the breakpoint by source location in this particular file."},
{ LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
@@ -124,6 +125,10 @@
{ LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
"Set the breakpoint by function basename (C++ namespaces and arguments will be ignored)." },
+ { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', required_argument, NULL, 0, eArgTypeRegularExpression,
+ "Set the breakpoint specifying a regular expression to match a pattern in the source text in a given source file." },
+
+
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -187,6 +192,10 @@
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;
@@ -275,6 +284,52 @@
}
bool
+CommandObjectBreakpointSet::ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result)
+{
+ if (m_options.m_filename.empty())
+ {
+ uint32_t default_line;
+ // First use the Source Manager's default file.
+ // Then use the current stack frame's file.
+ if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
+ {
+ StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame;
+ if (cur_frame == NULL)
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else if (!cur_frame->HasDebugInformation())
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
+ if (sc.line_entry.file)
+ {
+ file = sc.line_entry.file;
+ }
+ else
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ file.SetFile(m_options.m_filename.c_str(), false);
+ }
+ return true;
+}
+
+bool
CommandObjectBreakpointSet::Execute
(
Args& command,
@@ -294,6 +349,7 @@
// 2). -a [-s -g] (setting breakpoint by address)
// 3). -n [-s -g] (setting breakpoint by function name)
// 4). -r [-s -g] (setting breakpoint by function name regular expression)
+ // 5). -p -f (setting a breakpoint by comparing a reg-exp to source text)
BreakpointSetType break_type = eSetTypeInvalid;
@@ -305,94 +361,42 @@
break_type = eSetTypeFunctionName;
else if (!m_options.m_func_regexp.empty())
break_type = eSetTypeFunctionRegexp;
+ else if (!m_options.m_source_text_regexp.empty())
+ break_type = eSetTypeSourceRegexp;
Breakpoint *bp = NULL;
FileSpec module_spec;
bool use_module = false;
int num_modules = m_options.m_modules.size();
+ FileSpecList module_spec_list;
+ FileSpecList *module_spec_list_ptr = NULL;
+
if ((num_modules > 0) && (break_type != eSetTypeAddress))
use_module = true;
+
+ if (use_module)
+ {
+ module_spec_list_ptr = &module_spec_list;
+ for (int i = 0; i < num_modules; ++i)
+ {
+ module_spec.SetFile(m_options.m_modules[i].c_str(), false);
+ module_spec_list.AppendIfUnique (module_spec);
+ }
+ }
switch (break_type)
{
case eSetTypeFileAndLine: // Breakpoint by source position
{
FileSpec file;
- if (m_options.m_filename.empty())
- {
- uint32_t default_line;
- // First use the Source Manager's default file.
- // Then use the current stack frame's file.
- if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
- {
- StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame;
- if (cur_frame == NULL)
- {
- result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
- result.SetStatus (eReturnStatusFailed);
- break;
- }
- else if (!cur_frame->HasDebugInformation())
- {
- result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
- result.SetStatus (eReturnStatusFailed);
- break;
- }
- else
- {
- const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
- if (sc.line_entry.file)
- {
- file = sc.line_entry.file;
- }
- else
- {
- result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
- result.SetStatus (eReturnStatusFailed);
- break;
- }
- }
- }
- }
- else
- {
- file.SetFile(m_options.m_filename.c_str(), false);
- }
-
- if (use_module)
- {
- for (int i = 0; i < num_modules; ++i)
- {
- module_spec.SetFile(m_options.m_modules[i].c_str(), false);
- bp = target->CreateBreakpoint (&module_spec,
- file,
- m_options.m_line_num,
- m_options.m_check_inlines).get();
- if (bp)
- {
- Stream &output_stream = result.GetOutputStream();
- result.AppendMessage ("Breakpoint created: ");
- bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
- output_stream.EOL();
- if (bp->GetNumLocations() == 0)
- output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual"
- " locations.\n");
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
- {
- result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
- m_options.m_modules[i].c_str());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- }
- else
- bp = target->CreateBreakpoint (NULL,
- file,
- m_options.m_line_num,
- m_options.m_check_inlines).get();
+ if (!ChooseFile (target, file, result))
+ break;
+
+ bp = target->CreateBreakpoint (module_spec_list_ptr,
+ file,
+ m_options.m_line_num,
+ m_options.m_check_inlines).get();
}
break;
@@ -407,72 +411,47 @@
if (name_type_mask == 0)
name_type_mask = eFunctionNameTypeAuto;
- if (use_module)
- {
- for (int i = 0; i < num_modules; ++i)
- {
- module_spec.SetFile(m_options.m_modules[i].c_str(), false);
- bp = target->CreateBreakpoint (&module_spec,
- m_options.m_func_name.c_str(),
- name_type_mask,
- Breakpoint::Exact).get();
- if (bp)
- {
- Stream &output_stream = result.GetOutputStream();
- output_stream.Printf ("Breakpoint created: ");
- bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
- output_stream.EOL();
- if (bp->GetNumLocations() == 0)
- output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual"
- " locations.\n");
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
- {
- result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
- m_options.m_modules[i].c_str());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- }
- else
- bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get();
+ bp = target->CreateBreakpoint (module_spec_list_ptr,
+ m_options.m_func_name.c_str(),
+ name_type_mask,
+ Breakpoint::Exact).get();
}
break;
case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
{
RegularExpression regexp(m_options.m_func_regexp.c_str());
- if (use_module)
+ if (!regexp.IsValid())
{
- for (int i = 0; i < num_modules; ++i)
- {
- module_spec.SetFile(m_options.m_modules[i].c_str(), false);
- bp = target->CreateBreakpoint (&module_spec, regexp).get();
- if (bp)
- {
- Stream &output_stream = result.GetOutputStream();
- output_stream.Printf ("Breakpoint created: ");
- bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
- output_stream.EOL();
- if (bp->GetNumLocations() == 0)
- output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual"
- " locations.\n");
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
- {
- result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
- m_options.m_modules[i].c_str());
- result.SetStatus (eReturnStatusFailed);
- }
- }
+ char err_str[1024];
+ regexp.GetErrorAsCString(err_str, sizeof(err_str));
+ result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"",
+ err_str);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
- else
- bp = target->CreateBreakpoint (NULL, regexp).get();
+ bp = target->CreateBreakpoint (module_spec_list_ptr, regexp).get();
}
break;
+ case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
+ {
+ FileSpec file;
+ if (!ChooseFile (target, file, result))
+ break;
+ RegularExpression regexp(m_options.m_source_text_regexp.c_str());
+ if (!regexp.IsValid())
+ {
+ char err_str[1024];
+ regexp.GetErrorAsCString(err_str, sizeof(err_str));
+ result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"",
+ err_str);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ bp = target->CreateBreakpoint (module_spec_list_ptr, file, regexp).get();
+ }
+ break;
default:
break;
}
@@ -496,7 +475,7 @@
bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
}
- if (bp && !use_module)
+ if (bp)
{
Stream &output_stream = result.GetOutputStream();
output_stream.Printf ("Breakpoint created: ");