summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2011-09-21 01:17:13 +0000
committerJim Ingham <jingham@apple.com>2011-09-21 01:17:13 +0000
commit969795f14bed2c9af7167d0d07b234193c82034c (patch)
tree2e4f23507b807790ac4806cb0957929194947afb /lldb/source
parent699128e58af0015061f2da8477261aef6464dca9 (diff)
downloadbcm5719-llvm-969795f14bed2c9af7167d0d07b234193c82034c.tar.gz
bcm5719-llvm-969795f14bed2c9af7167d0d07b234193c82034c.zip
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.) llvm-svn: 140225
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp12
-rw-r--r--lldb/source/API/SBFileSpecList.cpp139
-rw-r--r--lldb/source/API/SBTarget.cpp46
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileLine.cpp20
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp139
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp241
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.h7
-rw-r--r--lldb/source/Core/RegularExpression.cpp41
-rw-r--r--lldb/source/Core/SearchFilter.cpp175
-rw-r--r--lldb/source/Core/SourceManager.cpp60
-rw-r--r--lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp18
-rw-r--r--lldb/source/Target/Target.cpp45
14 files changed, 789 insertions, 159 deletions
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index 61d0a99f975..8a15423c324 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -136,6 +136,18 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
return num_completions;
}
+int
+SBCommandInterpreter::HandleCompletion (const char *current_line,
+ uint32_t cursor_pos,
+ int match_start_point,
+ int max_return_elements,
+ lldb::SBStringList &matches)
+{
+ const char *cursor = current_line + cursor_pos;
+ const char *last_char = current_line + strlen (current_line);
+ return HandleCompletion (current_line, cursor, last_char, match_start_point, max_return_elements, matches);
+}
+
bool
SBCommandInterpreter::HasCommands ()
{
diff --git a/lldb/source/API/SBFileSpecList.cpp b/lldb/source/API/SBFileSpecList.cpp
new file mode 100644
index 00000000000..3abb4fc135b
--- /dev/null
+++ b/lldb/source/API/SBFileSpecList.cpp
@@ -0,0 +1,139 @@
+//===-- SBFileSpecListList.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <limits.h>
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBFileSpecList.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/FileSpec.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBFileSpecList::SBFileSpecList () :
+ m_opaque_ap(new FileSpecList())
+{
+}
+
+SBFileSpecList::SBFileSpecList (const SBFileSpecList &rhs) :
+ m_opaque_ap()
+{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (rhs.m_opaque_ap.get())
+ m_opaque_ap.reset (new FileSpecList (*(rhs.get())));
+
+ if (log)
+ {
+ log->Printf ("SBFileSpecList::SBFileSpecList (const SBFileSpecList rhs.ap=%p) => SBFileSpecList(%p): %s",
+ rhs.m_opaque_ap.get(), m_opaque_ap.get());
+ }
+}
+
+SBFileSpecList::~SBFileSpecList ()
+{
+}
+
+const SBFileSpecList &
+SBFileSpecList::operator = (const SBFileSpecList &rhs)
+{
+ if (this != &rhs)
+ {
+ m_opaque_ap.reset (new lldb_private::FileSpecList(*(rhs.get())));
+ }
+ return *this;
+}
+
+uint32_t
+SBFileSpecList::GetSize () const
+{
+ return m_opaque_ap->GetSize();
+}
+
+void
+SBFileSpecList::Append (const SBFileSpec &sb_file)
+{
+ m_opaque_ap->Append (sb_file.ref());
+}
+
+bool
+SBFileSpecList::AppendIfUnique (const SBFileSpec &sb_file)
+{
+ return m_opaque_ap->AppendIfUnique (sb_file.ref());
+}
+
+void
+SBFileSpecList::Clear()
+{
+ m_opaque_ap->Clear();
+}
+
+uint32_t
+SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file)
+{
+ return m_opaque_ap->FindFileIndex (idx, sb_file.ref());
+}
+
+const SBFileSpec
+SBFileSpecList::GetFileSpecAtIndex (uint32_t idx) const
+{
+ SBFileSpec new_spec;
+ new_spec.SetFileSpec(m_opaque_ap->GetFileSpecAtIndex(idx));
+ return new_spec;
+}
+
+const lldb_private::FileSpecList *
+SBFileSpecList::operator->() const
+{
+ return m_opaque_ap.get();
+}
+
+const lldb_private::FileSpecList *
+SBFileSpecList::get() const
+{
+ return m_opaque_ap.get();
+}
+
+
+const lldb_private::FileSpecList &
+SBFileSpecList::operator*() const
+{
+ return *m_opaque_ap.get();
+}
+
+const lldb_private::FileSpecList &
+SBFileSpecList::ref() const
+{
+ return *m_opaque_ap.get();
+}
+
+bool
+SBFileSpecList::GetDescription (SBStream &description) const
+{
+ if (m_opaque_ap.get())
+ {
+ uint32_t num_files = m_opaque_ap->GetSize();
+ description.Printf ("%d files: ", num_files);
+ for (uint32_t i = 0; i < num_files; i++)
+ {
+ char path[PATH_MAX];
+ if (m_opaque_ap->GetFileSpecAtIndex(i).GetPath(path, sizeof(path)))
+ description.Printf ("\n %s", path);
+ }
+ }
+ else
+ description.Printf ("No value");
+
+ return true;
+}
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 5f3716c4e1a..4e0dac4e907 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -580,8 +580,9 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
if (module_name && module_name[0])
{
- FileSpec module_file_spec(module_name, false);
- *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
+ FileSpecList module_spec_list;
+ module_spec_list.Append (FileSpec (module_name, false));
+ *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
}
else
{
@@ -611,9 +612,10 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
if (module_name && module_name[0])
{
- FileSpec module_file_spec(module_name, false);
+ FileSpecList module_spec_list;
+ module_spec_list.Append (FileSpec (module_name, false));
- *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false);
+ *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, regexp, false);
}
else
{
@@ -652,6 +654,42 @@ SBTarget::BreakpointCreateByAddress (addr_t address)
return sb_bp;
}
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name)
+{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ SBBreakpoint sb_bp;
+ if (m_opaque_sp.get() && source_regex && source_regex[0])
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
+ RegularExpression regexp(source_regex);
+
+ if (module_name && module_name[0])
+ {
+ FileSpecList module_spec_list;
+ module_spec_list.Append (FileSpec (module_name, false));
+
+ *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, source_file.ref(), regexp, false);
+ }
+ else
+ {
+ *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, source_file.ref(), regexp, false);
+ }
+ }
+
+ if (log)
+ {
+ char path[PATH_MAX];
+ source_file->GetPath (path, sizeof(path));
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
+ m_opaque_sp.get(), source_regex, path, sb_bp.get());
+ }
+
+ return sb_bp;
+}
+
+
SBBreakpoint
SBTarget::FindBreakpointByID (break_id_t bp_id)
{
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
index 13eda3c5d64..224dd158f67 100644
--- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -67,12 +67,22 @@ BreakpointResolverFileLine::SearchCallback
Address line_start = sc.line_entry.range.GetBaseAddress();
if (line_start.IsValid())
{
- BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
- if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ if (filter.AddressPasses(line_start))
{
- StreamString s;
- bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
- log->Printf ("Added location: %s\n", s.GetData());
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+ if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ else if (log)
+ {
+ log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass the filter.\n",
+ line_start.GetFileAddress(),
+ m_file_spec.GetFilename().AsCString("<Unknown>"),
+ m_line_number);
}
}
else
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
new file mode 100644
index 00000000000..238c3709354
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -0,0 +1,139 @@
+//===-- BreakpointResolverFileRegex.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Target.h"
+#include "lldb/lldb-private-log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverFileRegex:
+//----------------------------------------------------------------------
+BreakpointResolverFileRegex::BreakpointResolverFileRegex
+(
+ Breakpoint *bkpt,
+ const FileSpec &file_spec,
+ RegularExpression &regex
+) :
+ BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
+ m_file_spec (file_spec),
+ m_regex (regex)
+{
+}
+
+BreakpointResolverFileRegex::~BreakpointResolverFileRegex ()
+{
+}
+
+Searcher::CallbackReturn
+BreakpointResolverFileRegex::SearchCallback
+(
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing
+)
+{
+
+ assert (m_breakpoint != NULL);
+ if (!context.target_sp)
+ return eCallbackReturnContinue;
+
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ CompileUnit *cu = context.comp_unit;
+ FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
+ if (cu_file_spec == m_file_spec
+ || (!m_file_spec.GetDirectory() && cu_file_spec.GetFilename() == m_file_spec.GetFilename()))
+ {
+ std::vector<uint32_t> line_matches;
+ context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
+ uint32_t num_matches = line_matches.size();
+ for (int i = 0; i < num_matches; i++)
+ {
+ uint32_t start_idx = 0;
+ while (1)
+ {
+ LineEntry line_entry;
+
+ // Cycle through all the line entries that might match this one:
+ start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, &line_entry);
+ if (start_idx == UINT32_MAX)
+ break;
+ start_idx++;
+
+ Address line_start = line_entry.range.GetBaseAddress();
+ if (line_start.IsValid())
+ {
+ if (filter.AddressPasses(line_start))
+ {
+ BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+ if (log && bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ else if (log)
+ {
+ log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n",
+ line_start.GetFileAddress(),
+ m_file_spec.GetFilename().AsCString("<Unknown>"),
+ line_matches[i]);
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
+ line_start.GetFileAddress(),
+ m_file_spec.GetFilename().AsCString("<Unknown>"),
+ line_matches[i]);
+ }
+
+ }
+ }
+ assert (m_breakpoint != NULL);
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+Searcher::Depth
+BreakpointResolverFileRegex::GetDepth()
+{
+ return Searcher::eDepthCompUnit;
+}
+
+void
+BreakpointResolverFileRegex::GetDescription (Stream *s)
+{
+ s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText());
+}
+
+void
+BreakpointResolverFileRegex::Dump (Stream *s) const
+{
+
+}
+
diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
index 60547c6bd78..141a15bef7d 100644
--- a/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -104,7 +104,6 @@ BreakpointResolverName::BreakpointResolverName
m_match_type (Breakpoint::Regexp),
m_skip_prologue (skip_prologue)
{
-
}
BreakpointResolverName::BreakpointResolverName
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 5c96a7f6d92..cc2051d3184 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -56,6 +56,7 @@ CommandObjectBreakpointSet::CommandOptions::CommandOptions(CommandInterpreter &i
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 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{ 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 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{ 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 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx,
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 @@ CommandObjectBreakpointSet::GetOptions ()
}
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 @@ CommandObjectBreakpointSet::Execute
// 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 @@ CommandObjectBreakpointSet::Execute
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 @@ CommandObjectBreakpointSet::Execute
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 @@ CommandObjectBreakpointSet::Execute
bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
}
- if (bp && !use_module)
+ if (bp)
{
Stream &output_stream = result.GetOutputStream();
output_stream.Printf ("Breakpoint created: ");
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h
index d8382a75c0b..9df14dafad4 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.h
+++ b/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -57,7 +57,8 @@ public:
eSetTypeFileAndLine,
eSetTypeAddress,
eSetTypeFunctionName,
- eSetTypeFunctionRegexp
+ eSetTypeFunctionRegexp,
+ eSetTypeSourceRegexp
} BreakpointSetType;
CommandObjectBreakpointSet (CommandInterpreter &interpreter);
@@ -103,6 +104,7 @@ public:
std::string m_func_name;
uint32_t m_func_name_type_mask;
std::string m_func_regexp;
+ std::string m_source_text_regexp;
STLStringArray m_modules;
lldb::addr_t m_load_addr;
uint32_t m_ignore_count;
@@ -114,6 +116,9 @@ public:
};
private:
+ bool
+ ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result);
+
CommandOptions m_options;
};
diff --git a/lldb/source/Core/RegularExpression.cpp b/lldb/source/Core/RegularExpression.cpp
index 6fb94d98bb5..c3953aae068 100644
--- a/lldb/source/Core/RegularExpression.cpp
+++ b/lldb/source/Core/RegularExpression.cpp
@@ -19,6 +19,7 @@ RegularExpression::RegularExpression() :
m_re(),
m_comp_err (1),
m_preg(),
+ m_compile_flags(REG_EXTENDED),
m_matches()
{
memset(&m_preg,0,sizeof(m_preg));
@@ -31,13 +32,43 @@ RegularExpression::RegularExpression() :
RegularExpression::RegularExpression(const char* re, int flags) :
m_re(),
m_comp_err (1),
+ m_compile_flags(flags),
m_preg()
{
memset(&m_preg,0,sizeof(m_preg));
- Compile(re, flags);
+ Compile(re);
}
//----------------------------------------------------------------------
+// Constructor that compiles "re" using "flags" and stores the
+// resulting compiled regular expression into this object.
+//----------------------------------------------------------------------
+RegularExpression::RegularExpression(const char* re) :
+ m_re(),
+ m_comp_err (1),
+ m_compile_flags(REG_EXTENDED),
+ m_preg()
+{
+ memset(&m_preg,0,sizeof(m_preg));
+ Compile(re);
+}
+
+RegularExpression::RegularExpression(const RegularExpression &rhs)
+{
+ memset(&m_preg,0,sizeof(m_preg));
+ Compile(rhs.GetText(), rhs.GetCompileFlags());
+}
+
+const RegularExpression &
+RegularExpression::operator= (const RegularExpression &rhs)
+{
+ if (&rhs != this)
+ {
+ Compile (rhs.GetText(), rhs.GetCompileFlags());
+ }
+ return *this;
+}
+//----------------------------------------------------------------------
// Destructor
//
// Any previosuly compiled regular expression contained in this
@@ -61,9 +92,17 @@ RegularExpression::~RegularExpression()
// otherwise.
//----------------------------------------------------------------------
bool
+RegularExpression::Compile(const char* re)
+{
+ return Compile (re, m_compile_flags);
+}
+
+bool
RegularExpression::Compile(const char* re, int flags)
{
Free();
+ m_compile_flags = flags;
+
if (re && re[0])
{
m_re = re;
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index 8a9140df50d..e0521aa70e2 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -432,3 +432,178 @@ SearchFilterByModule::Dump (Stream *s) const
{
}
+//----------------------------------------------------------------------
+// SearchFilterByModuleList:
+// Selects a shared library matching a given file spec
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// SearchFilterByModuleList constructors
+//----------------------------------------------------------------------
+
+SearchFilterByModuleList::SearchFilterByModuleList (lldb::TargetSP &target_sp, const FileSpecList &module_list) :
+ SearchFilter (target_sp),
+ m_module_spec_list (module_list)
+{
+}
+
+
+//----------------------------------------------------------------------
+// SearchFilterByModuleList copy constructor
+//----------------------------------------------------------------------
+SearchFilterByModuleList::SearchFilterByModuleList(const SearchFilterByModuleList& rhs) :
+ SearchFilter (rhs),
+ m_module_spec_list (rhs.m_module_spec_list)
+{
+}
+
+//----------------------------------------------------------------------
+// SearchFilterByModuleList assignment operator
+//----------------------------------------------------------------------
+const SearchFilterByModuleList&
+SearchFilterByModuleList::operator=(const SearchFilterByModuleList& rhs)
+{
+ m_target_sp = rhs.m_target_sp;
+ m_module_spec_list = rhs.m_module_spec_list;
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SearchFilterByModuleList::~SearchFilterByModuleList()
+{
+}
+
+bool
+SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp)
+{
+ if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec()) != UINT32_MAX)
+ return true;
+ else
+ return false;
+}
+
+bool
+SearchFilterByModuleList::ModulePasses (const FileSpec &spec)
+{
+ if (m_module_spec_list.FindFileIndex(0, spec) != UINT32_MAX)
+ return true;
+ else
+ return false;
+}
+
+bool
+SearchFilterByModuleList::SymbolContextPasses
+(
+ const SymbolContext &context,
+ lldb::SymbolContextItem scope
+ )
+{
+ if (!(scope & eSymbolContextModule))
+ return false;
+
+ if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec()) != UINT32_MAX)
+ return true;
+ else
+ return false;
+}
+
+bool
+SearchFilterByModuleList::AddressPasses (Address &address)
+{
+ // FIXME: Not yet implemented
+ return true;
+}
+
+
+bool
+SearchFilterByModuleList::CompUnitPasses (FileSpec &fileSpec)
+{
+ return true;
+}
+
+bool
+SearchFilterByModuleList::CompUnitPasses (CompileUnit &compUnit)
+{
+ return true;
+}
+
+void
+SearchFilterByModuleList::Search (Searcher &searcher)
+{
+ if (!m_target_sp)
+ return;
+
+ if (searcher.GetDepth() == Searcher::eDepthTarget)
+ {
+ SymbolContext empty_sc;
+ empty_sc.target_sp = m_target_sp;
+ searcher.SearchCallback (*this, empty_sc, NULL, false);
+ }
+
+ // If the module file spec is a full path, then we can just find the one
+ // filespec that passes. Otherwise, we need to go through all modules and
+ // find the ones that match the file name.
+
+ ModuleList matching_modules;
+ const size_t num_modules = m_target_sp->GetImages().GetSize ();
+ for (size_t i = 0; i < num_modules; i++)
+ {
+ Module* module = m_target_sp->GetImages().GetModulePointerAtIndex(i);
+ if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec()) != UINT32_MAX)
+ {
+ SymbolContext matchingContext(m_target_sp, ModuleSP(module));
+ Searcher::CallbackReturn shouldContinue;
+
+ shouldContinue = DoModuleIteration(matchingContext, searcher);
+ if (shouldContinue == Searcher::eCallbackReturnStop)
+ return;
+ }
+ }
+}
+
+void
+SearchFilterByModuleList::GetDescription (Stream *s)
+{
+ uint32_t num_modules = m_module_spec_list.GetSize();
+ if (num_modules == 1)
+ {
+ s->Printf (", module = ", num_modules);
+ if (s->GetVerbose())
+ {
+ char buffer[2048];
+ m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047);
+ s->PutCString(buffer);
+ }
+ else
+ {
+ s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("<unknown>"));
+ }
+ }
+ else
+ {
+ s->Printf (", modules(%d) = ", num_modules);
+ for (uint32_t i = 0; i < num_modules; i++)
+ {
+ if (s->GetVerbose())
+ {
+ char buffer[2048];
+ m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047);
+ s->PutCString(buffer);
+ }
+ else
+ {
+ s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("<unknown>"));
+ }
+ if (i != num_modules - 1)
+ s->PutCString (", ");
+ }
+ }
+}
+
+void
+SearchFilterByModuleList::Dump (Stream *s) const
+{
+
+}
diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp
index 708bf89bd99..6b0670f31b4 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -231,6 +231,19 @@ SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line)
return false;
}
+void
+SourceManager::FindLinesMatchingRegex (FileSpec &file_spec,
+ RegularExpression& regex,
+ uint32_t start_line,
+ uint32_t end_line,
+ std::vector<uint32_t> &match_lines)
+{
+ match_lines.clear();
+ FileSP file_sp = GetFile (file_spec);
+ if (!file_sp)
+ return;
+ return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines);
+}
SourceManager::File::File(const FileSpec &file_spec, Target *target) :
m_file_spec_orig (file_spec),
@@ -368,6 +381,36 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before,
return 0;
}
+void
+SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines)
+{
+ TimeValue curr_mod_time (m_file_spec.GetModificationTime());
+ if (m_mod_time != curr_mod_time)
+ {
+ m_mod_time = curr_mod_time;
+ m_data_sp = m_file_spec.ReadFileContents ();
+ m_offsets.clear();
+ }
+
+ match_lines.clear();
+
+ if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line)))
+ return;
+ if (start_line > end_line)
+ return;
+
+ for (uint32_t line_no = start_line; line_no < end_line; line_no++)
+ {
+ std::string buffer;
+ if (!GetLine (line_no, buffer))
+ break;
+ if (regex.Execute(buffer.c_str()))
+ {
+ match_lines.push_back(line_no);
+ }
+ }
+}
+
bool
SourceManager::File::FileSpecMatches (const FileSpec &file_spec)
{
@@ -457,6 +500,23 @@ SourceManager::File::CalculateLineOffsets (uint32_t line)
return false;
}
+bool
+SourceManager::File::GetLine (uint32_t line_no, std::string &buffer)
+{
+ if (!LineIsValid(line_no))
+ return false;
+
+ uint32_t start_offset = GetLineOffset (line_no);
+ uint32_t end_offset = GetLineOffset (line_no + 1);
+ if (end_offset == UINT32_MAX)
+ {
+ end_offset = m_data_sp->GetByteSize();
+ }
+ buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset);
+
+ return true;
+}
+
void
SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp)
{
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index 6628f92a10f..55e0af68cb8 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -985,7 +985,9 @@ DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
const bool internal_bp = false;
const LazyBool skip_prologue = eLazyBoolNo;
- Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(),
+ FileSpecList module_spec_list;
+ module_spec_list.Append (m_kernel.module_sp->GetFileSpec());
+ Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
"OSKextLoadedKextSummariesUpdated",
eFunctionNameTypeFull,
internal_bp,
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 5148751755d..14517e605ee 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -124,7 +124,7 @@ SymbolFileSymtab::GetNumCompileUnits()
// If we don't have any source file symbols we will just have one compile unit for
// the entire object file
if (m_source_indexes.empty())
- return 1;
+ return 0;
// If we have any source file symbols we will logically orgnize the object symbols
// using these.
@@ -138,14 +138,14 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
// If we don't have any source file symbols we will just have one compile unit for
// the entire object file
- if (m_source_indexes.empty())
- {
- const FileSpec &obj_file_spec = m_obj_file->GetFileSpec();
- if (obj_file_spec)
- cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown));
-
- }
- else if (idx < m_source_indexes.size())
+// if (m_source_indexes.empty())
+// {
+// const FileSpec &obj_file_spec = m_obj_file->GetFileSpec();
+// if (obj_file_spec)
+// cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown));
+//
+// }
+ /* else */ if (idx < m_source_indexes.size())
{
const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
if (cu_symbol)
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 154946206d9..5fdc2333eb8 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -16,6 +16,7 @@
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Event.h"
@@ -206,9 +207,21 @@ Target::GetBreakpointByID (break_id_t break_id)
}
BreakpointSP
-Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal)
+Target::CreateBreakpoint (const FileSpecList *containingModules,
+ const FileSpec &file,
+ RegularExpression &source_regex,
+ bool internal)
{
- SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+ SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, file, source_regex));
+ return CreateBreakpoint (filter_sp, resolver_sp, internal);
+}
+
+
+BreakpointSP
+Target::CreateBreakpoint (const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal)
+{
+ SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL, file, line_no, check_inlines));
return CreateBreakpoint (filter_sp, resolver_sp, internal);
}
@@ -242,7 +255,7 @@ Target::CreateBreakpoint (Address &addr, bool internal)
}
BreakpointSP
-Target::CreateBreakpoint (const FileSpec *containingModule,
+Target::CreateBreakpoint (const FileSpecList *containingModules,
const char *func_name,
uint32_t func_name_type_mask,
bool internal,
@@ -251,7 +264,7 @@ Target::CreateBreakpoint (const FileSpec *containingModule,
BreakpointSP bp_sp;
if (func_name)
{
- SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+ SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL,
func_name,
@@ -284,13 +297,33 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule)
return filter_sp;
}
+SearchFilterSP
+Target::GetSearchFilterForModuleList (const FileSpecList *containingModules)
+{
+ SearchFilterSP filter_sp;
+ lldb::TargetSP target_sp = this->GetSP();
+ if (containingModules && containingModules->GetSize() != 0)
+ {
+ // TODO: We should look into sharing module based search filters
+ // across many breakpoints like we do for the simple target based one
+ filter_sp.reset (new SearchFilterByModuleList (target_sp, *containingModules));
+ }
+ else
+ {
+ if (m_search_filter_sp.get() == NULL)
+ m_search_filter_sp.reset (new SearchFilter (target_sp));
+ filter_sp = m_search_filter_sp;
+ }
+ return filter_sp;
+}
+
BreakpointSP
-Target::CreateBreakpoint (const FileSpec *containingModule,
+Target::CreateBreakpoint (const FileSpecList *containingModules,
RegularExpression &func_regex,
bool internal,
LazyBool skip_prologue)
{
- SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
+ SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL,
func_regex,
skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));
OpenPOWER on IntegriCloud