130fdc8d8SChris Lattner //===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointResolverFileLine.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 1730fdc8d8SChris Lattner #include "lldb/Core/Log.h" 181f746071SGreg Clayton #include "lldb/Core/Module.h" 1930fdc8d8SChris Lattner #include "lldb/Core/StreamString.h" 201f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 211f746071SGreg Clayton #include "lldb/Symbol/Function.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb; 2430fdc8d8SChris Lattner using namespace lldb_private; 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner //---------------------------------------------------------------------- 2730fdc8d8SChris Lattner // BreakpointResolverFileLine: 2830fdc8d8SChris Lattner //---------------------------------------------------------------------- 29b9c1b51eSKate Stone BreakpointResolverFileLine::BreakpointResolverFileLine( 30b9c1b51eSKate Stone Breakpoint *bkpt, const FileSpec &file_spec, uint32_t line_no, 31b9c1b51eSKate Stone lldb::addr_t offset, bool check_inlines, bool skip_prologue, 32b9c1b51eSKate Stone bool exact_match) 33b9c1b51eSKate Stone : BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset), 34b9c1b51eSKate Stone m_file_spec(file_spec), m_line_number(line_no), m_inlines(check_inlines), 35b9c1b51eSKate Stone m_skip_prologue(skip_prologue), m_exact_match(exact_match) {} 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone BreakpointResolverFileLine::~BreakpointResolverFileLine() {} 3830fdc8d8SChris Lattner 39e14dc268SJim Ingham BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( 401a81b273SJim Ingham Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, 411a81b273SJim Ingham Error &error) { 42e14dc268SJim Ingham std::string filename; 43e14dc268SJim Ingham uint32_t line_no; 44e14dc268SJim Ingham bool check_inlines; 45e14dc268SJim Ingham bool skip_prologue; 46e14dc268SJim Ingham bool exact_match; 47e14dc268SJim Ingham bool success; 48e14dc268SJim Ingham 49e14dc268SJim Ingham lldb::addr_t offset = 0; 50e14dc268SJim Ingham 51e14dc268SJim Ingham success = options_dict.GetValueForKeyAsString(GetKey(OptionNames::FileName), 52e14dc268SJim Ingham filename); 53e14dc268SJim Ingham if (!success) { 54e14dc268SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find filename entry."); 55e14dc268SJim Ingham return nullptr; 56e14dc268SJim Ingham } 57e14dc268SJim Ingham 58e14dc268SJim Ingham success = options_dict.GetValueForKeyAsInteger( 59e14dc268SJim Ingham GetKey(OptionNames::LineNumber), line_no); 60e14dc268SJim Ingham if (!success) { 61e14dc268SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find line number entry."); 62e14dc268SJim Ingham return nullptr; 63e14dc268SJim Ingham } 64e14dc268SJim Ingham 65e14dc268SJim Ingham success = options_dict.GetValueForKeyAsBoolean(GetKey(OptionNames::Inlines), 66e14dc268SJim Ingham check_inlines); 67e14dc268SJim Ingham if (!success) { 68e14dc268SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find check inlines entry."); 69e14dc268SJim Ingham return nullptr; 70e14dc268SJim Ingham } 71e14dc268SJim Ingham 72e14dc268SJim Ingham success = options_dict.GetValueForKeyAsBoolean( 73e14dc268SJim Ingham GetKey(OptionNames::SkipPrologue), skip_prologue); 74e14dc268SJim Ingham if (!success) { 75e14dc268SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find skip prologue entry."); 76e14dc268SJim Ingham return nullptr; 77e14dc268SJim Ingham } 78e14dc268SJim Ingham 79e14dc268SJim Ingham success = options_dict.GetValueForKeyAsBoolean( 80e14dc268SJim Ingham GetKey(OptionNames::ExactMatch), exact_match); 81e14dc268SJim Ingham if (!success) { 82e14dc268SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry."); 83e14dc268SJim Ingham return nullptr; 84e14dc268SJim Ingham } 85e14dc268SJim Ingham 86*771ef6d4SMalcolm Parsons FileSpec file_spec(filename, false); 87e14dc268SJim Ingham 88e14dc268SJim Ingham return new BreakpointResolverFileLine(bkpt, file_spec, line_no, offset, 89e14dc268SJim Ingham check_inlines, skip_prologue, 90e14dc268SJim Ingham exact_match); 91e14dc268SJim Ingham } 92e14dc268SJim Ingham 93e14dc268SJim Ingham StructuredData::ObjectSP 94e14dc268SJim Ingham BreakpointResolverFileLine::SerializeToStructuredData() { 95e14dc268SJim Ingham StructuredData::DictionarySP options_dict_sp( 96e14dc268SJim Ingham new StructuredData::Dictionary()); 97e14dc268SJim Ingham 98e14dc268SJim Ingham options_dict_sp->AddStringItem(GetKey(OptionNames::FileName), 99e14dc268SJim Ingham m_file_spec.GetPath()); 100e14dc268SJim Ingham options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber), 101e14dc268SJim Ingham m_line_number); 102e14dc268SJim Ingham options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines); 103e14dc268SJim Ingham options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue), 104e14dc268SJim Ingham m_skip_prologue); 105e14dc268SJim Ingham options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch), 106e14dc268SJim Ingham m_exact_match); 107e14dc268SJim Ingham 108e14dc268SJim Ingham return WrapOptionsDict(options_dict_sp); 109e14dc268SJim Ingham } 110e14dc268SJim Ingham 11130fdc8d8SChris Lattner Searcher::CallbackReturn 112b9c1b51eSKate Stone BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, 11330fdc8d8SChris Lattner SymbolContext &context, 114b9c1b51eSKate Stone Address *addr, bool containing) { 11530fdc8d8SChris Lattner SymbolContextList sc_list; 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner assert(m_breakpoint != NULL); 11830fdc8d8SChris Lattner 119b9c1b51eSKate Stone // There is a tricky bit here. You can have two compilation units that 120b9c1b51eSKate Stone // #include the same file, and 121b9c1b51eSKate Stone // in one of them the function at m_line_number is used (and so code and a 122b9c1b51eSKate Stone // line entry for it is generated) but in the 123b9c1b51eSKate Stone // other it isn't. If we considered the CU's independently, then in the 124b9c1b51eSKate Stone // second inclusion, we'd move the breakpoint 125b9c1b51eSKate Stone // to the next function that actually generated code in the header file. That 126b9c1b51eSKate Stone // would end up being confusing. 127b9c1b51eSKate Stone // So instead, we do the CU iterations by hand here, then scan through the 128b9c1b51eSKate Stone // complete list of matches, and figure out 129bc2f9182SJim Ingham // the closest line number match, and only set breakpoints on that match. 130bc2f9182SJim Ingham 131b9c1b51eSKate Stone // Note also that if file_spec only had a file name and not a directory, there 132b9c1b51eSKate Stone // may be many different file spec's in 133b9c1b51eSKate Stone // the resultant list. The closest line match for one will not be right for 134b9c1b51eSKate Stone // some totally different file. 135b9c1b51eSKate Stone // So we go through the match list and pull out the sets that have the same 136b9c1b51eSKate Stone // file spec in their line_entry 137bc2f9182SJim Ingham // and treat each set separately. 138bc2f9182SJim Ingham 139c7bece56SGreg Clayton const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); 140b9c1b51eSKate Stone for (size_t i = 0; i < num_comp_units; i++) { 141bc2f9182SJim Ingham CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); 142b9c1b51eSKate Stone if (cu_sp) { 1432dafd8edSGreg Clayton if (filter.CompUnitPasses(*cu_sp)) 144b9c1b51eSKate Stone cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, 145b9c1b51eSKate Stone m_exact_match, eSymbolContextEverything, 146b9c1b51eSKate Stone sc_list); 147bc2f9182SJim Ingham } 1482dafd8edSGreg Clayton } 14930fdc8d8SChris Lattner StreamString s; 150b9c1b51eSKate Stone s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"), 151969795f1SJim Ingham m_line_number); 152f642373cSJim Ingham 15395eae423SZachary Turner SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString()); 154bc2f9182SJim Ingham 15530fdc8d8SChris Lattner return Searcher::eCallbackReturnContinue; 15630fdc8d8SChris Lattner } 15730fdc8d8SChris Lattner 158b9c1b51eSKate Stone Searcher::Depth BreakpointResolverFileLine::GetDepth() { 159bc2f9182SJim Ingham return Searcher::eDepthModule; 16030fdc8d8SChris Lattner } 16130fdc8d8SChris Lattner 162b9c1b51eSKate Stone void BreakpointResolverFileLine::GetDescription(Stream *s) { 163b9c1b51eSKate Stone s->Printf("file = '%s', line = %u, exact_match = %d", 164b9c1b51eSKate Stone m_file_spec.GetPath().c_str(), m_line_number, m_exact_match); 16530fdc8d8SChris Lattner } 16630fdc8d8SChris Lattner 167b9c1b51eSKate Stone void BreakpointResolverFileLine::Dump(Stream *s) const {} 16830fdc8d8SChris Lattner 16933df7cd3SJim Ingham lldb::BreakpointResolverSP 170b9c1b51eSKate Stone BreakpointResolverFileLine::CopyForBreakpoint(Breakpoint &breakpoint) { 171b9c1b51eSKate Stone lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine( 172b9c1b51eSKate Stone &breakpoint, m_file_spec, m_line_number, m_offset, m_inlines, 173b9c1b51eSKate Stone m_skip_prologue, m_exact_match)); 17433df7cd3SJim Ingham 17533df7cd3SJim Ingham return ret_sp; 17633df7cd3SJim Ingham } 177