diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h --- a/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -10,6 +10,7 @@ #define LLDB_BREAKPOINT_BREAKPOINTRESOLVERFILELINE_H #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Utility/SourceLocationSpec.h" namespace lldb_private { @@ -21,10 +22,8 @@ class BreakpointResolverFileLine : public BreakpointResolver { public: BreakpointResolverFileLine(const lldb::BreakpointSP &bkpt, - const FileSpec &resolver, - uint32_t line_no, uint32_t column, - lldb::addr_t m_offset, bool check_inlines, - bool skip_prologue, bool exact_match); + lldb::addr_t offset, bool skip_prologue, + const SourceLocationSpec &location_spec); static BreakpointResolver * CreateFromStructuredData(const lldb::BreakpointSP &bkpt, @@ -60,13 +59,8 @@ void FilterContexts(SymbolContextList &sc_list, bool is_relative); friend class Breakpoint; - FileSpec m_file_spec; ///< This is the file spec we are looking for. - uint32_t m_line_number; ///< This is the line number that we are looking for. - uint32_t m_column; ///< This is the column that we are looking for. - bool m_inlines; ///< This determines whether the resolver looks for inlined - ///< functions or not. + SourceLocationSpec m_location_spec; bool m_skip_prologue; - bool m_exact_match; private: BreakpointResolverFileLine(const BreakpointResolverFileLine &) = delete; diff --git a/lldb/include/lldb/Core/AddressResolverFileLine.h b/lldb/include/lldb/Core/AddressResolverFileLine.h --- a/lldb/include/lldb/Core/AddressResolverFileLine.h +++ b/lldb/include/lldb/Core/AddressResolverFileLine.h @@ -11,7 +11,7 @@ #include "lldb/Core/AddressResolver.h" #include "lldb/Core/SearchFilter.h" -#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/SourceLocationSpec.h" #include "lldb/lldb-defines.h" #include @@ -28,8 +28,7 @@ class AddressResolverFileLine : public AddressResolver { public: - AddressResolverFileLine(const FileSpec &resolver, uint32_t line_no, - bool check_inlines); + AddressResolverFileLine(SourceLocationSpec location_spec); ~AddressResolverFileLine() override; @@ -42,10 +41,7 @@ void GetDescription(Stream *s) override; protected: - FileSpec m_file_spec; // This is the file spec we are looking for. - uint32_t m_line_number; // This is the line number that we are looking for. - bool m_inlines; // This determines whether the resolver looks for inlined - // functions or not. + SourceLocationSpec m_src_location_spec; private: AddressResolverFileLine(const AddressResolverFileLine &) = delete; diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -15,6 +15,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SourceModule.h" +#include "lldb/Utility/SourceLocationSpec.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-enumerations.h" @@ -345,29 +346,22 @@ /// Resolve symbol contexts by file and line. /// - /// Given a file in \a file_spec, and a line number, find all instances and + /// Given a file in \a src_location_spec, find all instances and /// append them to the supplied symbol context list \a sc_list. /// - /// \param[in] file_spec - /// A file specification. If \a file_spec contains no directory - /// information, only the basename will be used when matching - /// contexts. If the directory in \a file_spec is valid, a - /// complete file specification match will be performed. - /// - /// \param[in] line - /// The line number to match against the compile unit's line - /// tables. + /// \param[in] src_location_spec + /// The \a src_location_spec containing the \a file_spec, the line and the + /// column of the symbol to look for. Also hold the inlines and + /// exact_match flags. /// - /// \param[in] check_inlines - /// If \b true this function will also match any inline + /// If check_inlines is \b true, this function will also match any inline /// file and line matches. If \b false, the compile unit's /// file specification must match \a file_spec for any matches /// to be returned. /// - /// \param[in] exact - /// If true, only resolve the context if \a line exists in the line table. - /// If false, resolve the context to the closest line greater than \a line - /// in the line table. + /// If exact_match is \b true, only resolve the context if \a line and \a + /// column exists in the line table. If \b false, resolve the context to + /// the closest line greater than \a line in the line table. /// /// \param[in] resolve_scope /// For each matching line entry, this bitfield indicates what @@ -382,8 +376,7 @@ /// entries appended to. /// /// \see enum SymbolContext::Scope - void ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, - bool check_inlines, bool exact, + void ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -14,6 +14,7 @@ #include "lldb/Core/Section.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Utility/RangeMap.h" +#include "lldb/Utility/SourceLocationSpec.h" #include "lldb/lldb-private.h" #include @@ -137,12 +138,8 @@ /// CompileUnit::GetSupportFiles() /// FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const /// - /// \param[in] line - /// The source line to match. - /// - /// \param[in] exact - /// If true, match only if you find a line entry exactly matching \a line. - /// If false, return the closest line entry greater than \a line. + /// \param[in] src_location_spec + /// The source location specifier to match. /// /// \param[out] line_entry_ptr /// A pointer to a line entry object that will get a copy of @@ -155,13 +152,14 @@ /// /// \see CompileUnit::GetSupportFiles() /// \see FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const - uint32_t FindLineEntryIndexByFileIndex(uint32_t start_idx, uint32_t file_idx, - uint32_t line, bool exact, - LineEntry *line_entry_ptr); + uint32_t + FindLineEntryIndexByFileIndex(uint32_t start_idx, uint32_t file_idx, + const SourceLocationSpec &src_location_spec, + LineEntry *line_entry_ptr); uint32_t FindLineEntryIndexByFileIndex( uint32_t start_idx, const std::vector &file_indexes, - uint32_t line, bool exact, LineEntry *line_entry_ptr); + const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr); size_t FineLineEntriesForFileIndex(uint32_t file_idx, bool append, SymbolContextList &sc_list); diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -18,6 +18,7 @@ #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeSystem.h" +#include "lldb/Utility/SourceLocationSpec.h" #include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-private.h" #include "llvm/ADT/DenseSet.h" @@ -209,10 +210,10 @@ virtual uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) = 0; - virtual uint32_t ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, bool check_inlines, - lldb::SymbolContextItem resolve_scope, - SymbolContextList &sc_list); + virtual uint32_t + ResolveSymbolContext(const SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + SymbolContextList &sc_list); virtual void DumpClangAST(Stream &s) {} virtual void FindGlobalVariables(ConstString name, diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -843,12 +843,20 @@ std::vector step_over_until_addrs; const bool abort_other_plans = false; const bool stop_other_threads = false; + // TODO: Handle SourceLocationSpec column information const bool check_inlines = true; const bool exact = false; + auto location_spec = SourceLocationSpec::Create( + step_file_spec, line, /*column=*/llvm::None, check_inlines, exact); + if (!location_spec) { + sb_error.SetErrorString( + llvm::toString(location_spec.takeError()).c_str()); + return sb_error; + } + SymbolContextList sc_list; - frame_sc.comp_unit->ResolveSymbolContext(step_file_spec, line, - check_inlines, exact, + frame_sc.comp_unit->ResolveSymbolContext(*location_spec, eSymbolContextLineEntry, sc_list); const uint32_t num_matches = sc_list.GetSize(); if (num_matches > 0) { diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -980,9 +980,12 @@ if (m_resolver_sp) { BreakpointResolverFileLine *resolverFileLine = dyn_cast(m_resolver_sp.get()); + + // TODO: Handle SourceLocationSpec column information if (resolverFileLine && - resolverFileLine->m_file_spec.GetFilename() == filename && - resolverFileLine->m_line_number == line_number) { + resolverFileLine->m_location_spec.GetFileSpec().GetFilename() == + filename && + resolverFileLine->m_location_spec.GetLine() == line_number) { return true; } } diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -20,20 +20,17 @@ // BreakpointResolverFileLine: BreakpointResolverFileLine::BreakpointResolverFileLine( - const BreakpointSP &bkpt, const FileSpec &file_spec, uint32_t line_no, - uint32_t column, lldb::addr_t offset, bool check_inlines, - bool skip_prologue, bool exact_match) + const BreakpointSP &bkpt, lldb::addr_t offset, bool skip_prologue, + const SourceLocationSpec &location_spec) : BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset), - m_file_spec(file_spec), m_line_number(line_no), m_column(column), - m_inlines(check_inlines), m_skip_prologue(skip_prologue), - m_exact_match(exact_match) {} + m_location_spec(location_spec), m_skip_prologue(skip_prologue) {} BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, Status &error) { llvm::StringRef filename; - uint32_t line_no; - uint32_t column; + uint32_t line; + uint16_t column; bool check_inlines; bool skip_prologue; bool exact_match; @@ -49,7 +46,7 @@ } success = options_dict.GetValueForKeyAsInteger( - GetKey(OptionNames::LineNumber), line_no); + GetKey(OptionNames::LineNumber), line); if (!success) { error.SetErrorString("BRFL::CFSD: Couldn't find line number entry."); return nullptr; @@ -84,10 +81,16 @@ } FileSpec file_spec(filename); + auto location_spec = SourceLocationSpec::Create(file_spec, line, column, + check_inlines, exact_match); - return new BreakpointResolverFileLine(bkpt, file_spec, line_no, column, - offset, check_inlines, skip_prologue, - exact_match); + if (!location_spec) { + error.SetErrorString(llvm::toString(location_spec.takeError())); + return nullptr; + } + + return new BreakpointResolverFileLine(bkpt, offset, skip_prologue, + *location_spec); } StructuredData::ObjectSP @@ -95,17 +98,24 @@ StructuredData::DictionarySP options_dict_sp( new StructuredData::Dictionary()); - options_dict_sp->AddStringItem(GetKey(OptionNames::FileName), - m_file_spec.GetPath()); - options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber), - m_line_number); - options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column), - m_column); - options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines); options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue), m_skip_prologue); + options_dict_sp->AddStringItem(GetKey(OptionNames::FileName), + m_location_spec.GetFileSpec().GetPath()); + options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber), + m_location_spec.GetLine()); + + llvm::Optional column = m_location_spec.GetColumn(); + if (!column) + options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column), + LLDB_INVALID_COLUMN_NUMBER); + else + options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column), *column); + + options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), + m_location_spec.GetCheckInlines()); options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch), - m_exact_match); + m_location_spec.GetExactMatch()); return WrapOptionsDict(options_dict_sp); } @@ -119,12 +129,12 @@ // inlined into. void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, bool is_relative) { - if (m_exact_match) + if (m_location_spec.GetExactMatch()) return; // Nothing to do. Contexts are precise. llvm::StringRef relative_path; if (is_relative) - relative_path = m_file_spec.GetDirectory().GetStringRef(); + relative_path = m_location_spec.GetFileSpec().GetDirectory().GetStringRef(); Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); for(uint32_t i = 0; i < sc_list.GetSize(); ++i) { @@ -191,12 +201,13 @@ // But only do this calculation if the line number we found in the SC // was different from the one requested in the source file. If we actually // found an exact match it must be valid. - - if (m_line_number == sc.line_entry.line) + + if (m_location_spec.GetLine() == sc.line_entry.line) continue; const int decl_line_is_too_late_fudge = 1; - if (line && m_line_number < line - decl_line_is_too_late_fudge) { + if (line && + m_location_spec.GetLine() < line - decl_line_is_too_late_fudge) { LLDB_LOG(log, "removing symbol context at {0}:{1}", file, line); sc_list.RemoveContextAtIndex(i); --i; @@ -224,8 +235,13 @@ // file. So we go through the match list and pull out the sets that have the // same file spec in their line_entry and treat each set separately. - FileSpec search_file_spec = m_file_spec; - const bool is_relative = m_file_spec.IsRelative(); + const uint32_t line = m_location_spec.GetLine(); + auto optional_column = m_location_spec.GetColumn(); + const uint16_t column = + optional_column ? *optional_column : LLDB_INVALID_COLUMN_NUMBER; + + FileSpec search_file_spec = m_location_spec.GetFileSpec(); + const bool is_relative = search_file_spec.IsRelative(); if (is_relative) search_file_spec.GetDirectory().Clear(); @@ -234,8 +250,7 @@ CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); if (cu_sp) { if (filter.CompUnitPasses(*cu_sp)) - cu_sp->ResolveSymbolContext(search_file_spec, m_line_number, m_inlines, - m_exact_match, eSymbolContextEverything, + cu_sp->ResolveSymbolContext(m_location_spec, eSymbolContextEverything, sc_list); } } @@ -243,11 +258,12 @@ FilterContexts(sc_list, is_relative); StreamString s; - s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString(""), - m_line_number); + s.Printf("for %s:%d ", + m_location_spec.GetFileSpec().GetFilename().AsCString(""), + line); - SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(), - m_line_number, m_column); + SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(), line, + column); return Searcher::eCallbackReturnContinue; } @@ -257,11 +273,13 @@ } void BreakpointResolverFileLine::GetDescription(Stream *s) { - s->Printf("file = '%s', line = %u, ", m_file_spec.GetPath().c_str(), - m_line_number); - if (m_column) - s->Printf("column = %u, ", m_column); - s->Printf("exact_match = %d", m_exact_match); + s->Printf("file = '%s', line = %u, ", + m_location_spec.GetFileSpec().GetPath().c_str(), + m_location_spec.GetLine()); + auto column = m_location_spec.GetColumn(); + if (column) + s->Printf("column = %u, ", *column); + s->Printf("exact_match = %d", m_location_spec.GetExactMatch()); } void BreakpointResolverFileLine::Dump(Stream *s) const {} @@ -269,8 +287,7 @@ lldb::BreakpointResolverSP BreakpointResolverFileLine::CopyForBreakpoint(BreakpointSP &breakpoint) { lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine( - breakpoint, m_file_spec, m_line_number, m_column, GetOffset(), m_inlines, - m_skip_prologue, m_exact_match)); + breakpoint, GetOffset(), m_skip_prologue, m_location_spec)); return ret_sp; } diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp --- a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -107,10 +107,16 @@ uint32_t num_matches = line_matches.size(); for (uint32_t i = 0; i < num_matches; i++) { SymbolContextList sc_list; + // TODO: Handle SourceLocationSpec column information const bool search_inlines = false; - - cu->ResolveSymbolContext(cu_file_spec, line_matches[i], search_inlines, - m_exact_match, eSymbolContextEverything, sc_list); + auto location_spec = SourceLocationSpec::Create( + cu_file_spec, line_matches[i], /*column=*/llvm::None, search_inlines, + m_exact_match); + if (!location_spec) { + llvm::errs() << "Invalid SourceLocationSpec.\n"; + return eCallbackReturnContinue; + } + cu->ResolveSymbolContext(*location_spec, eSymbolContextEverything, sc_list); // Find all the function names: if (!m_function_names.empty()) { std::vector sc_to_remove; diff --git a/lldb/source/Core/AddressResolverFileLine.cpp b/lldb/source/Core/AddressResolverFileLine.cpp --- a/lldb/source/Core/AddressResolverFileLine.cpp +++ b/lldb/source/Core/AddressResolverFileLine.cpp @@ -28,11 +28,9 @@ using namespace lldb_private; // AddressResolverFileLine: -AddressResolverFileLine::AddressResolverFileLine(const FileSpec &file_spec, - uint32_t line_no, - bool check_inlines) - : AddressResolver(), m_file_spec(file_spec), m_line_number(line_no), - m_inlines(check_inlines) {} +AddressResolverFileLine::AddressResolverFileLine( + SourceLocationSpec location_spec) + : AddressResolver(), m_src_location_spec(location_spec) {} AddressResolverFileLine::~AddressResolverFileLine() {} @@ -44,8 +42,9 @@ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - cu->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, false, - eSymbolContextEverything, sc_list); + // TODO: Handle SourceLocationSpec column information + cu->ResolveSymbolContext(m_src_location_spec, eSymbolContextEverything, + sc_list); uint32_t sc_list_size = sc_list.GetSize(); for (uint32_t i = 0; i < sc_list_size; i++) { SymbolContext sc; @@ -65,8 +64,9 @@ "error: Unable to resolve address at file address 0x%" PRIx64 " for %s:%d\n", line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString(""), - m_line_number); + m_src_location_spec.GetFileSpec().GetFilename().AsCString( + ""), + m_src_location_spec.GetLine()); } } } @@ -78,6 +78,8 @@ } void AddressResolverFileLine::GetDescription(Stream *s) { - s->Printf("File and line address - file: \"%s\" line: %u", - m_file_spec.GetFilename().AsCString(""), m_line_number); + s->Printf( + "File and line address - file: \"%s\" line: %u", + m_src_location_spec.GetFileSpec().GetFilename().AsCString(""), + m_src_location_spec.GetLine()); } diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -598,9 +598,20 @@ const uint32_t initial_count = sc_list.GetSize(); - if (SymbolFile *symbols = GetSymbolFile()) - symbols->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, - sc_list); + if (SymbolFile *symbols = GetSymbolFile()) { + // TODO: Handle SourceLocationSpec column information + const bool exact_match = false; + auto location_spec = SourceLocationSpec::Create(file_spec, line, + /*column=*/llvm::None, + check_inlines, exact_match); + + if (!location_spec) { + llvm::errs() << llvm::toString(location_spec.takeError()) << "\n"; + return 0; + } + + symbols->ResolveSymbolContext(*location_spec, resolve_scope, sc_list); + } return sc_list.GetSize() - initial_count; } @@ -917,7 +928,20 @@ std::vector
&output_local, std::vector
&output_extern) { SearchFilterByModule filter(target_sp, m_file); - AddressResolverFileLine resolver(file, line, true); + + // TODO: Handle SourceLocationSpec column information + const llvm::Optional column = llvm::None; + const bool check_inlines = true; + const bool exact_match = false; + auto location_spec = SourceLocationSpec::Create(file, line, column, + check_inlines, exact_match); + + if (!location_spec) { + llvm::errs() << llvm::toString(location_spec.takeError()) << "\n"; + return; + } + + AddressResolverFileLine resolver(*location_spec); resolver.ResolveAddress(filter); for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) { diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -101,8 +101,7 @@ lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override; - uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, - bool check_inlines, + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -278,7 +278,7 @@ } uint32_t SymbolFileBreakpad::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard guard(GetModuleMutex()); if (!(resolve_scope & eSymbolContextCompUnit)) @@ -287,8 +287,7 @@ uint32_t old_size = sc_list.GetSize(); for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { CompileUnit &cu = *GetCompileUnitAtIndex(i); - cu.ResolveSymbolContext(file_spec, line, check_inlines, - /*exact*/ false, resolve_scope, sc_list); + cu.ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); } return sc_list.GetSize() - old_size; } @@ -716,10 +715,10 @@ llvm::Optional next_addr; auto finish_sequence = [&]() { LineTable::AppendLineEntryToSequence( - line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0, - /*file_idx*/ 0, /*is_start_of_statement*/ false, - /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, - /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true); + line_seq_up.get(), *next_addr, /*line=*/0, /*column=*/0, + /*file_idx=*/0, /*is_start_of_statement=*/false, + /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false, + /*is_epilogue_begin=*/false, /*is_terminal_entry=*/true); sequences.push_back(std::move(line_seq_up)); line_seq_up = LineTable::CreateLineSequenceContainer(); }; @@ -739,10 +738,10 @@ finish_sequence(); } LineTable::AppendLineEntryToSequence( - line_seq_up.get(), record->Address, record->LineNum, /*column*/ 0, - map[record->FileNum], /*is_start_of_statement*/ true, - /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, - /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false); + line_seq_up.get(), record->Address, record->LineNum, /*column=*/0, + map[record->FileNum], /*is_start_of_statement=*/true, + /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false, + /*is_epilogue_begin=*/false, /*is_terminal_entry=*/false); next_addr = record->Address + record->Size; } if (next_addr) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -161,11 +161,10 @@ lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1959,12 +1959,11 @@ return resolved; } -uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, - bool check_inlines, - SymbolContextItem resolve_scope, - SymbolContextList &sc_list) { +uint32_t SymbolFileDWARF::ResolveSymbolContext( + const SourceLocationSpec &src_location_spec, + SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard guard(GetModuleMutex()); + const bool check_inlines = src_location_spec.GetCheckInlines(); const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; @@ -1973,11 +1972,10 @@ if (!dc_cu) continue; - bool file_spec_matches_cu_file_spec = - FileSpec::Match(file_spec, dc_cu->GetPrimaryFile()); + bool file_spec_matches_cu_file_spec = FileSpec::Match( + src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile()); if (check_inlines || file_spec_matches_cu_file_spec) { - dc_cu->ResolveSymbolContext(file_spec, line, check_inlines, false, - resolve_scope, sc_list); + dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); if (!check_inlines) break; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -97,11 +97,10 @@ uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext &parent_decl_ctx, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -806,7 +806,7 @@ } uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard guard(GetModuleMutex()); const uint32_t initial = sc_list.GetSize(); @@ -815,18 +815,19 @@ for (uint32_t i = 0; i < cu_count; ++i) { // If we are checking for inlines, then we need to look through all compile // units no matter if "file_spec" matches. - bool resolve = check_inlines; + bool resolve = src_location_spec.GetCheckInlines(); if (!resolve) { FileSpec so_file_spec; if (GetFileSpecForSO(i, so_file_spec)) - resolve = FileSpec::Match(file_spec, so_file_spec); + resolve = + FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec); } if (resolve) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i); if (oso_dwarf) - oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines, - resolve_scope, sc_list); + oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope, + sc_list); } } return sc_list.GetSize() - initial; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -120,8 +120,7 @@ uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override; - uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, - bool check_inlines, + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1001,7 +1001,7 @@ } uint32_t SymbolFileNativePDB::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { return 0; } diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -104,11 +104,10 @@ lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -784,10 +784,12 @@ } uint32_t SymbolFilePDB::ResolveSymbolContext( - const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, + const lldb_private::SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { std::lock_guard guard(GetModuleMutex()); const size_t old_size = sc_list.GetSize(); + const FileSpec &file_spec = src_location_spec.GetFileSpec(); + const uint32_t line = src_location_spec.GetLine(); if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified // file. For example, if `file_spec` is , then this should return @@ -806,7 +808,7 @@ // this file unless the FileSpec matches. For inline functions, we don't // have to match the FileSpec since they could be defined in headers // other than file specified in FileSpec. - if (!check_inlines) { + if (!src_location_spec.GetCheckInlines()) { std::string source_file = compiland->getSourceFileFullPath(); if (source_file.empty()) continue; diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -224,18 +224,31 @@ if (file_indexes.empty()) return UINT32_MAX; + // TODO: Handle SourceLocationSpec column information + const llvm::Optional column = llvm::None; + const bool inlined = false; + auto location_spec = + SourceLocationSpec::Create(*file_spec_ptr, line, column, inlined, exact); + + if (!location_spec) { + llvm::errs() << llvm::toString(location_spec.takeError()) << "\n"; + return UINT32_MAX; + } + LineTable *line_table = GetLineTable(); if (line_table) return line_table->FindLineEntryIndexByFileIndex( - start_idx, file_indexes, line, exact, line_entry_ptr); + start_idx, file_indexes, *location_spec, line_entry_ptr); return UINT32_MAX; } -void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, bool check_inlines, - bool exact, - SymbolContextItem resolve_scope, - SymbolContextList &sc_list) { +void CompileUnit::ResolveSymbolContext( + const SourceLocationSpec &src_location_spec, + SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + const FileSpec file_spec = src_location_spec.GetFileSpec(); + const uint32_t line = src_location_spec.GetLine(); + const bool check_inlines = src_location_spec.GetCheckInlines(); + // First find all of the file indexes that match our "file_spec". If // "file_spec" has an empty directory, then only compare the basenames when // finding file indexes @@ -288,21 +301,25 @@ // table function that searches for a line entries that match a single // support file index line_idx = line_table->FindLineEntryIndexByFileIndex( - 0, file_indexes.front(), line, exact, &line_entry); + 0, file_indexes.front(), src_location_spec, &line_entry); } else { // We found multiple support files that match "file_spec" so use the // line table function that searches for a line entries that match a // multiple support file indexes. - line_idx = line_table->FindLineEntryIndexByFileIndex(0, file_indexes, line, - exact, &line_entry); + line_idx = line_table->FindLineEntryIndexByFileIndex( + 0, file_indexes, src_location_spec, &line_entry); } // If "exact == true", then "found_line" will be the same as "line". If // "exact == false", the "found_line" will be the closest line entry // with a line number greater than "line" and we will use this for our // subsequent line exact matches below. - uint32_t found_line = line_entry.line; - + const bool inlines = false; + const bool exact = true; + auto found_entry = SourceLocationSpec::Create( + line_entry.file, line_entry.line, line_entry.column, inlines, exact); + lldbassert(found_entry && "Invalid SourceLocationSpec."); + while (line_idx != UINT32_MAX) { // If they only asked for the line entry, then we're done, we can // just copy that over. But if they wanted more than just the line @@ -317,10 +334,10 @@ sc_list.Append(sc); if (num_file_indexes == 1) line_idx = line_table->FindLineEntryIndexByFileIndex( - line_idx + 1, file_indexes.front(), found_line, true, &line_entry); + line_idx + 1, file_indexes.front(), *found_entry, &line_entry); else line_idx = line_table->FindLineEntryIndexByFileIndex( - line_idx + 1, file_indexes, found_line, true, &line_entry); + line_idx + 1, file_indexes, *found_entry, &line_entry); } } diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -304,7 +304,7 @@ uint32_t LineTable::FindLineEntryIndexByFileIndex( uint32_t start_idx, const std::vector &file_indexes, - uint32_t line, bool exact, LineEntry *line_entry_ptr) { + const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) { const size_t count = m_entries.size(); size_t best_match = UINT32_MAX; @@ -324,13 +324,15 @@ // after and // if they're not in the same function, don't return a match. + uint32_t line = src_location_spec.GetLine(); + if (m_entries[idx].line < line) { continue; } else if (m_entries[idx].line == line) { if (line_entry_ptr) ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); return idx; - } else if (!exact) { + } else if (!src_location_spec.GetExactMatch()) { if (best_match == UINT32_MAX) best_match = idx; else if (m_entries[idx].line < m_entries[best_match].line) @@ -346,10 +348,9 @@ return UINT32_MAX; } -uint32_t LineTable::FindLineEntryIndexByFileIndex(uint32_t start_idx, - uint32_t file_idx, - uint32_t line, bool exact, - LineEntry *line_entry_ptr) { +uint32_t LineTable::FindLineEntryIndexByFileIndex( + uint32_t start_idx, uint32_t file_idx, + const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) { const size_t count = m_entries.size(); size_t best_match = UINT32_MAX; @@ -368,13 +369,15 @@ // after and // if they're not in the same function, don't return a match. + uint32_t line = src_location_spec.GetLine(); + if (m_entries[idx].line < line) { continue; } else if (m_entries[idx].line == line) { if (line_entry_ptr) ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); return idx; - } else if (!exact) { + } else if (!src_location_spec.GetExactMatch()) { if (best_match == UINT32_MAX) best_match = idx; else if (m_entries[idx].line < m_entries[best_match].line) diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -97,10 +97,10 @@ return type_system_or_err; } -uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, bool check_inlines, - lldb::SymbolContextItem resolve_scope, - SymbolContextList &sc_list) { +uint32_t +SymbolFile::ResolveSymbolContext(const SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + SymbolContextList &sc_list) { return 0; } diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -371,9 +371,16 @@ if (move_to_nearest_code == eLazyBoolCalculate) move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo; + auto location_spec = + SourceLocationSpec::Create(remapped_file, line_no, column, check_inlines, + !static_cast(move_to_nearest_code)); + if (!location_spec) { + llvm::errs() << llvm::toString(location_spec.takeError()) << "\n"; + return nullptr; + } + BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine( - nullptr, remapped_file, line_no, column, offset, check_inlines, - skip_prologue, !static_cast(move_to_nearest_code))); + nullptr, offset, skip_prologue, *location_spec)); return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true); } diff --git a/lldb/source/Utility/SourceLocationSpec.cpp b/lldb/source/Utility/SourceLocationSpec.cpp --- a/lldb/source/Utility/SourceLocationSpec.cpp +++ b/lldb/source/Utility/SourceLocationSpec.cpp @@ -22,12 +22,7 @@ if (!file_spec) return llvm::createStringError( llvm::errc::invalid_argument, - "SourceLocationSpec requires a valid FileSpec."); - - if (!line || line == LLDB_INVALID_LINE_NUMBER) - return llvm::createStringError( - llvm::errc::invalid_argument, - "SourceLocationSpec requires a valid line number."); + "Invalid source location spec. Requires a valid file spec."); return SourceLocationSpec(file_spec, line, column, check_inlines, exact_match); diff --git a/lldb/unittests/Symbol/TestLineEntry.cpp b/lldb/unittests/Symbol/TestLineEntry.cpp --- a/lldb/unittests/Symbol/TestLineEntry.cpp +++ b/lldb/unittests/Symbol/TestLineEntry.cpp @@ -53,8 +53,10 @@ } llvm::Expected LineEntryTest::GetLineEntryForLine(uint32_t line) { - bool check_inlines = true; - bool exact = true; + // TODO: Handle SourceLocationSpec column information + const llvm::Optional column = llvm::None; + const bool check_inlines = true; + const bool exact_match = true; SymbolContextList sc_comp_units; SymbolContextList sc_line_entries; FileSpec file_spec("inlined-functions.cpp"); @@ -64,9 +66,14 @@ if (sc_comp_units.GetSize() == 0) return llvm::createStringError(llvm::inconvertibleErrorCode(), "No comp unit found on the test object."); + + auto location_spec = SourceLocationSpec::Create(file_spec, line, column, + check_inlines, exact_match); + if (!location_spec) + return location_spec.takeError(); + sc_comp_units[0].comp_unit->ResolveSymbolContext( - file_spec, line, check_inlines, exact, eSymbolContextLineEntry, - sc_line_entries); + *location_spec, eSymbolContextLineEntry, sc_line_entries); if (sc_line_entries.GetSize() == 0) return llvm::createStringError(llvm::inconvertibleErrorCode(), "No line entry found on the test object.");