diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBCommandInterpreter.cpp | 12 | ||||
-rw-r--r-- | lldb/source/API/SBFileSpecList.cpp | 139 | ||||
-rw-r--r-- | lldb/source/API/SBTarget.cpp | 46 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverFileLine.cpp | 20 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp | 139 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverName.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.cpp | 241 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.h | 7 | ||||
-rw-r--r-- | lldb/source/Core/RegularExpression.cpp | 41 | ||||
-rw-r--r-- | lldb/source/Core/SearchFilter.cpp | 175 | ||||
-rw-r--r-- | lldb/source/Core/SourceManager.cpp | 60 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 45 |
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 ®ex +) : + 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)); |