Added the ability to restrict breakpoints by function name, function regexp, selector

etc to specific source files.
Added SB API's to specify these source files & also more than one module.
Added an "exact" option to CompileUnit's FindLineEntry API.

llvm-svn: 140362
This commit is contained in:
Jim Ingham 2011-09-23 00:54:11 +00:00
parent b9a11322b1
commit 87df91b866
34 changed files with 691 additions and 170 deletions

View File

@ -47,6 +47,12 @@ public:
uint32_t line,
lldb::SBFileSpec *inline_file_spec) const;
uint32_t
FindLineEntryIndex (uint32_t start_idx,
uint32_t line,
lldb::SBFileSpec *inline_file_spec,
bool exact) const;
#ifndef SWIG
bool

View File

@ -44,13 +44,15 @@ public:
Clear();
uint32_t
FindFileIndex (uint32_t idx, const SBFileSpec &sb_file);
FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full);
const SBFileSpec
GetFileSpecAtIndex (uint32_t idx) const;
private:
friend class SBTarget;
#ifndef SWIG
const lldb_private::FileSpecList *

View File

@ -14,6 +14,7 @@
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFileSpecList.h"
#include "lldb/API/SBType.h"
namespace lldb {
@ -314,11 +315,28 @@ public:
lldb::SBBreakpoint
BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL);
lldb::SBBreakpoint
BreakpointCreateByName (const char *symbol_name,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list);
lldb::SBBreakpoint
BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL);
lldb::SBBreakpoint
BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name = NULL);
BreakpointCreateByRegex (const char *symbol_name_regex,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list);
lldb::SBBreakpoint
BreakpointCreateBySourceRegex (const char *source_regex,
const lldb::SBFileSpec &source_file,
const char *module_name = NULL);
lldb::SBBreakpoint
BreakpointCreateBySourceRegex (const char *source_regex,
const SBFileSpecList &module_list,
const lldb::SBFileSpecList &source_file);
lldb::SBBreakpoint
BreakpointCreateByAddress (addr_t address);

View File

@ -29,7 +29,6 @@ class BreakpointResolverFileRegex :
{
public:
BreakpointResolverFileRegex (Breakpoint *bkpt,
const FileSpec &resolver,
RegularExpression &regex);
virtual
@ -58,8 +57,7 @@ public:
protected:
friend class Breakpoint;
FileSpec m_file_spec; // This is the file spec we are looking for.
RegularExpression m_regex; // This is the line number that we are looking for.
RegularExpression m_regex; // This is the line expression that we are looking for.
private:
DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex);

View File

@ -116,12 +116,15 @@ public:
/// @param[in] file
/// The file specification to search for.
///
/// @param[in] full
/// Should FileSpec::Equal be called with "full" true or false.
///
/// @return
/// The index of the file that matches \a file if it is found,
/// else UINT32_MAX is returned.
//------------------------------------------------------------------
uint32_t
FindFileIndex (uint32_t idx, const FileSpec &file) const;
FindFileIndex (uint32_t idx, const FileSpec &file, bool full) const;
//------------------------------------------------------------------
/// Get file at index.

View File

@ -216,6 +216,21 @@ public:
virtual void
SearchInModuleList (Searcher &searcher, ModuleList &modules);
//------------------------------------------------------------------
/// This determines which items are REQUIRED for the filter to pass.
/// For instance, if you are filtering by Compilation Unit, obviously
/// symbols that have no compilation unit can't pass So return eSymbolContextCU
/// and search callbacks can then short cut the search to avoid looking at
/// things that obviously won't pass.
///
/// @return
/// The required elements for the search, which is an or'ed together
/// set of lldb:SearchContextItem enum's.
///
//------------------------------------------------------------------
virtual uint32_t
GetFilterRequiredItems ();
//------------------------------------------------------------------
/// Prints a canonical description for the search filter to the stream \a s.
///
@ -311,6 +326,9 @@ public:
virtual void
GetDescription(Stream *s);
virtual uint32_t
GetFilterRequiredItems ();
virtual void
Dump (Stream *s) const;
@ -369,6 +387,65 @@ public:
virtual void
GetDescription(Stream *s);
virtual uint32_t
GetFilterRequiredItems ();
virtual void
Dump (Stream *s) const;
virtual void
Search (Searcher &searcher);
private:
FileSpecList m_module_spec_list;
};
class SearchFilterByModuleListAndCU :
public SearchFilterByModuleList
{
public:
//------------------------------------------------------------------
/// The basic constructor takes a Target, which gives the space to search,
/// and the module list to restrict the search to.
///
/// @param[in] target
/// The Target that provides the module list to search.
///
/// @param[in] module
/// The Module that limits the search.
//------------------------------------------------------------------
SearchFilterByModuleListAndCU (lldb::TargetSP &targetSP,
const FileSpecList &module_list,
const FileSpecList &cu_list);
SearchFilterByModuleListAndCU (const SearchFilterByModuleListAndCU& rhs);
virtual
~SearchFilterByModuleListAndCU ();
const SearchFilterByModuleListAndCU&
operator=(const SearchFilterByModuleListAndCU& rhs);
virtual bool
SymbolContextPasses (const SymbolContext &context,
lldb::SymbolContextItem scope);
virtual bool
AddressPasses (Address &address);
virtual bool
CompUnitPasses (FileSpec &fileSpec);
virtual bool
CompUnitPasses (CompileUnit &compUnit);
virtual void
GetDescription(Stream *s);
virtual uint32_t
GetFilterRequiredItems ();
virtual void
Dump (Stream *s) const;
@ -377,6 +454,7 @@ public:
private:
FileSpecList m_module_spec_list;
FileSpecList m_cu_spec_list;
};
} // namespace lldb_private

View File

@ -202,6 +202,10 @@ public:
/// else if NULL, search for line entries that match the compile
/// unit file.
///
/// @param[in] exact
/// If \btrue match only if there is a line table entry for this line number.
/// If \bfalse, find the line table entry equal to or after this line number.
///
/// @param[out] line_entry
/// If non-NULL, a copy of the line entry that was found.
///
@ -213,6 +217,7 @@ public:
FindLineEntry (uint32_t start_idx,
uint32_t line,
const FileSpec* file_spec_ptr,
bool exact,
LineEntry *line_entry);
//------------------------------------------------------------------

View File

@ -250,10 +250,10 @@ public:
bool check_inlines,
bool internal = false);
// Use this to create breakpoint that matches regex against the source lines in file:
// Use this to create breakpoint that matches regex against the source lines in files given in source_file_list:
lldb::BreakpointSP
CreateBreakpoint (const FileSpecList *containingModules,
const FileSpec &file,
CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *source_file_list,
RegularExpression &source_regex,
bool internal = false);
@ -267,11 +267,12 @@ public:
CreateBreakpoint (Address &addr,
bool internal = false);
// Use this to create a function breakpoint by regexp in containingModule, or all modules if it is NULL
// Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL
// When "skip_prologue is set to eLazyBoolCalculate, we use the current target
// setting, else we use the values passed in
lldb::BreakpointSP
CreateBreakpoint (const FileSpecList *containingModules,
CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regexp,
bool internal = false,
LazyBool skip_prologue = eLazyBoolCalculate);
@ -281,6 +282,7 @@ public:
// setting, else we use the values passed in
lldb::BreakpointSP
CreateBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const char *func_name,
uint32_t func_name_type_mask,
bool internal = false,
@ -889,6 +891,10 @@ protected:
lldb::SearchFilterSP
GetSearchFilterForModuleList (const FileSpecList *containingModuleList);
lldb::SearchFilterSP
GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);
static void
ImageSearchPathsChanged (const PathMappingList &path_list,

View File

@ -71,6 +71,12 @@ public:
uint32_t line,
lldb::SBFileSpec *inline_file_spec) const;
uint32_t
FindLineEntryIndex (uint32_t start_idx,
uint32_t line,
lldb::SBFileSpec *inline_file_spec,
bool exact) const;
bool
GetDescription (lldb::SBStream &description);
};

View File

@ -34,7 +34,7 @@ public:
Clear();
uint32_t
FindFileIndex (uint32_t idx, const SBFileSpec &sb_file);
FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full);
const SBFileSpec
GetFileSpecAtIndex (uint32_t idx) const;

View File

@ -98,6 +98,13 @@ SBCompileUnit::GetLineEntryAtIndex (uint32_t idx) const
uint32_t
SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec *inline_file_spec) const
{
const bool exact = true;
return FindLineEntryIndex (start_idx, line, inline_file_spec, exact);
}
uint32_t
SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec *inline_file_spec, bool exact) const
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@ -114,6 +121,7 @@ SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec
index = m_opaque_ptr->FindLineEntry (start_idx,
line,
inline_file_spec ? inline_file_spec->get() : NULL,
exact,
NULL);
}

View File

@ -80,9 +80,9 @@ SBFileSpecList::Clear()
}
uint32_t
SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file)
SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full)
{
return m_opaque_ap->FindFileIndex (idx, sb_file.ref());
return m_opaque_ap->FindFileIndex (idx, sb_file.ref(), full);
}
const SBFileSpec

View File

@ -575,18 +575,18 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
if (m_opaque_sp.get() && symbol_name && symbol_name[0])
if (m_opaque_sp.get())
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
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, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
*sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
}
else
{
*sb_bp = m_opaque_sp->CreateBreakpoint (NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
*sb_bp = m_opaque_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
}
}
@ -599,6 +599,34 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
return sb_bp;
}
lldb::SBBreakpoint
SBTarget::BreakpointCreateByName (const char *symbol_name,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
if (m_opaque_sp.get() && symbol_name && symbol_name[0])
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
*sb_bp = m_opaque_sp->CreateBreakpoint (module_list.get(),
comp_unit_list.get(),
symbol_name,
eFunctionNameTypeFull | eFunctionNameTypeBase,
false);
}
if (log)
{
log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\") => SBBreakpoint(%p)",
m_opaque_sp.get(), symbol_name, sb_bp.get());
}
return sb_bp;
}
SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name)
{
@ -615,11 +643,11 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
FileSpecList module_spec_list;
module_spec_list.Append (FileSpec (module_name, false));
*sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, regexp, false);
*sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, false);
}
else
{
*sb_bp = m_opaque_sp->CreateBreakpoint (NULL, regexp, false);
*sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, false);
}
}
@ -632,7 +660,30 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo
return sb_bp;
}
lldb::SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
if (m_opaque_sp.get() && symbol_name_regex && symbol_name_regex[0])
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
RegularExpression regexp(symbol_name_regex);
*sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, false);
}
if (log)
{
log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
m_opaque_sp.get(), symbol_name_regex, sb_bp.get());
}
return sb_bp;
}
SBBreakpoint
SBTarget::BreakpointCreateByAddress (addr_t address)
@ -664,17 +715,19 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
RegularExpression regexp(source_regex);
FileSpecList source_file_spec_list;
source_file_spec_list.Append (source_file.ref());
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);
*sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false);
}
else
{
*sb_bp = m_opaque_sp->CreateBreakpoint (NULL, source_file.ref(), regexp, false);
*sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false);
}
}
@ -689,6 +742,29 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S
return sb_bp;
}
lldb::SBBreakpoint
SBTarget::BreakpointCreateBySourceRegex (const char *source_regex,
const SBFileSpecList &module_list,
const lldb::SBFileSpecList &source_file_list)
{
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);
*sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false);
}
if (log)
{
log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\") => SBBreakpoint(%p)",
m_opaque_sp.get(), source_regex, sb_bp.get());
}
return sb_bp;
}
SBBreakpoint
SBTarget::FindBreakpointByID (break_id_t bp_id)

View File

@ -29,11 +29,9 @@ using namespace lldb_private;
BreakpointResolverFileRegex::BreakpointResolverFileRegex
(
Breakpoint *bkpt,
const FileSpec &file_spec,
RegularExpression &regex
) :
BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
m_file_spec (file_spec),
m_regex (regex)
{
}
@ -60,62 +58,58 @@ BreakpointResolverFileRegex::SearchCallback
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++)
{
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;
bool exact = false;
while (1)
{
uint32_t start_idx = 0;
while (1)
{
LineEntry line_entry;
LineEntry line_entry;
// Cycle through all the line entries that might match this one:
start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry);
if (start_idx == UINT32_MAX)
break;
exact = true;
start_idx++;
// 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())
Address line_start = line_entry.range.GetBaseAddress();
if (line_start.IsValid())
{
if (filter.AddressPasses(line_start))
{
if (filter.AddressPasses(line_start))
BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
if (log && bp_loc_sp && !m_breakpoint->IsInternal())
{
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]);
StreamString s;
bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
log->Printf ("Added location: %s\n", s.GetData());
}
}
else
else if (log)
{
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]);
log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n",
line_start.GetFileAddress(),
cu_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(),
cu_file_spec.GetFilename().AsCString("<Unknown>"),
line_matches[i]);
}
}
assert (m_breakpoint != NULL);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
}
assert (m_breakpoint != NULL);
return Searcher::eCallbackReturnContinue;
}
@ -128,7 +122,7 @@ BreakpointResolverFileRegex::GetDepth()
void
BreakpointResolverFileRegex::GetDescription (Stream *s)
{
s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText());
s->Printf ("source regex = \"%s\"", m_regex.GetText());
}
void

View File

@ -161,16 +161,22 @@ BreakpointResolverName::SearchCallback
const bool include_symbols = false;
const bool append = false;
bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
switch (m_match_type)
{
case Breakpoint::Exact:
if (context.module_sp)
{
if (context.module_sp->FindFunctions (m_func_name,
uint32_t num_functions = context.module_sp->FindFunctions (m_func_name,
m_func_name_type_mask,
include_symbols,
append,
func_list) == 0)
func_list);
// If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
// symbols, since all the ones from a set compilation unit will have been found above already.
if (num_functions == 0 && !filter_by_cu)
{
if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
@ -180,7 +186,8 @@ BreakpointResolverName::SearchCallback
case Breakpoint::Regexp:
if (context.module_sp)
{
context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
if (!filter_by_cu)
context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
context.module_sp->FindFunctions (m_regex,
include_symbols,
append,
@ -192,7 +199,26 @@ BreakpointResolverName::SearchCallback
log->Warning ("glob is not supported yet.");
break;
}
// If the filter specifies a Compilation Unit, remove the ones that don't pass at this point.
if (filter_by_cu)
{
uint32_t num_functions = func_list.GetSize();
for (size_t idx = 0; idx < num_functions; idx++)
{
SymbolContext sc;
func_list.GetContextAtIndex(idx, sc);
if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
{
func_list.RemoveContextAtIndex(idx);
num_functions--;
idx--;
}
}
}
if (!m_basename_filter.empty())
{
// Filter out any matches whose names don't contain the basename filter

View File

@ -49,7 +49,7 @@ AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel leve
CommandObjectBreakpointSet::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
Options (interpreter),
m_filename (),
m_filenames (),
m_line_num (0),
m_column (0),
m_check_inlines (true),
@ -71,6 +71,8 @@ CommandObjectBreakpointSet::CommandOptions::~CommandOptions ()
{
}
#define LLDB_OPT_FILE (LLDB_OPT_SET_ALL & ~(LLDB_OPT_SET_2))
OptionDefinition
CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
{
@ -92,11 +94,11 @@ 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 | 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_FILE, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
"Specifies the source file in which to set this breakpoint."},
{ LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
"Set the breakpoint by source location at this particular line."},
"Specifies the line number on which to set this breakpoint."},
// Comment out this option for the moment, as we don't actually use it, but will in the future.
// This way users won't see it, but the infrastructure is left in place.
@ -160,7 +162,7 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx,
break;
case 'f':
m_filename.assign (option_arg);
m_filenames.AppendIfUnique (FileSpec(option_arg, false));
break;
case 'l':
@ -202,7 +204,7 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx,
case 's':
{
m_modules.push_back (std::string (option_arg));
m_modules.AppendIfUnique (FileSpec (option_arg, false));
break;
}
case 'i':
@ -244,14 +246,14 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx,
void
CommandObjectBreakpointSet::CommandOptions::OptionParsingStarting ()
{
m_filename.clear();
m_filenames.Clear();
m_line_num = 0;
m_column = 0;
m_func_name.clear();
m_func_name_type_mask = 0;
m_func_regexp.clear();
m_load_addr = LLDB_INVALID_ADDRESS;
m_modules.clear();
m_modules.Clear();
m_ignore_count = 0;
m_thread_id = LLDB_INVALID_THREAD_ID;
m_thread_index = UINT32_MAX;
@ -284,48 +286,41 @@ CommandObjectBreakpointSet::GetOptions ()
}
bool
CommandObjectBreakpointSet::ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result)
CommandObjectBreakpointSet::GetDefaultFile (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))
{
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().GetFramePtr();
if (cur_frame == NULL)
{
StackFrame *cur_frame = m_interpreter.GetExecutionContext().GetFramePtr();
if (cur_frame == NULL)
result.AppendError ("No selected frame to use to find the default file.");
result.SetStatus (eReturnStatusFailed);
return false;
}
else if (!cur_frame->HasDebugInformation())
{
result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info.");
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
if (sc.line_entry.file)
{
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;
file = sc.line_entry.file;
}
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;
}
result.AppendError ("Can't find the file for the selected frame to use as the default file.");
result.SetStatus (eReturnStatusFailed);
return false;
}
}
}
else
{
file.SetFile(m_options.m_filename.c_str(), false);
}
return true;
}
@ -367,33 +362,36 @@ CommandObjectBreakpointSet::Execute
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;
int num_modules = m_options.m_modules.GetSize();
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 (!ChooseFile (target, file, result))
break;
uint32_t num_files = m_options.m_filenames.GetSize();
if (num_files == 0)
{
if (!GetDefaultFile (target, file, result))
{
result.AppendError("No file supplied and no default file available.");
result.SetStatus (eReturnStatusFailed);
return false;
}
}
else if (num_files > 1)
{
result.AppendError("Only one file at a time is allowed for file and line breakpoints.");
result.SetStatus (eReturnStatusFailed);
return false;
}
else
file = m_options.m_filenames.GetFileSpecAtIndex(0);
bp = target->CreateBreakpoint (module_spec_list_ptr,
bp = target->CreateBreakpoint (&(m_options.m_modules),
file,
m_options.m_line_num,
m_options.m_check_inlines).get();
@ -410,8 +408,9 @@ CommandObjectBreakpointSet::Execute
if (name_type_mask == 0)
name_type_mask = eFunctionNameTypeAuto;
bp = target->CreateBreakpoint (module_spec_list_ptr,
bp = target->CreateBreakpoint (&(m_options.m_modules),
&(m_options.m_filenames),
m_options.m_func_name.c_str(),
name_type_mask,
Breakpoint::Exact).get();
@ -430,15 +429,29 @@ CommandObjectBreakpointSet::Execute
result.SetStatus (eReturnStatusFailed);
return false;
}
bp = target->CreateBreakpoint (module_spec_list_ptr, regexp).get();
bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get();
}
break;
case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
{
FileSpec file;
if (!ChooseFile (target, file, result))
break;
int num_files = m_options.m_filenames.GetSize();
if (num_files == 0)
{
FileSpec file;
if (!GetDefaultFile (target, file, result))
{
result.AppendError ("No files provided and could not find default file.");
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
m_options.m_filenames.Append (file);
}
}
RegularExpression regexp(m_options.m_source_text_regexp.c_str());
if (!regexp.IsValid())
{
@ -449,7 +462,7 @@ CommandObjectBreakpointSet::Execute
result.SetStatus (eReturnStatusFailed);
return false;
}
bp = target->CreateBreakpoint (module_spec_list_ptr, file, regexp).get();
bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get();
}
break;
default:

View File

@ -97,7 +97,7 @@ public:
// Instance variables to hold the values for command options.
std::string m_filename;
FileSpecList m_filenames;
uint32_t m_line_num;
uint32_t m_column;
bool m_check_inlines;
@ -105,7 +105,7 @@ public:
uint32_t m_func_name_type_mask;
std::string m_func_regexp;
std::string m_source_text_regexp;
STLStringArray m_modules;
FileSpecList m_modules;
lldb::addr_t m_load_addr;
uint32_t m_ignore_count;
lldb::tid_t m_thread_id;
@ -117,7 +117,7 @@ public:
private:
bool
ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result);
GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result);
CommandOptions m_options;
};

View File

@ -999,7 +999,8 @@ public:
while (index_ptr <= end_ptr)
{
LineEntry line_entry;
index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
const bool exact = false;
index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
if (index_ptr == UINT32_MAX)
break;

View File

@ -52,7 +52,7 @@ FileLineResolver::SearchCallback
if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, m_file_spec.GetDirectory()))
{
uint32_t start_file_idx = 0;
uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec);
uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false);
if (file_idx != UINT32_MAX)
{
LineTable *line_table = cu->GetLineTable();
@ -67,7 +67,7 @@ FileLineResolver::SearchCallback
line_table->FineLineEntriesForFileIndex (file_idx, append, m_sc_list);
// Get the next file index in case we have multiple file
// entries for the same file
file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec);
file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec, false);
}
}
else

View File

@ -107,7 +107,7 @@ FileSpecList::Dump(Stream *s, const char *separator_cstr) const
// it is found, else UINT32_MAX is returned.
//------------------------------------------------------------------
uint32_t
FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec) const
FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec, bool full) const
{
const uint32_t num_files = m_files.size();
uint32_t idx;
@ -125,7 +125,7 @@ FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec) cons
}
else
{
if (m_files[idx] == file_spec)
if (FileSpec::Equal (m_files[idx], file_spec, full))
return idx;
}
}

View File

@ -110,6 +110,12 @@ SearchFilter::CompUnitPasses (CompileUnit &compUnit)
return true;
}
uint32_t
SearchFilter::GetFilterRequiredItems()
{
return (lldb::SymbolContextItem) 0;
}
void
SearchFilter::GetDescription (Stream *s)
{
@ -427,6 +433,12 @@ SearchFilterByModule::GetDescription (Stream *s)
}
}
uint32_t
SearchFilterByModule::GetFilterRequiredItems()
{
return eSymbolContextModule;
}
void
SearchFilterByModule::Dump (Stream *s) const
{
@ -478,7 +490,10 @@ SearchFilterByModuleList::~SearchFilterByModuleList()
bool
SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp)
{
if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec()) != UINT32_MAX)
if (m_module_spec_list.GetSize() == 0)
return true;
if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX)
return true;
else
return false;
@ -487,7 +502,10 @@ SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp)
bool
SearchFilterByModuleList::ModulePasses (const FileSpec &spec)
{
if (m_module_spec_list.FindFileIndex(0, spec) != UINT32_MAX)
if (m_module_spec_list.GetSize() == 0)
return true;
if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX)
return true;
else
return false;
@ -503,7 +521,7 @@ SearchFilterByModuleList::SymbolContextPasses
if (!(scope & eSymbolContextModule))
return false;
if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec()) != UINT32_MAX)
if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec(), true) != UINT32_MAX)
return true;
else
return false;
@ -551,7 +569,7 @@ SearchFilterByModuleList::Search (Searcher &searcher)
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)
if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) != UINT32_MAX)
{
SymbolContext matchingContext(m_target_sp, ModuleSP(module));
Searcher::CallbackReturn shouldContinue;
@ -602,8 +620,204 @@ SearchFilterByModuleList::GetDescription (Stream *s)
}
}
uint32_t
SearchFilterByModuleList::GetFilterRequiredItems()
{
return eSymbolContextModule;
}
void
SearchFilterByModuleList::Dump (Stream *s) const
{
}
//----------------------------------------------------------------------
// SearchFilterByModuleListAndCU:
// Selects a shared library matching a given file spec
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// SearchFilterByModuleListAndCU constructors
//----------------------------------------------------------------------
SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU (lldb::TargetSP &target_sp,
const FileSpecList &module_list,
const FileSpecList &cu_list) :
SearchFilterByModuleList (target_sp, module_list),
m_cu_spec_list (cu_list)
{
}
//----------------------------------------------------------------------
// SearchFilterByModuleListAndCU copy constructor
//----------------------------------------------------------------------
SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(const SearchFilterByModuleListAndCU& rhs) :
SearchFilterByModuleList (rhs),
m_cu_spec_list (rhs.m_cu_spec_list)
{
}
//----------------------------------------------------------------------
// SearchFilterByModuleListAndCU assignment operator
//----------------------------------------------------------------------
const SearchFilterByModuleListAndCU&
SearchFilterByModuleListAndCU::operator=(const SearchFilterByModuleListAndCU& rhs)
{
if (&rhs != this)
{
m_target_sp = rhs.m_target_sp;
m_module_spec_list = rhs.m_module_spec_list;
m_cu_spec_list = rhs.m_cu_spec_list;
}
return *this;
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU()
{
}
bool
SearchFilterByModuleListAndCU::SymbolContextPasses
(
const SymbolContext &context,
lldb::SymbolContextItem scope
)
{
if (!SearchFilterByModuleList::SymbolContextPasses(context, scope))
return false;
if (!(scope & eSymbolContextCompUnit))
return false;
if (context.comp_unit && m_cu_spec_list.FindFileIndex(0, static_cast<FileSpec>(context.comp_unit), false) == UINT32_MAX)
return false;
return true;
}
bool
SearchFilterByModuleListAndCU::AddressPasses (Address &address)
{
// FIXME: Not yet implemented
return true;
}
bool
SearchFilterByModuleListAndCU::CompUnitPasses (FileSpec &fileSpec)
{
return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
}
bool
SearchFilterByModuleListAndCU::CompUnitPasses (CompileUnit &compUnit)
{
return m_cu_spec_list.FindFileIndex(0, static_cast<FileSpec>(compUnit), false) != UINT32_MAX;
}
void
SearchFilterByModuleListAndCU::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 ();
bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
for (size_t i = 0; i < num_modules; i++)
{
lldb::ModuleSP module_sp = m_target_sp->GetImages().GetModuleAtIndex(i);
if (no_modules_in_filter || m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX)
{
SymbolContext matchingContext(m_target_sp, module_sp);
Searcher::CallbackReturn shouldContinue;
if (searcher.GetDepth() == Searcher::eDepthModule)
{
shouldContinue = DoModuleIteration(matchingContext, searcher);
if (shouldContinue == Searcher::eCallbackReturnStop)
return;
}
else
{
const size_t num_cu = module_sp->GetNumCompileUnits();
for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++)
{
CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
matchingContext.comp_unit = cu_sp.get();
if (m_cu_spec_list.FindFileIndex(0, static_cast<FileSpec>(matchingContext.comp_unit), false) != UINT32_MAX)
{
shouldContinue = DoCUIteration(module_sp, matchingContext, searcher);
if (shouldContinue == Searcher::eCallbackReturnStop)
return;
}
}
}
}
}
}
void
SearchFilterByModuleListAndCU::GetDescription (Stream *s)
{
uint32_t num_modules = m_module_spec_list.GetSize();
if (num_modules == 1)
{
s->Printf (", module = ");
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 if (num_modules > 0)
{
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 (", ");
}
}
}
uint32_t
SearchFilterByModuleListAndCU::GetFilterRequiredItems()
{
return eSymbolContextModule | eSymbolContextCompUnit;
}
void
SearchFilterByModuleListAndCU::Dump (Stream *s) const
{
}

View File

@ -506,10 +506,10 @@ FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full)
bool
FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
{
if (full)
return a == b;
else
if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
return a.m_filename == b.m_filename;
else
return a == b;
}

View File

@ -988,6 +988,7 @@ DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
FileSpecList module_spec_list;
module_spec_list.Append (m_kernel.module_sp->GetFileSpec());
Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
NULL,
"OSKextLoadedKextSummariesUpdated",
eFunctionNameTypeFull,
internal_bp,

View File

@ -262,6 +262,7 @@ ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
if (!m_cxx_exception_bp_sp)
m_cxx_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
NULL,
"__cxa_throw",
eFunctionNameTypeBase,
true);
@ -270,6 +271,7 @@ ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
if (!m_cxx_exception_alloc_bp_sp)
m_cxx_exception_alloc_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
NULL,
"__cxa_allocate",
eFunctionNameTypeBase,
true);

View File

@ -114,6 +114,7 @@ AppleObjCRuntimeV1::SetExceptionBreakpoints ()
if (!m_objc_exception_bp_sp)
{
m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
NULL,
"objc_exception_throw",
eFunctionNameTypeBase,
true);

View File

@ -480,6 +480,7 @@ AppleObjCRuntimeV2::SetExceptionBreakpoints ()
if (!m_objc_exception_bp_sp)
{
m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
NULL,
"__cxa_throw",
eFunctionNameTypeBase,
true);

View File

@ -2534,7 +2534,7 @@ ProcessGDBRemote::StartNoticingNewThreads()
{
for (int i = 0; bp_names[i] != NULL; i++)
{
Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, bp_names[i], eFunctionNameTypeFull, true).get();
Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, NULL, bp_names[i], eFunctionNameTypeFull, true).get();
if (breakpoint)
{
if (log)

View File

@ -1804,7 +1804,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
// find it in the support files, we are done.
if (check_inlines)
{
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true);
if (file_idx == UINT32_MAX)
continue;
}
@ -1818,7 +1818,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
// We will have already looked up the file index if
// we are searching for inline entries.
if (!check_inlines)
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true);
if (file_idx != UINT32_MAX)
{

View File

@ -253,13 +253,13 @@ CompileUnit::GetVariableList(bool can_create)
}
uint32_t
CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, LineEntry *line_entry_ptr)
CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, bool exact, LineEntry *line_entry_ptr)
{
uint32_t file_idx = 0;
if (file_spec_ptr)
{
file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr);
file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr, true);
if (file_idx == UINT32_MAX)
return UINT32_MAX;
}
@ -269,13 +269,14 @@ CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* f
// Unit that is in the support files (the one at 0 was artifically added.)
// So prefer the one further on in the support files if it exists...
FileSpecList &support_files = GetSupportFiles();
file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0));
const bool full = true;
file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0), full);
if (file_idx == UINT32_MAX)
file_idx = 0;
}
LineTable *line_table = GetLineTable();
if (line_table)
return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, true, line_entry_ptr);
return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, exact, line_entry_ptr);
return UINT32_MAX;
}
@ -304,11 +305,11 @@ CompileUnit::ResolveSymbolContext
if (file_spec_matches_cu_file_spec == false && check_inlines == false)
return 0;
uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec);
uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true);
while (file_idx != UINT32_MAX)
{
file_indexes.push_back (file_idx);
file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec);
file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true);
}
const size_t num_file_indexes = file_indexes.size();

View File

@ -207,13 +207,13 @@ Target::GetBreakpointByID (break_id_t break_id)
}
BreakpointSP
Target::CreateBreakpoint (const FileSpecList *containingModules,
const FileSpec &file,
Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *source_file_spec_list,
RegularExpression &source_regex,
bool internal)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, file, source_regex));
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex));
return CreateBreakpoint (filter_sp, resolver_sp, internal);
}
@ -255,7 +255,8 @@ Target::CreateBreakpoint (Address &addr, bool internal)
}
BreakpointSP
Target::CreateBreakpoint (const FileSpecList *containingModules,
Target::CreateBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const char *func_name,
uint32_t func_name_type_mask,
bool internal,
@ -264,7 +265,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
BreakpointSP bp_sp;
if (func_name)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles));
BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL,
func_name,
@ -317,13 +318,36 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules)
return filter_sp;
}
SearchFilterSP
Target::GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles)
{
if (containingSourceFiles == NULL || containingSourceFiles->GetSize() == 0)
return GetSearchFilterForModuleList(containingModules);
SearchFilterSP filter_sp;
lldb::TargetSP target_sp = this->GetSP();
if (containingModules == NULL)
{
// We could make a special "CU List only SearchFilter". Better yet was if these could be composable,
// but that will take a little reworking.
filter_sp.reset (new SearchFilterByModuleListAndCU (target_sp, FileSpecList(), *containingSourceFiles));
}
else
{
filter_sp.reset (new SearchFilterByModuleListAndCU (target_sp, *containingModules, *containingSourceFiles));
}
return filter_sp;
}
BreakpointSP
Target::CreateBreakpoint (const FileSpecList *containingModules,
Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regex,
bool internal,
LazyBool skip_prologue)
{
SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules));
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles));
BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL,
func_regex,
skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));

View File

@ -1,5 +1,5 @@
LEVEL = ../../../make
C_SOURCES := main.c
C_SOURCES := main.c a.c b.c
include $(LEVEL)/Makefile.rules

View File

@ -77,6 +77,25 @@ class BreakpointCommandTestCase(TestBase):
"print >> here",
"here.close()"])
# Next lets try some other breakpoint kinds. First break with a regular expression
# and then specify only one file. The first time we should get two locations,
# the second time only one:
self.expect ("break set -r ._MyFunction",
patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 2"])
self.expect ("break set -r ._MyFunction -f a.c",
patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 1"])
self.expect ("break set -r ._MyFunction -f a.c -f b.c",
patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 2"])
# Now try a source regex breakpoint:
self.expect ("break set -p \"is about to return [12]0\" -f a.c -f b.c",
patterns = ["Breakpoint created: [0-9]+: source regex = \"is about to return \[12\]0\", locations = 2"])
self.expect ("break set -p \"is about to return [12]0\" -f a.c",
patterns = ["Breakpoint created: [0-9]+: source regex = \"is about to return \[12\]0\", locations = 1"])
# Run the program. Remove 'output.txt' if it exists.
if os.path.exists('output.txt'):
os.remove('output.txt')

View File

@ -0,0 +1,9 @@
#include <stdio.h>
int
a_MyFunction ()
{
// Set a breakpoint here.
printf ("a is about to return 10.\n");
return 10;
}

View File

@ -0,0 +1,9 @@
#include <stdio.h>
int
b_MyFunction ()
{
// Set a breakpoint here.
printf ("b is about to return 20.\n");
return 20;
}