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