1 //===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Breakpoint/BreakpointResolverFileLine.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/BreakpointLocation.h" 17 #include "lldb/Core/Log.h" 18 #include "lldb/Core/Module.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Symbol/CompileUnit.h" 21 #include "lldb/Symbol/Function.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 //---------------------------------------------------------------------- 27 // BreakpointResolverFileLine: 28 //---------------------------------------------------------------------- 29 BreakpointResolverFileLine::BreakpointResolverFileLine( 30 Breakpoint *bkpt, const FileSpec &file_spec, uint32_t line_no, 31 lldb::addr_t offset, bool check_inlines, bool skip_prologue, 32 bool exact_match) 33 : BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset), 34 m_file_spec(file_spec), m_line_number(line_no), m_inlines(check_inlines), 35 m_skip_prologue(skip_prologue), m_exact_match(exact_match) {} 36 37 BreakpointResolverFileLine::~BreakpointResolverFileLine() {} 38 39 BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( 40 Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, 41 Error &error) { 42 std::string filename; 43 uint32_t line_no; 44 bool check_inlines; 45 bool skip_prologue; 46 bool exact_match; 47 bool success; 48 49 lldb::addr_t offset = 0; 50 51 success = options_dict.GetValueForKeyAsString(GetKey(OptionNames::FileName), 52 filename); 53 if (!success) { 54 error.SetErrorString("BRFL::CFSD: Couldn't find filename entry."); 55 return nullptr; 56 } 57 58 success = options_dict.GetValueForKeyAsInteger( 59 GetKey(OptionNames::LineNumber), line_no); 60 if (!success) { 61 error.SetErrorString("BRFL::CFSD: Couldn't find line number entry."); 62 return nullptr; 63 } 64 65 success = options_dict.GetValueForKeyAsBoolean(GetKey(OptionNames::Inlines), 66 check_inlines); 67 if (!success) { 68 error.SetErrorString("BRFL::CFSD: Couldn't find check inlines entry."); 69 return nullptr; 70 } 71 72 success = options_dict.GetValueForKeyAsBoolean( 73 GetKey(OptionNames::SkipPrologue), skip_prologue); 74 if (!success) { 75 error.SetErrorString("BRFL::CFSD: Couldn't find skip prologue entry."); 76 return nullptr; 77 } 78 79 success = options_dict.GetValueForKeyAsBoolean( 80 GetKey(OptionNames::ExactMatch), exact_match); 81 if (!success) { 82 error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry."); 83 return nullptr; 84 } 85 86 FileSpec file_spec(filename, false); 87 88 return new BreakpointResolverFileLine(bkpt, file_spec, line_no, offset, 89 check_inlines, skip_prologue, 90 exact_match); 91 } 92 93 StructuredData::ObjectSP 94 BreakpointResolverFileLine::SerializeToStructuredData() { 95 StructuredData::DictionarySP options_dict_sp( 96 new StructuredData::Dictionary()); 97 98 options_dict_sp->AddStringItem(GetKey(OptionNames::FileName), 99 m_file_spec.GetPath()); 100 options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber), 101 m_line_number); 102 options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines); 103 options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue), 104 m_skip_prologue); 105 options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch), 106 m_exact_match); 107 108 return WrapOptionsDict(options_dict_sp); 109 } 110 111 Searcher::CallbackReturn 112 BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, 113 SymbolContext &context, 114 Address *addr, bool containing) { 115 SymbolContextList sc_list; 116 117 assert(m_breakpoint != NULL); 118 119 // There is a tricky bit here. You can have two compilation units that 120 // #include the same file, and 121 // in one of them the function at m_line_number is used (and so code and a 122 // line entry for it is generated) but in the 123 // other it isn't. If we considered the CU's independently, then in the 124 // second inclusion, we'd move the breakpoint 125 // to the next function that actually generated code in the header file. That 126 // would end up being confusing. 127 // So instead, we do the CU iterations by hand here, then scan through the 128 // complete list of matches, and figure out 129 // the closest line number match, and only set breakpoints on that match. 130 131 // Note also that if file_spec only had a file name and not a directory, there 132 // may be many different file spec's in 133 // the resultant list. The closest line match for one will not be right for 134 // some totally different file. 135 // So we go through the match list and pull out the sets that have the same 136 // file spec in their line_entry 137 // and treat each set separately. 138 139 const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); 140 for (size_t i = 0; i < num_comp_units; i++) { 141 CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); 142 if (cu_sp) { 143 if (filter.CompUnitPasses(*cu_sp)) 144 cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, 145 m_exact_match, eSymbolContextEverything, 146 sc_list); 147 } 148 } 149 StreamString s; 150 s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"), 151 m_line_number); 152 153 SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString()); 154 155 return Searcher::eCallbackReturnContinue; 156 } 157 158 Searcher::Depth BreakpointResolverFileLine::GetDepth() { 159 return Searcher::eDepthModule; 160 } 161 162 void BreakpointResolverFileLine::GetDescription(Stream *s) { 163 s->Printf("file = '%s', line = %u, exact_match = %d", 164 m_file_spec.GetPath().c_str(), m_line_number, m_exact_match); 165 } 166 167 void BreakpointResolverFileLine::Dump(Stream *s) const {} 168 169 lldb::BreakpointResolverSP 170 BreakpointResolverFileLine::CopyForBreakpoint(Breakpoint &breakpoint) { 171 lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine( 172 &breakpoint, m_file_spec, m_line_number, m_offset, m_inlines, 173 m_skip_prologue, m_exact_match)); 174 175 return ret_sp; 176 } 177