kwk created this revision. Herald added subscribers: lldb-commits, dexonsmith, aprantl, mehdi_amini, mgorny. Herald added a reviewer: jdoerfert. Herald added a project: LLDB. kwk planned changes to this revision. kwk added a comment.
I plan to refactor some of this patch. To set a breakpoint on a function called `YOURFUNCTION` you do this: (lldb) breakpoint set -n YOURFUNCTION The output then could look like this: Breakpoint 1: where = YOURTARGET`YOURFUNCTION() + 4 at YOURFILE:1:20, address = 0x01234 LLDB does a good job in finding `YOURFUNCTION` because, indeed, `YOURFILE` contains the definition of `YOURFUNCTION`. Let's say, you not only want to find `YOURFUNCTION` anywhere in `YOURTARGET`. Say, you want to find `YOURFUNCTION` in the file that LLDB found it in. This is how you'd do that: (lldb) breakpoint set -n YOURFUNCTION -f YOURFILE This is where things get a bit tricky. If `YOURFILE` points to a header file in which `YOURFUNCTION` is not only declared but also defined, then chances are that it might be inlined into `YOURTARGET` and LLDB cannot find it. *Why?* You might ask and the answer is that LLDB uses only the `DW_TAG_compile_unit`'s name that it finds under the `DW_AT_name` attribute. Suppose this is a snippet of `llvm-darfdump YOURTARGET` 0x0000000b: DW_TAG_compile_unit DW_AT_name ("main.c") 0x0000002a: DW_TAG_subprogram DW_AT_name ("YOURFUNCTION") DW_AT_decl_file ("YOURFILE") Then LLDB only looks at the file called `main.c` and ignores the `DW_AT_decl_file`. With this change I introduce a switch that teaches LLDB to optionally also respect the `DW_AT_decl_file` all you have to do is pass an option to the previously mentioned breakpoint command. (lldb) breakpoint set -n YOURFUNCTION -f YOURFILE --search-source-files I'm happy to change the name of the flag from `--search-source-files` or `-Q` to something else. Maybe `--respect-decl-file` or `--follow-decl-file` are better names, but for now this is about the working of this patch and not about names. If you're not convinced that this change has any purpose, think about LTO and how it might inline your functions with logic that is hard to reason about when you just have the source code and a binary. For reference, here's the definition for `DW_AT_decl_file` from the DWARF spec in chapter 2.14: > It is sometimes useful in a debugger to be able to associate a > declaration with its occurrence in the program source. > [...] > The value of the DW_AT_decl_file attribute corresponds to a file > number from the line number information table for the compilation unit > containing the debugging information entry and represents the source > file in which the declaration appeared (see Section 6.2 on page 148). > The value 0 indicates that no source file has been specified. Reference to lldb-dev mailing list ================================== I once brought this topic up on the lldb-dev mailing list (http://lists.llvm.org/pipermail/lldb-dev/2019-November/015707.html) and since then worked on it. Performance considerations -------------------------- That is where Jim Ingham wrote: > You probably also want to take some care not to regress the > performance of the case where the function is defined in a CU, since > that's the more common usage. Since I didn't change the default behavior in LLDB, I think the performance is not in danger. Documentation issue ------------------- Jim also brought up an idea of documenting and querying options of commands: > Another thing I've thought about doing is adding the ability to have > help include one of the non-optional, non-overlapping options to the > command, so you could say: > > (lldb) help break set -n > > and that would tell you that this is a "by function name" breakpoint, > and in that case -n means... That might help reduce the information > overload, and give a better sense of what these complex commands do. I haven't implemented this yet but I wanted to bubble this idea up here so it receives more attention. Thoughts on LTO --------------- Jim's thoughts on LTO: > Back to your original query... If the function is defined in a .h > file, or gets inlined by LTO, this filtering is trickier, and I > didn't implement that behavior when I implemented this breakpoint > type. So in that case, and in the case where LTO inlines a function, > the feature isn't implemented correctly. The -n searche always looks > for out of line and inline instances when doing the search. So we > already get the searcher to all the instances. > You would just have to widen the search beyond "Does the CU match" to > try to figure out where the inlined instance was defined. That is essentially what I do in this change. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D74136 Files: lldb/include/lldb/Core/SearchFilter.h lldb/include/lldb/Target/Target.h lldb/source/Breakpoint/BreakpointResolverName.cpp lldb/source/Breakpoint/CMakeLists.txt lldb/source/Commands/CommandObjectBreakpoint.cpp lldb/source/Commands/Options.td lldb/source/Core/SearchFilter.cpp lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp lldb/source/Target/Target.cpp lldb/test/Shell/Breakpoint/Inputs/search-source-files.cpp lldb/test/Shell/Breakpoint/Inputs/search-source-files.h lldb/test/Shell/Breakpoint/Inputs/search-source-files2.h lldb/test/Shell/Breakpoint/search-source-files.test
Index: lldb/test/Shell/Breakpoint/search-source-files.test =================================================================== --- /dev/null +++ lldb/test/Shell/Breakpoint/search-source-files.test @@ -0,0 +1,81 @@ +# In these tests we will set breakpoints on a function by name. That function +# is defined in a header file (search-source-files.h) and will therefore be +# inlined into the file that includes it (search-source-files.cpp). +# +# The change that goes along with this test file introduces a flag +# (--search-source-files or -Q) that you can pass to "(lldb) breakpoint set". +# We run several tests, each one time without and one time with this new +# parameter. That way we verify that LLDB's default behavior hasn't changed. +# +# TODO(kwk): Check that we can also do the same with C++ methods in files? +# (See https://lldb.llvm.org/use/tutorial.html and look for --method.) + +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: %build %p/Inputs/search-source-files.cpp -o dummy.out +# RUN: %lldb -b -s %s dummy.out | FileCheck --color --dump-input=fail %s + +#--------------------------------- +# Set breakpoint by function name. +#--------------------------------- + +breakpoint set -n inlined_42 +# CHECK: (lldb) breakpoint set -n inlined_42 +# CHECK-NEXT: Breakpoint 1: where = dummy.out`inlined_42() + 4 at search-source-files.h:1:20, address = 0x0{{.*}} + +breakpoint set -n inlined_42 --search-source-files +# CHECK: (lldb) breakpoint set -n inlined_42 --search-source-files +# CHECK-NEXT: Breakpoint 2: where = dummy.out`inlined_42() + 4 at search-source-files.h:1:20, address = 0x0{{.*}} + +#---------------------------------------------------------------------- +# Set breakpoint by function name and filename +# (the one in which the function is inlined, aka the compilation unit). +#---------------------------------------------------------------------- + +breakpoint set -n inlined_42 -f search-source-files.cpp +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-source-files.cpp +# CHECK-NEXT: Breakpoint 3: where = dummy.out`inlined_42() + 4 at search-source-files.h:1:20, address = 0x0{{.*}} + +breakpoint set -n inlined_42 -f search-source-files.cpp --search-source-files +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-source-files.cpp --search-source-files +# CHECK-NEXT: Breakpoint 4: no locations (pending). + +#---------------------------------------------------- +# Set breakpoint by function name and source filename +# (the file in which the function is defined). +# +# NOTE: This test is the really interesting one as it +# shows that we can now search by source files +# that are themselves no compulation units when +# the --search-source-files parameter is given. +#---------------------------------------------------- + +breakpoint set -n inlined_42 -f search-source-files.h +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-source-files.h +# CHECK-NEXT: Breakpoint 5: no locations (pending). +# CHECK-NEXT: WARNING: Unable to resolve breakpoint to any actual locations. + +breakpoint set -n inlined_42 -f search-source-files.h --search-source-files +# CHECK: (lldb) breakpoint set -n inlined_42 -f search-source-files.h --search-source-files +# CHECK-NEXT: Breakpoint 6: where = dummy.out`inlined_42() + 4 at search-source-files.h:1:20, address = 0x0{{.*}} + +#----------------------------------------------------- +# Set breakpoint by function name and source filename. +# This time the file doesn't exist. +# +# NOTE: This test exists in order to prove that +# --search-source-files doesn't widen the search +# space too much. When we search for a function +# in file that doesn't exist, we should get no +# results. +#----------------------------------------------------- + +breakpoint set -n inlined_42 -f file-not-existing.h +# CHECK: (lldb) breakpoint set -n inlined_42 -f file-not-existing.h +# CHECK-NEXT: Breakpoint 7: no locations (pending). +# CHECK-NEXT: WARNING: Unable to resolve breakpoint to any actual locations. + +breakpoint set -n inlined_42 -f file-not-existing.h --search-source-files +# CHECK: (lldb) breakpoint set -n inlined_42 -f file-not-existing.h --search-source-files +# CHECK-NEXT: Breakpoint 8: no locations (pending). +# CHECK-NEXT: WARNING: Unable to resolve breakpoint to any actual locations. Index: lldb/test/Shell/Breakpoint/Inputs/search-source-files2.h =================================================================== --- /dev/null +++ lldb/test/Shell/Breakpoint/Inputs/search-source-files2.h @@ -0,0 +1 @@ +int return_zero() { return 0; } \ No newline at end of file Index: lldb/test/Shell/Breakpoint/Inputs/search-source-files.h =================================================================== --- /dev/null +++ lldb/test/Shell/Breakpoint/Inputs/search-source-files.h @@ -0,0 +1 @@ +int inlined_42() { return 42; } Index: lldb/test/Shell/Breakpoint/Inputs/search-source-files.cpp =================================================================== --- /dev/null +++ lldb/test/Shell/Breakpoint/Inputs/search-source-files.cpp @@ -0,0 +1,7 @@ +#include "search-source-files.h" +#include "search-source-files2.h" + +int main(int argc, char *argv[]) { + int a = inlined_42(); + return return_zero() + a; +} Index: lldb/source/Target/Target.cpp =================================================================== --- lldb/source/Target/Target.cpp +++ lldb/source/Target/Target.cpp @@ -323,7 +323,7 @@ LazyBool check_inlines, LazyBool skip_prologue, bool internal, bool hardware, - LazyBool move_to_nearest_code) { + LazyBool move_to_nearest_code) { FileSpec remapped_file; if (!GetSourcePathMap().ReverseRemapPath(file, remapped_file)) remapped_file = file; @@ -438,12 +438,18 @@ const std::vector<std::string> &func_names, FunctionNameType func_name_type_mask, LanguageType language, lldb::addr_t offset, - LazyBool skip_prologue, bool internal, bool hardware) { + LazyBool skip_prologue, bool internal, bool hardware, + bool search_source_files) { BreakpointSP bp_sp; size_t num_names = func_names.size(); if (num_names > 0) { - SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList( - containingModules, containingSourceFiles)); + SearchFilterSP filter_sp; + if (search_source_files) + filter_sp = GetSearchFilterForModuleListAndCUOrSupportFile( + containingModules, containingSourceFiles); + else + filter_sp = GetSearchFilterForModuleAndCUList(containingModules, + containingSourceFiles); if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; @@ -544,6 +550,23 @@ return filter_sp; } +SearchFilterSP Target::GetSearchFilterForModuleListAndCUOrSupportFile( + const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles) { + if (containingSourceFiles == nullptr || containingSourceFiles->GetSize() == 0) + return GetSearchFilterForModuleList(containingModules); + + SearchFilterSP filter_sp; + if (containingModules == nullptr) { + filter_sp = std::make_shared<SearchFilterByModuleListAndCUOrSupportFile>( + shared_from_this(), FileSpecList(), *containingSourceFiles); + } else { + filter_sp = std::make_shared<SearchFilterByModuleListAndCUOrSupportFile>( + shared_from_this(), *containingModules, *containingSourceFiles); + } + return filter_sp; +} + BreakpointSP Target::CreateFuncRegexBreakpoint( const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, RegularExpression func_regex, Index: lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp =================================================================== --- lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -350,7 +350,9 @@ 0, /* offset */ eLazyBoolNo, /* skip_prologue */ true, /* internal */ - false /* request_hardware */); + false, /* request_hardware */ + false /* search source files */ + ); } if (dyld_break->GetNumResolvedLocations() != 1) { Index: lldb/source/Core/SearchFilter.cpp =================================================================== --- lldb/source/Core/SearchFilter.cpp +++ lldb/source/Core/SearchFilter.cpp @@ -40,13 +40,14 @@ using namespace lldb; using namespace lldb_private; -const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception", - "Module", "Modules", - "ModulesAndCU", "Unknown"}; +const char *SearchFilter::g_ty_to_name[] = { + "Unconstrained", "Exception", "Module", + "Modules", "ModulesAndCU", "ModulesAndCUOrSupportFile", + "Unknown"}; const char *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = { - "ModuleList", "CUList"}; + "ModuleList", "CUList", "CUOrSupportFileList"}; const char *SearchFilter::FilterTyToName(enum FilterTy type) { if (type > LastKnownFilterType) @@ -123,6 +124,11 @@ result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData( target, *subclass_options, error); break; + case ByModuleListAndCUOrSupportFile: + result_sp = + SearchFilterByModuleListAndCUOrSupportFile::CreateFromStructuredData( + target, *subclass_options, error); + break; case Exception: error.SetErrorString("Can't serialize exception breakpoints yet."); break; @@ -659,9 +665,9 @@ SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( const lldb::TargetSP &target_sp, const FileSpecList &module_list, - const FileSpecList &cu_list) + const FileSpecList &cu_list, enum FilterTy filter_ty) : SearchFilterByModuleList(target_sp, module_list, - FilterTy::ByModulesAndCU), + filter_ty), m_cu_spec_list(cu_list) {} SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default; @@ -710,7 +716,7 @@ } return std::make_shared<SearchFilterByModuleListAndCU>( - target.shared_from_this(), modules, cus); + target.shared_from_this(), modules, cus, FilterTy::ByModulesAndCU); } StructuredData::ObjectSP @@ -836,3 +842,61 @@ SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) { return std::make_shared<SearchFilterByModuleListAndCU>(*this); } + +// SearchFilterByModuleListAndCUOrSupportFile: + +SearchFilterByModuleListAndCUOrSupportFile:: + SearchFilterByModuleListAndCUOrSupportFile( + const lldb::TargetSP &target_sp, const FileSpecList &module_list, + const FileSpecList &cu_or_support_file_list) + : SearchFilterByModuleListAndCU(target_sp, module_list, + cu_or_support_file_list, + FilterTy::ByModuleListAndCUOrSupportFile) {} + +SearchFilterByModuleListAndCUOrSupportFile:: + SearchFilterByModuleListAndCUOrSupportFile( + const SearchFilterByModuleListAndCUOrSupportFile &rhs) = default; + +SearchFilterByModuleListAndCUOrSupportFile:: + ~SearchFilterByModuleListAndCUOrSupportFile() = default; + +StructuredData::ObjectSP +SearchFilterByModuleListAndCUOrSupportFile::SerializeToStructuredData() { + auto options_dict_sp = std::make_shared<StructuredData::Dictionary>(); + SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp); + SerializeFileSpecList(options_dict_sp, OptionNames::CUOrSupportFileList, + m_cu_spec_list); + return WrapOptionsDict(options_dict_sp); +} + +bool SearchFilterByModuleListAndCUOrSupportFile::AddressPasses( + Address &address) { + SymbolContext sym_ctx; + address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything); + if (!sym_ctx.comp_unit) { + if (m_cu_spec_list.GetSize() != 0) + return false; // Has no comp_unit so can't pass the file check. + } + FileSpec cu_spec; + if (sym_ctx.comp_unit) + cu_spec = sym_ctx.comp_unit->GetPrimaryFile(); + // If the primary source file associated with the symbol's compile unit is in + // the list of CU's or support files, that's enough. + // TODO(kwk): Is that enough? + if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) != + UINT32_MAX) + return true; // Passes the file check (SearchFilterByModuleListAndCU returns true here) + return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp); +} + +uint32_t SearchFilterByModuleListAndCUOrSupportFile::GetFilterRequiredItems() { + return eSymbolContextModule | eSymbolContextCompUnit | eSymbolContextFunction; +} + +lldb::SearchFilterSP +SearchFilterByModuleListAndCUOrSupportFile::DoCopyForBreakpoint( + Breakpoint &breakpoint) { + return std::make_shared<SearchFilterByModuleListAndCUOrSupportFile>(*this); +} + + Index: lldb/source/Commands/Options.td =================================================================== --- lldb/source/Commands/Options.td +++ lldb/source/Commands/Options.td @@ -196,6 +196,8 @@ Groups<[1, 9]>, Arg<"Boolean">, Desc<"Move breakpoints to nearest code. If not set the " "target.move-to-nearest-codesetting is used.">; + def breakpoint_set_search_source_files : Option<"search-source-files", "Q">, + Desc<"Always search all search files and not only compilation unit files when using -f or derivates.">; /* Don't add this option till it actually does something useful... def breakpoint_set_exception_typename : Option<"exception-typename", "O">, Arg<"TypeName">, Desc<"The breakpoint will only stop if an " Index: lldb/source/Commands/CommandObjectBreakpoint.cpp =================================================================== --- lldb/source/Commands/CommandObjectBreakpoint.cpp +++ lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -444,6 +444,10 @@ m_source_regex_func_names.insert(std::string(option_arg)); break; + case 'Q': { + m_search_source_files = true; + } break; + default: llvm_unreachable("Unimplemented option"); } @@ -474,6 +478,7 @@ m_move_to_nearest_code = eLazyBoolCalculate; m_source_regex_func_names.clear(); m_current_key.clear(); + m_search_source_files = false; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -505,6 +510,9 @@ LazyBool m_move_to_nearest_code; std::unordered_set<std::string> m_source_regex_func_names; std::string m_current_key; + bool m_search_source_files; // When using -f or derivates make sure to + // always search all source files and not only + // compilation unit file names. }; protected: @@ -611,7 +619,7 @@ &(m_options.m_modules), &(m_options.m_filenames), m_options.m_func_names, name_type_mask, m_options.m_language, m_options.m_offset_addr, m_options.m_skip_prologue, internal, - m_options.m_hardware); + m_options.m_hardware, m_options.m_search_source_files); } break; case eSetTypeFunctionRegexp: // Breakpoint by regular expression function Index: lldb/source/Breakpoint/CMakeLists.txt =================================================================== --- lldb/source/Breakpoint/CMakeLists.txt +++ lldb/source/Breakpoint/CMakeLists.txt @@ -13,6 +13,7 @@ BreakpointResolverAddress.cpp BreakpointResolverFileLine.cpp BreakpointResolverFileRegex.cpp +# BreakpointResolverDeclFileRegex.cpp BreakpointResolverName.cpp BreakpointResolverScripted.cpp BreakpointSite.cpp Index: lldb/source/Breakpoint/BreakpointResolverName.cpp =================================================================== --- lldb/source/Breakpoint/BreakpointResolverName.cpp +++ lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -248,6 +248,8 @@ // accelerate function lookup. At that point, we should switch the depth to // CompileUnit, and look in these tables. +#include "lldb/Symbol/CompileUnit.h" + Searcher::CallbackReturn BreakpointResolverName::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr) { @@ -268,6 +270,8 @@ } bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; + bool filter_by_function = + (filter.GetFilterRequiredItems() & eSymbolContextFunction) != 0; bool filter_by_language = (m_language != eLanguageTypeUnknown); const bool include_symbols = !filter_by_cu; const bool include_inlines = true; @@ -312,8 +316,26 @@ SymbolContext sc; func_list.GetContextAtIndex(idx, sc); if (filter_by_cu) { - if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) - remove_it = true; + if (!filter_by_function) { + if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) + remove_it = true; + } else { + // TODO(kwk): Currently this appears somewhat like a hack because only + // the SearchFilterByModuleListAndCUOrSupportFile search filter + // requires eSymbolContextCompUnit and eSymbolContextFunction + // (filter_by_cu && filter_by_function). + + // Keep this symbol context if it is a function call to a function + // whose declaration is located in a file that passes. This is needed + // for inlined functions (e.g. when LTO is enabled) and templates. + if (Type *type = sc.function->GetType()) { + Declaration &decl = + const_cast<Declaration &>(type->GetDeclaration()); + FileSpec &source_file = decl.GetFile(); + if (!filter.CompUnitPasses(source_file)) + remove_it = true; + } + } } if (filter_by_language) { @@ -335,64 +357,67 @@ // Remove any duplicates between the function list and the symbol list SymbolContext sc; - if (func_list.GetSize()) { - for (i = 0; i < func_list.GetSize(); i++) { - if (func_list.GetContextAtIndex(i, sc)) { - bool is_reexported = false; - - if (sc.block && sc.block->GetInlinedFunctionInfo()) { - if (!sc.block->GetStartAddress(break_addr)) - break_addr.Clear(); - } else if (sc.function) { - break_addr = sc.function->GetAddressRange().GetBaseAddress(); - if (m_skip_prologue && break_addr.IsValid()) { - const uint32_t prologue_byte_size = - sc.function->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - } - } else if (sc.symbol) { - if (sc.symbol->GetType() == eSymbolTypeReExported) { - const Symbol *actual_symbol = - sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); - if (actual_symbol) { - is_reexported = true; - break_addr = actual_symbol->GetAddress(); - } - } else { - break_addr = sc.symbol->GetAddress(); - } - - if (m_skip_prologue && break_addr.IsValid()) { - const uint32_t prologue_byte_size = - sc.symbol->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - else { - const Architecture *arch = - m_breakpoint->GetTarget().GetArchitecturePlugin(); - if (arch) - arch->AdjustBreakpointAddress(*sc.symbol, break_addr); - } - } + if (!func_list.GetSize()) + return Searcher::eCallbackReturnContinue; + + for (i = 0; i < func_list.GetSize(); i++) { + if (!func_list.GetContextAtIndex(i, sc)) + continue; + + bool is_reexported = false; + + if (sc.block && sc.block->GetInlinedFunctionInfo()) { + if (!sc.block->GetStartAddress(break_addr)) + break_addr.Clear(); + } else if (sc.function) { + break_addr = sc.function->GetAddressRange().GetBaseAddress(); + if (m_skip_prologue && break_addr.IsValid()) { + const uint32_t prologue_byte_size = + sc.function->GetPrologueByteSize(); + if (prologue_byte_size) + break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + } + } else if (sc.symbol) { + if (sc.symbol->GetType() == eSymbolTypeReExported) { + const Symbol *actual_symbol = + sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); + if (actual_symbol) { + is_reexported = true; + break_addr = actual_symbol->GetAddress(); } + } else { + break_addr = sc.symbol->GetAddress(); + } - if (break_addr.IsValid()) { - if (filter.AddressPasses(break_addr)) { - BreakpointLocationSP bp_loc_sp( - AddLocation(break_addr, &new_location)); - bp_loc_sp->SetIsReExported(is_reexported); - if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) { - if (log) { - StreamString s; - bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - LLDB_LOGF(log, "Added location: %s\n", s.GetData()); - } - } - } + if (m_skip_prologue && break_addr.IsValid()) { + const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); + if (prologue_byte_size) + break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + else { + const Architecture *arch = + m_breakpoint->GetTarget().GetArchitecturePlugin(); + if (arch) + arch->AdjustBreakpointAddress(*sc.symbol, break_addr); } } } + + if (!break_addr.IsValid()) + continue; + + if (!filter.AddressPasses(break_addr)) + continue; + + BreakpointLocationSP bp_loc_sp( + AddLocation(break_addr, &new_location)); + bp_loc_sp->SetIsReExported(is_reexported); + if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) { + if (log) { + StreamString s; + bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); + LLDB_LOGF(log, "Added location: %s\n", s.GetData()); + } + } } return Searcher::eCallbackReturnContinue; Index: lldb/include/lldb/Target/Target.h =================================================================== --- lldb/include/lldb/Target/Target.h +++ lldb/include/lldb/Target/Target.h @@ -660,8 +660,8 @@ const std::vector<std::string> &func_names, lldb::FunctionNameType func_name_type_mask, lldb::LanguageType language, lldb::addr_t m_offset, - LazyBool skip_prologue, bool internal, - bool request_hardware); + LazyBool skip_prologue, bool internal, bool request_hardware, + bool search_source_files); // Use this to create a general breakpoint: lldb::BreakpointSP CreateBreakpoint(lldb::SearchFilterSP &filter_sp, @@ -1236,6 +1236,10 @@ GetSearchFilterForModuleAndCUList(const FileSpecList *containingModules, const FileSpecList *containingSourceFiles); + lldb::SearchFilterSP GetSearchFilterForModuleListAndCUOrSupportFile( + const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles); + lldb::REPLSP GetREPL(Status &err, lldb::LanguageType language, const char *repl_options, bool can_create); Index: lldb/include/lldb/Core/SearchFilter.h =================================================================== --- lldb/include/lldb/Core/SearchFilter.h +++ lldb/include/lldb/Core/SearchFilter.h @@ -210,7 +210,8 @@ ByModule, ByModules, ByModulesAndCU, - LastKnownFilterType = ByModulesAndCU, + ByModuleListAndCUOrSupportFile, + LastKnownFilterType = ByModuleListAndCUOrSupportFile, UnknownFilter }; @@ -231,7 +232,13 @@ protected: // Serialization of SearchFilter options: - enum OptionNames { ModList = 0, CUList, LanguageName, LastOptionName }; + enum OptionNames { + ModList = 0, + CUList, + LanguageName, + CUOrSupportFileList, + LastOptionName + }; static const char *g_option_names[LastOptionName]; static const char *GetKey(enum OptionNames enum_value) { @@ -404,9 +411,10 @@ public: /// The basic constructor takes a Target, which gives the space to search, /// and the module list to restrict the search to. - SearchFilterByModuleListAndCU(const lldb::TargetSP &targetSP, - const FileSpecList &module_list, - const FileSpecList &cu_list); + SearchFilterByModuleListAndCU( + const lldb::TargetSP &targetSP, const FileSpecList &module_list, + const FileSpecList &cu_list, + enum FilterTy filter_ty = FilterTy::ByModulesAndCU); ~SearchFilterByModuleListAndCU() override; @@ -434,10 +442,32 @@ protected: lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; -private: +protected: FileSpecList m_cu_spec_list; }; +class SearchFilterByModuleListAndCUOrSupportFile + : public SearchFilterByModuleListAndCU { +public: + SearchFilterByModuleListAndCUOrSupportFile( + const lldb::TargetSP &targetSP, const FileSpecList &module_list, + const FileSpecList &cu_or_file_list); + + SearchFilterByModuleListAndCUOrSupportFile( + const SearchFilterByModuleListAndCUOrSupportFile &rhs); + + ~SearchFilterByModuleListAndCUOrSupportFile() override; + + bool AddressPasses(Address &address) override; + + uint32_t GetFilterRequiredItems() override; + + StructuredData::ObjectSP SerializeToStructuredData() override; + +protected: + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; +}; + } // namespace lldb_private #endif // liblldb_SearchFilter_h_
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits