1 //===-- LineEntry.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/Symbol/LineEntry.h" 11 #include "lldb/Symbol/CompileUnit.h" 12 #include "lldb/Target/Process.h" 13 #include "lldb/Target/Target.h" 14 15 using namespace lldb_private; 16 17 LineEntry::LineEntry() : 18 range(), 19 file(), 20 line(LLDB_INVALID_LINE_NUMBER), 21 column(0), 22 is_start_of_statement(0), 23 is_start_of_basic_block(0), 24 is_prologue_end(0), 25 is_epilogue_begin(0), 26 is_terminal_entry(0) 27 { 28 } 29 30 LineEntry::LineEntry 31 ( 32 const lldb::SectionSP §ion_sp, 33 lldb::addr_t section_offset, 34 lldb::addr_t byte_size, 35 const FileSpec &_file, 36 uint32_t _line, 37 uint16_t _column, 38 bool _is_start_of_statement, 39 bool _is_start_of_basic_block, 40 bool _is_prologue_end, 41 bool _is_epilogue_begin, 42 bool _is_terminal_entry 43 ) : 44 range(section_sp, section_offset, byte_size), 45 file(_file), 46 original_file(_file), 47 line(_line), 48 column(_column), 49 is_start_of_statement(_is_start_of_statement), 50 is_start_of_basic_block(_is_start_of_basic_block), 51 is_prologue_end(_is_prologue_end), 52 is_epilogue_begin(_is_epilogue_begin), 53 is_terminal_entry(_is_terminal_entry) 54 { 55 } 56 57 void 58 LineEntry::Clear() 59 { 60 range.Clear(); 61 file.Clear(); 62 original_file.Clear(); 63 line = LLDB_INVALID_LINE_NUMBER; 64 column = 0; 65 is_start_of_statement = 0; 66 is_start_of_basic_block = 0; 67 is_prologue_end = 0; 68 is_epilogue_begin = 0; 69 is_terminal_entry = 0; 70 } 71 72 73 bool 74 LineEntry::IsValid() const 75 { 76 return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER; 77 } 78 79 bool 80 LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const 81 { 82 bool result = false; 83 if (file) 84 { 85 if (show_fullpaths) 86 file.Dump (s); 87 else 88 file.GetFilename().Dump (s); 89 90 if (line) 91 s->PutChar(':'); 92 result = true; 93 } 94 if (line) 95 s->Printf ("%u", line); 96 else 97 result = false; 98 99 return result; 100 } 101 102 bool 103 LineEntry::Dump 104 ( 105 Stream *s, 106 Target *target, 107 bool show_file, 108 Address::DumpStyle style, 109 Address::DumpStyle fallback_style, 110 bool show_range 111 ) const 112 { 113 if (show_range) 114 { 115 // Show address range 116 if (!range.Dump(s, target, style, fallback_style)) 117 return false; 118 } 119 else 120 { 121 // Show address only 122 if (!range.GetBaseAddress().Dump(s, 123 target, 124 style, 125 fallback_style)) 126 return false; 127 } 128 if (show_file) 129 *s << ", file = " << file; 130 if (line) 131 s->Printf(", line = %u", line); 132 if (column) 133 s->Printf(", column = %u", column); 134 if (is_start_of_statement) 135 *s << ", is_start_of_statement = TRUE"; 136 137 if (is_start_of_basic_block) 138 *s << ", is_start_of_basic_block = TRUE"; 139 140 if (is_prologue_end) 141 *s << ", is_prologue_end = TRUE"; 142 143 if (is_epilogue_begin) 144 *s << ", is_epilogue_begin = TRUE"; 145 146 if (is_terminal_entry) 147 *s << ", is_terminal_entry = TRUE"; 148 return true; 149 } 150 151 bool 152 LineEntry::GetDescription (Stream *s, lldb::DescriptionLevel level, CompileUnit* cu, Target *target, bool show_address_only) const 153 { 154 155 if (level == lldb::eDescriptionLevelBrief || level == lldb::eDescriptionLevelFull) 156 { 157 if (show_address_only) 158 { 159 range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 160 } 161 else 162 { 163 range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 164 } 165 166 *s << ": " << file; 167 168 if (line) 169 { 170 s->Printf(":%u", line); 171 if (column) 172 s->Printf(":%u", column); 173 } 174 175 176 if (level == lldb::eDescriptionLevelFull) 177 { 178 if (is_start_of_statement) 179 *s << ", is_start_of_statement = TRUE"; 180 181 if (is_start_of_basic_block) 182 *s << ", is_start_of_basic_block = TRUE"; 183 184 if (is_prologue_end) 185 *s << ", is_prologue_end = TRUE"; 186 187 if (is_epilogue_begin) 188 *s << ", is_epilogue_begin = TRUE"; 189 190 if (is_terminal_entry) 191 *s << ", is_terminal_entry = TRUE"; 192 } 193 else 194 { 195 if (is_terminal_entry) 196 s->EOL(); 197 } 198 } 199 else 200 { 201 return Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true); 202 } 203 return true; 204 } 205 206 207 bool 208 lldb_private::operator< (const LineEntry& a, const LineEntry& b) 209 { 210 return LineEntry::Compare (a, b) < 0; 211 } 212 213 int 214 LineEntry::Compare (const LineEntry& a, const LineEntry& b) 215 { 216 int result = Address::CompareFileAddress (a.range.GetBaseAddress(), b.range.GetBaseAddress()); 217 if (result != 0) 218 return result; 219 220 const lldb::addr_t a_byte_size = a.range.GetByteSize(); 221 const lldb::addr_t b_byte_size = b.range.GetByteSize(); 222 223 if (a_byte_size < b_byte_size) 224 return -1; 225 if (a_byte_size > b_byte_size) 226 return +1; 227 228 // Check for an end sequence entry mismatch after we have determined 229 // that the address values are equal. If one of the items is an end 230 // sequence, we don't care about the line, file, or column info. 231 if (a.is_terminal_entry > b.is_terminal_entry) 232 return -1; 233 if (a.is_terminal_entry < b.is_terminal_entry) 234 return +1; 235 236 if (a.line < b.line) 237 return -1; 238 if (a.line > b.line) 239 return +1; 240 241 if (a.column < b.column) 242 return -1; 243 if (a.column > b.column) 244 return +1; 245 246 return FileSpec::Compare (a.file, b.file, true); 247 } 248 249 AddressRange 250 LineEntry::GetSameLineContiguousAddressRange () const 251 { 252 // Add each LineEntry's range to complete_line_range until we find 253 // a different file / line number. 254 AddressRange complete_line_range = range; 255 256 while (true) 257 { 258 SymbolContext next_line_sc; 259 Address range_end (complete_line_range.GetBaseAddress()); 260 range_end.Slide (complete_line_range.GetByteSize()); 261 range_end.CalculateSymbolContext (&next_line_sc, lldb::eSymbolContextLineEntry); 262 263 if (next_line_sc.line_entry.IsValid() 264 && next_line_sc.line_entry.range.GetByteSize() > 0 265 && original_file == next_line_sc.line_entry.original_file) 266 { 267 // Include any line 0 entries - they indicate that this is compiler-generated code 268 // that does not correspond to user source code. 269 if (next_line_sc.line_entry.line == 0) 270 { 271 complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize()); 272 continue; 273 } 274 275 if (line == next_line_sc.line_entry.line) 276 { 277 // next_line_sc is the same file & line as this LineEntry, so extend our 278 // AddressRange by its size and continue to see if there are more LineEntries 279 // that we can combine. 280 complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize()); 281 continue; 282 } 283 } 284 break; 285 } 286 return complete_line_range; 287 } 288 289 void 290 LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) 291 { 292 if (target_sp) 293 { 294 // Apply any file remappings to our file 295 FileSpec new_file_spec; 296 if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec)) 297 file = new_file_spec; 298 } 299 } 300