summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
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