1283625Sdim//===-- DWARFDebugLine.cpp ------------------------------------------------===// 2283625Sdim// 3283625Sdim// The LLVM Compiler Infrastructure 4283625Sdim// 5283625Sdim// This file is distributed under the University of Illinois Open Source 6283625Sdim// License. See LICENSE.TXT for details. 7283625Sdim// 8283625Sdim//===----------------------------------------------------------------------===// 9283625Sdim 10283625Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 11283625Sdim#include "llvm/Support/Dwarf.h" 12283625Sdim#include "llvm/Support/Format.h" 13283625Sdim#include "llvm/Support/Path.h" 14283625Sdim#include "llvm/Support/raw_ostream.h" 15283625Sdim#include <algorithm> 16283625Sdimusing namespace llvm; 17283625Sdimusing namespace dwarf; 18283625Sdimtypedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; 19283625Sdim 20283625SdimDWARFDebugLine::Prologue::Prologue() { 21283625Sdim clear(); 22283625Sdim} 23283625Sdim 24283625Sdimvoid DWARFDebugLine::Prologue::clear() { 25283625Sdim TotalLength = Version = PrologueLength = 0; 26283625Sdim MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; 27283625Sdim OpcodeBase = 0; 28284236Sdim IsDWARF64 = false; 29283625Sdim StandardOpcodeLengths.clear(); 30283625Sdim IncludeDirectories.clear(); 31283625Sdim FileNames.clear(); 32283625Sdim} 33283625Sdim 34283625Sdimvoid DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { 35283625Sdim OS << "Line table prologue:\n" 36284236Sdim << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength) 37283625Sdim << format(" version: %u\n", Version) 38284236Sdim << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength) 39283625Sdim << format(" min_inst_length: %u\n", MinInstLength) 40283625Sdim << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst) 41283625Sdim << format(" default_is_stmt: %u\n", DefaultIsStmt) 42283625Sdim << format(" line_base: %i\n", LineBase) 43283625Sdim << format(" line_range: %u\n", LineRange) 44283625Sdim << format(" opcode_base: %u\n", OpcodeBase); 45283625Sdim 46283625Sdim for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i) 47283625Sdim OS << format("standard_opcode_lengths[%s] = %u\n", LNStandardString(i+1), 48283625Sdim StandardOpcodeLengths[i]); 49283625Sdim 50283625Sdim if (!IncludeDirectories.empty()) 51283625Sdim for (uint32_t i = 0; i < IncludeDirectories.size(); ++i) 52283625Sdim OS << format("include_directories[%3u] = '", i+1) 53283625Sdim << IncludeDirectories[i] << "'\n"; 54283625Sdim 55283625Sdim if (!FileNames.empty()) { 56283625Sdim OS << " Dir Mod Time File Len File Name\n" 57283625Sdim << " ---- ---------- ---------- -----------" 58283625Sdim "----------------\n"; 59283625Sdim for (uint32_t i = 0; i < FileNames.size(); ++i) { 60283625Sdim const FileNameEntry& fileEntry = FileNames[i]; 61283625Sdim OS << format("file_names[%3u] %4" PRIu64 " ", i+1, fileEntry.DirIdx) 62283625Sdim << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ", 63283625Sdim fileEntry.ModTime, fileEntry.Length) 64283625Sdim << fileEntry.Name << '\n'; 65283625Sdim } 66283625Sdim } 67283625Sdim} 68283625Sdim 69283625Sdimbool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data, 70283625Sdim uint32_t *offset_ptr) { 71284236Sdim const uint64_t prologue_offset = *offset_ptr; 72283625Sdim 73283625Sdim clear(); 74283625Sdim TotalLength = debug_line_data.getU32(offset_ptr); 75284236Sdim if (TotalLength == UINT32_MAX) { 76284236Sdim IsDWARF64 = true; 77284236Sdim TotalLength = debug_line_data.getU64(offset_ptr); 78284236Sdim } else if (TotalLength > 0xffffff00) { 79284236Sdim return false; 80284236Sdim } 81283625Sdim Version = debug_line_data.getU16(offset_ptr); 82283625Sdim if (Version < 2) 83283625Sdim return false; 84283625Sdim 85284236Sdim PrologueLength = debug_line_data.getUnsigned(offset_ptr, 86284236Sdim sizeofPrologueLength()); 87284236Sdim const uint64_t end_prologue_offset = PrologueLength + *offset_ptr; 88283625Sdim MinInstLength = debug_line_data.getU8(offset_ptr); 89283625Sdim if (Version >= 4) 90283625Sdim MaxOpsPerInst = debug_line_data.getU8(offset_ptr); 91283625Sdim DefaultIsStmt = debug_line_data.getU8(offset_ptr); 92283625Sdim LineBase = debug_line_data.getU8(offset_ptr); 93283625Sdim LineRange = debug_line_data.getU8(offset_ptr); 94283625Sdim OpcodeBase = debug_line_data.getU8(offset_ptr); 95283625Sdim 96283625Sdim StandardOpcodeLengths.reserve(OpcodeBase - 1); 97283625Sdim for (uint32_t i = 1; i < OpcodeBase; ++i) { 98283625Sdim uint8_t op_len = debug_line_data.getU8(offset_ptr); 99283625Sdim StandardOpcodeLengths.push_back(op_len); 100283625Sdim } 101283625Sdim 102283625Sdim while (*offset_ptr < end_prologue_offset) { 103283625Sdim const char *s = debug_line_data.getCStr(offset_ptr); 104283625Sdim if (s && s[0]) 105283625Sdim IncludeDirectories.push_back(s); 106283625Sdim else 107283625Sdim break; 108283625Sdim } 109283625Sdim 110283625Sdim while (*offset_ptr < end_prologue_offset) { 111283625Sdim const char *name = debug_line_data.getCStr(offset_ptr); 112283625Sdim if (name && name[0]) { 113283625Sdim FileNameEntry fileEntry; 114283625Sdim fileEntry.Name = name; 115283625Sdim fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); 116283625Sdim fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); 117283625Sdim fileEntry.Length = debug_line_data.getULEB128(offset_ptr); 118283625Sdim FileNames.push_back(fileEntry); 119283625Sdim } else { 120283625Sdim break; 121283625Sdim } 122283625Sdim } 123283625Sdim 124283625Sdim if (*offset_ptr != end_prologue_offset) { 125284236Sdim fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 126284236Sdim " should have ended at 0x%8.8" PRIx64 127284236Sdim " but it ended at 0x%8.8" PRIx64 "\n", 128284236Sdim prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr); 129283625Sdim return false; 130283625Sdim } 131283625Sdim return true; 132283625Sdim} 133283625Sdim 134283625SdimDWARFDebugLine::Row::Row(bool default_is_stmt) { 135283625Sdim reset(default_is_stmt); 136283625Sdim} 137283625Sdim 138283625Sdimvoid DWARFDebugLine::Row::postAppend() { 139283625Sdim BasicBlock = false; 140283625Sdim PrologueEnd = false; 141283625Sdim EpilogueBegin = false; 142283625Sdim} 143283625Sdim 144283625Sdimvoid DWARFDebugLine::Row::reset(bool default_is_stmt) { 145283625Sdim Address = 0; 146283625Sdim Line = 1; 147283625Sdim Column = 0; 148283625Sdim File = 1; 149283625Sdim Isa = 0; 150283625Sdim Discriminator = 0; 151283625Sdim IsStmt = default_is_stmt; 152283625Sdim BasicBlock = false; 153283625Sdim EndSequence = false; 154283625Sdim PrologueEnd = false; 155283625Sdim EpilogueBegin = false; 156283625Sdim} 157283625Sdim 158283625Sdimvoid DWARFDebugLine::Row::dump(raw_ostream &OS) const { 159283625Sdim OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column) 160283625Sdim << format(" %6u %3u %13u ", File, Isa, Discriminator) 161283625Sdim << (IsStmt ? " is_stmt" : "") 162283625Sdim << (BasicBlock ? " basic_block" : "") 163283625Sdim << (PrologueEnd ? " prologue_end" : "") 164283625Sdim << (EpilogueBegin ? " epilogue_begin" : "") 165283625Sdim << (EndSequence ? " end_sequence" : "") 166283625Sdim << '\n'; 167283625Sdim} 168283625Sdim 169283625SdimDWARFDebugLine::Sequence::Sequence() { 170283625Sdim reset(); 171283625Sdim} 172283625Sdim 173283625Sdimvoid DWARFDebugLine::Sequence::reset() { 174283625Sdim LowPC = 0; 175283625Sdim HighPC = 0; 176283625Sdim FirstRowIndex = 0; 177283625Sdim LastRowIndex = 0; 178283625Sdim Empty = true; 179283625Sdim} 180283625Sdim 181283625SdimDWARFDebugLine::LineTable::LineTable() { 182283625Sdim clear(); 183283625Sdim} 184283625Sdim 185283625Sdimvoid DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { 186283625Sdim Prologue.dump(OS); 187283625Sdim OS << '\n'; 188283625Sdim 189283625Sdim if (!Rows.empty()) { 190283625Sdim OS << "Address Line Column File ISA Discriminator Flags\n" 191283625Sdim << "------------------ ------ ------ ------ --- ------------- " 192283625Sdim "-------------\n"; 193283625Sdim for (const Row &R : Rows) { 194283625Sdim R.dump(OS); 195283625Sdim } 196283625Sdim } 197283625Sdim} 198283625Sdim 199283625Sdimvoid DWARFDebugLine::LineTable::clear() { 200283625Sdim Prologue.clear(); 201283625Sdim Rows.clear(); 202283625Sdim Sequences.clear(); 203283625Sdim} 204283625Sdim 205283625SdimDWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT) 206283625Sdim : LineTable(LT), RowNumber(0) { 207283625Sdim resetRowAndSequence(); 208283625Sdim} 209283625Sdim 210283625Sdimvoid DWARFDebugLine::ParsingState::resetRowAndSequence() { 211283625Sdim Row.reset(LineTable->Prologue.DefaultIsStmt); 212283625Sdim Sequence.reset(); 213283625Sdim} 214283625Sdim 215283625Sdimvoid DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) { 216283625Sdim if (Sequence.Empty) { 217283625Sdim // Record the beginning of instruction sequence. 218283625Sdim Sequence.Empty = false; 219283625Sdim Sequence.LowPC = Row.Address; 220283625Sdim Sequence.FirstRowIndex = RowNumber; 221283625Sdim } 222283625Sdim ++RowNumber; 223283625Sdim LineTable->appendRow(Row); 224283625Sdim if (Row.EndSequence) { 225283625Sdim // Record the end of instruction sequence. 226283625Sdim Sequence.HighPC = Row.Address; 227283625Sdim Sequence.LastRowIndex = RowNumber; 228283625Sdim if (Sequence.isValid()) 229283625Sdim LineTable->appendSequence(Sequence); 230283625Sdim Sequence.reset(); 231283625Sdim } 232283625Sdim Row.postAppend(); 233283625Sdim} 234283625Sdim 235283625Sdimconst DWARFDebugLine::LineTable * 236283625SdimDWARFDebugLine::getLineTable(uint32_t offset) const { 237283625Sdim LineTableConstIter pos = LineTableMap.find(offset); 238283625Sdim if (pos != LineTableMap.end()) 239283625Sdim return &pos->second; 240283625Sdim return nullptr; 241283625Sdim} 242283625Sdim 243283625Sdimconst DWARFDebugLine::LineTable * 244283625SdimDWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, 245283625Sdim uint32_t offset) { 246283625Sdim std::pair<LineTableIter, bool> pos = 247283625Sdim LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); 248283625Sdim LineTable *LT = &pos.first->second; 249283625Sdim if (pos.second) { 250283625Sdim if (!LT->parse(debug_line_data, RelocMap, &offset)) 251283625Sdim return nullptr; 252283625Sdim } 253283625Sdim return LT; 254283625Sdim} 255283625Sdim 256283625Sdimbool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data, 257283625Sdim const RelocAddrMap *RMap, 258283625Sdim uint32_t *offset_ptr) { 259283625Sdim const uint32_t debug_line_offset = *offset_ptr; 260283625Sdim 261283625Sdim clear(); 262283625Sdim 263283625Sdim if (!Prologue.parse(debug_line_data, offset_ptr)) { 264283625Sdim // Restore our offset and return false to indicate failure! 265283625Sdim *offset_ptr = debug_line_offset; 266283625Sdim return false; 267283625Sdim } 268283625Sdim 269283625Sdim const uint32_t end_offset = debug_line_offset + Prologue.TotalLength + 270284236Sdim Prologue.sizeofTotalLength(); 271283625Sdim 272283625Sdim ParsingState State(this); 273283625Sdim 274283625Sdim while (*offset_ptr < end_offset) { 275283625Sdim uint8_t opcode = debug_line_data.getU8(offset_ptr); 276283625Sdim 277283625Sdim if (opcode == 0) { 278283625Sdim // Extended Opcodes always start with a zero opcode followed by 279283625Sdim // a uleb128 length so you can skip ones you don't know about 280283625Sdim uint32_t ext_offset = *offset_ptr; 281283625Sdim uint64_t len = debug_line_data.getULEB128(offset_ptr); 282283625Sdim uint32_t arg_size = len - (*offset_ptr - ext_offset); 283283625Sdim 284283625Sdim uint8_t sub_opcode = debug_line_data.getU8(offset_ptr); 285283625Sdim switch (sub_opcode) { 286283625Sdim case DW_LNE_end_sequence: 287283625Sdim // Set the end_sequence register of the state machine to true and 288283625Sdim // append a row to the matrix using the current values of the 289283625Sdim // state-machine registers. Then reset the registers to the initial 290283625Sdim // values specified above. Every statement program sequence must end 291283625Sdim // with a DW_LNE_end_sequence instruction which creates a row whose 292283625Sdim // address is that of the byte after the last target machine instruction 293283625Sdim // of the sequence. 294283625Sdim State.Row.EndSequence = true; 295283625Sdim State.appendRowToMatrix(*offset_ptr); 296283625Sdim State.resetRowAndSequence(); 297283625Sdim break; 298283625Sdim 299283625Sdim case DW_LNE_set_address: 300283625Sdim // Takes a single relocatable address as an operand. The size of the 301283625Sdim // operand is the size appropriate to hold an address on the target 302283625Sdim // machine. Set the address register to the value given by the 303283625Sdim // relocatable address. All of the other statement program opcodes 304283625Sdim // that affect the address register add a delta to it. This instruction 305283625Sdim // stores a relocatable value into it instead. 306283625Sdim { 307283625Sdim // If this address is in our relocation map, apply the relocation. 308283625Sdim RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr); 309283625Sdim if (AI != RMap->end()) { 310283625Sdim const std::pair<uint8_t, int64_t> &R = AI->second; 311283625Sdim State.Row.Address = 312283625Sdim debug_line_data.getAddress(offset_ptr) + R.second; 313283625Sdim } else 314283625Sdim State.Row.Address = debug_line_data.getAddress(offset_ptr); 315283625Sdim } 316283625Sdim break; 317283625Sdim 318283625Sdim case DW_LNE_define_file: 319283625Sdim // Takes 4 arguments. The first is a null terminated string containing 320283625Sdim // a source file name. The second is an unsigned LEB128 number 321283625Sdim // representing the directory index of the directory in which the file 322283625Sdim // was found. The third is an unsigned LEB128 number representing the 323283625Sdim // time of last modification of the file. The fourth is an unsigned 324283625Sdim // LEB128 number representing the length in bytes of the file. The time 325283625Sdim // and length fields may contain LEB128(0) if the information is not 326283625Sdim // available. 327283625Sdim // 328283625Sdim // The directory index represents an entry in the include_directories 329283625Sdim // section of the statement program prologue. The index is LEB128(0) 330283625Sdim // if the file was found in the current directory of the compilation, 331283625Sdim // LEB128(1) if it was found in the first directory in the 332283625Sdim // include_directories section, and so on. The directory index is 333283625Sdim // ignored for file names that represent full path names. 334283625Sdim // 335283625Sdim // The files are numbered, starting at 1, in the order in which they 336283625Sdim // appear; the names in the prologue come before names defined by 337283625Sdim // the DW_LNE_define_file instruction. These numbers are used in the 338283625Sdim // the file register of the state machine. 339283625Sdim { 340283625Sdim FileNameEntry fileEntry; 341283625Sdim fileEntry.Name = debug_line_data.getCStr(offset_ptr); 342283625Sdim fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); 343283625Sdim fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); 344283625Sdim fileEntry.Length = debug_line_data.getULEB128(offset_ptr); 345283625Sdim Prologue.FileNames.push_back(fileEntry); 346283625Sdim } 347283625Sdim break; 348283625Sdim 349283625Sdim case DW_LNE_set_discriminator: 350283625Sdim State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr); 351283625Sdim break; 352283625Sdim 353283625Sdim default: 354283625Sdim // Length doesn't include the zero opcode byte or the length itself, but 355283625Sdim // it does include the sub_opcode, so we have to adjust for that below 356283625Sdim (*offset_ptr) += arg_size; 357283625Sdim break; 358283625Sdim } 359283625Sdim } else if (opcode < Prologue.OpcodeBase) { 360283625Sdim switch (opcode) { 361283625Sdim // Standard Opcodes 362283625Sdim case DW_LNS_copy: 363283625Sdim // Takes no arguments. Append a row to the matrix using the 364283625Sdim // current values of the state-machine registers. Then set 365283625Sdim // the basic_block register to false. 366283625Sdim State.appendRowToMatrix(*offset_ptr); 367283625Sdim break; 368283625Sdim 369283625Sdim case DW_LNS_advance_pc: 370283625Sdim // Takes a single unsigned LEB128 operand, multiplies it by the 371283625Sdim // min_inst_length field of the prologue, and adds the 372283625Sdim // result to the address register of the state machine. 373283625Sdim State.Row.Address += 374283625Sdim debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength; 375283625Sdim break; 376283625Sdim 377283625Sdim case DW_LNS_advance_line: 378283625Sdim // Takes a single signed LEB128 operand and adds that value to 379283625Sdim // the line register of the state machine. 380283625Sdim State.Row.Line += debug_line_data.getSLEB128(offset_ptr); 381283625Sdim break; 382283625Sdim 383283625Sdim case DW_LNS_set_file: 384283625Sdim // Takes a single unsigned LEB128 operand and stores it in the file 385283625Sdim // register of the state machine. 386283625Sdim State.Row.File = debug_line_data.getULEB128(offset_ptr); 387283625Sdim break; 388283625Sdim 389283625Sdim case DW_LNS_set_column: 390283625Sdim // Takes a single unsigned LEB128 operand and stores it in the 391283625Sdim // column register of the state machine. 392283625Sdim State.Row.Column = debug_line_data.getULEB128(offset_ptr); 393283625Sdim break; 394283625Sdim 395283625Sdim case DW_LNS_negate_stmt: 396283625Sdim // Takes no arguments. Set the is_stmt register of the state 397283625Sdim // machine to the logical negation of its current value. 398283625Sdim State.Row.IsStmt = !State.Row.IsStmt; 399283625Sdim break; 400283625Sdim 401283625Sdim case DW_LNS_set_basic_block: 402283625Sdim // Takes no arguments. Set the basic_block register of the 403283625Sdim // state machine to true 404283625Sdim State.Row.BasicBlock = true; 405283625Sdim break; 406283625Sdim 407283625Sdim case DW_LNS_const_add_pc: 408283625Sdim // Takes no arguments. Add to the address register of the state 409283625Sdim // machine the address increment value corresponding to special 410283625Sdim // opcode 255. The motivation for DW_LNS_const_add_pc is this: 411283625Sdim // when the statement program needs to advance the address by a 412283625Sdim // small amount, it can use a single special opcode, which occupies 413283625Sdim // a single byte. When it needs to advance the address by up to 414283625Sdim // twice the range of the last special opcode, it can use 415283625Sdim // DW_LNS_const_add_pc followed by a special opcode, for a total 416283625Sdim // of two bytes. Only if it needs to advance the address by more 417283625Sdim // than twice that range will it need to use both DW_LNS_advance_pc 418283625Sdim // and a special opcode, requiring three or more bytes. 419283625Sdim { 420283625Sdim uint8_t adjust_opcode = 255 - Prologue.OpcodeBase; 421283625Sdim uint64_t addr_offset = 422283625Sdim (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; 423283625Sdim State.Row.Address += addr_offset; 424283625Sdim } 425283625Sdim break; 426283625Sdim 427283625Sdim case DW_LNS_fixed_advance_pc: 428283625Sdim // Takes a single uhalf operand. Add to the address register of 429283625Sdim // the state machine the value of the (unencoded) operand. This 430283625Sdim // is the only extended opcode that takes an argument that is not 431283625Sdim // a variable length number. The motivation for DW_LNS_fixed_advance_pc 432283625Sdim // is this: existing assemblers cannot emit DW_LNS_advance_pc or 433283625Sdim // special opcodes because they cannot encode LEB128 numbers or 434283625Sdim // judge when the computation of a special opcode overflows and 435283625Sdim // requires the use of DW_LNS_advance_pc. Such assemblers, however, 436283625Sdim // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. 437283625Sdim State.Row.Address += debug_line_data.getU16(offset_ptr); 438283625Sdim break; 439283625Sdim 440283625Sdim case DW_LNS_set_prologue_end: 441283625Sdim // Takes no arguments. Set the prologue_end register of the 442283625Sdim // state machine to true 443283625Sdim State.Row.PrologueEnd = true; 444283625Sdim break; 445283625Sdim 446283625Sdim case DW_LNS_set_epilogue_begin: 447283625Sdim // Takes no arguments. Set the basic_block register of the 448283625Sdim // state machine to true 449283625Sdim State.Row.EpilogueBegin = true; 450283625Sdim break; 451283625Sdim 452283625Sdim case DW_LNS_set_isa: 453283625Sdim // Takes a single unsigned LEB128 operand and stores it in the 454283625Sdim // column register of the state machine. 455283625Sdim State.Row.Isa = debug_line_data.getULEB128(offset_ptr); 456283625Sdim break; 457283625Sdim 458283625Sdim default: 459283625Sdim // Handle any unknown standard opcodes here. We know the lengths 460283625Sdim // of such opcodes because they are specified in the prologue 461283625Sdim // as a multiple of LEB128 operands for each opcode. 462283625Sdim { 463283625Sdim assert(opcode - 1U < Prologue.StandardOpcodeLengths.size()); 464283625Sdim uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1]; 465283625Sdim for (uint8_t i = 0; i < opcode_length; ++i) 466283625Sdim debug_line_data.getULEB128(offset_ptr); 467283625Sdim } 468283625Sdim break; 469283625Sdim } 470283625Sdim } else { 471283625Sdim // Special Opcodes 472283625Sdim 473283625Sdim // A special opcode value is chosen based on the amount that needs 474283625Sdim // to be added to the line and address registers. The maximum line 475283625Sdim // increment for a special opcode is the value of the line_base 476283625Sdim // field in the header, plus the value of the line_range field, 477283625Sdim // minus 1 (line base + line range - 1). If the desired line 478283625Sdim // increment is greater than the maximum line increment, a standard 479283625Sdim // opcode must be used instead of a special opcode. The "address 480283625Sdim // advance" is calculated by dividing the desired address increment 481283625Sdim // by the minimum_instruction_length field from the header. The 482283625Sdim // special opcode is then calculated using the following formula: 483283625Sdim // 484283625Sdim // opcode = (desired line increment - line_base) + 485283625Sdim // (line_range * address advance) + opcode_base 486283625Sdim // 487283625Sdim // If the resulting opcode is greater than 255, a standard opcode 488283625Sdim // must be used instead. 489283625Sdim // 490283625Sdim // To decode a special opcode, subtract the opcode_base from the 491283625Sdim // opcode itself to give the adjusted opcode. The amount to 492283625Sdim // increment the address register is the result of the adjusted 493283625Sdim // opcode divided by the line_range multiplied by the 494283625Sdim // minimum_instruction_length field from the header. That is: 495283625Sdim // 496283625Sdim // address increment = (adjusted opcode / line_range) * 497283625Sdim // minimum_instruction_length 498283625Sdim // 499283625Sdim // The amount to increment the line register is the line_base plus 500283625Sdim // the result of the adjusted opcode modulo the line_range. That is: 501283625Sdim // 502283625Sdim // line increment = line_base + (adjusted opcode % line_range) 503283625Sdim 504283625Sdim uint8_t adjust_opcode = opcode - Prologue.OpcodeBase; 505283625Sdim uint64_t addr_offset = 506283625Sdim (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; 507283625Sdim int32_t line_offset = 508283625Sdim Prologue.LineBase + (adjust_opcode % Prologue.LineRange); 509283625Sdim State.Row.Line += line_offset; 510283625Sdim State.Row.Address += addr_offset; 511283625Sdim State.appendRowToMatrix(*offset_ptr); 512283625Sdim } 513283625Sdim } 514283625Sdim 515283625Sdim if (!State.Sequence.Empty) { 516283625Sdim fprintf(stderr, "warning: last sequence in debug line table is not" 517283625Sdim "terminated!\n"); 518283625Sdim } 519283625Sdim 520283625Sdim // Sort all sequences so that address lookup will work faster. 521283625Sdim if (!Sequences.empty()) { 522283625Sdim std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); 523283625Sdim // Note: actually, instruction address ranges of sequences should not 524283625Sdim // overlap (in shared objects and executables). If they do, the address 525283625Sdim // lookup would still work, though, but result would be ambiguous. 526283625Sdim // We don't report warning in this case. For example, 527283625Sdim // sometimes .so compiled from multiple object files contains a few 528283625Sdim // rudimentary sequences for address ranges [0x0, 0xsomething). 529283625Sdim } 530283625Sdim 531283625Sdim return end_offset; 532283625Sdim} 533283625Sdim 534284236Sdimuint32_t 535284236SdimDWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &seq, 536284236Sdim uint64_t address) const { 537284236Sdim if (!seq.containsPC(address)) 538284236Sdim return UnknownRowIndex; 539284236Sdim // Search for instruction address in the rows describing the sequence. 540284236Sdim // Rows are stored in a vector, so we may use arithmetical operations with 541284236Sdim // iterators. 542284236Sdim DWARFDebugLine::Row row; 543284236Sdim row.Address = address; 544284236Sdim RowIter first_row = Rows.begin() + seq.FirstRowIndex; 545284236Sdim RowIter last_row = Rows.begin() + seq.LastRowIndex; 546284236Sdim LineTable::RowIter row_pos = std::lower_bound( 547284236Sdim first_row, last_row, row, DWARFDebugLine::Row::orderByAddress); 548284236Sdim if (row_pos == last_row) { 549284236Sdim return seq.LastRowIndex - 1; 550284236Sdim } 551284236Sdim uint32_t index = seq.FirstRowIndex + (row_pos - first_row); 552284236Sdim if (row_pos->Address > address) { 553284236Sdim if (row_pos == first_row) 554284236Sdim return UnknownRowIndex; 555284236Sdim else 556284236Sdim index--; 557284236Sdim } 558284236Sdim return index; 559284236Sdim} 560284236Sdim 561283625Sdimuint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { 562283625Sdim if (Sequences.empty()) 563284236Sdim return UnknownRowIndex; 564283625Sdim // First, find an instruction sequence containing the given address. 565283625Sdim DWARFDebugLine::Sequence sequence; 566283625Sdim sequence.LowPC = address; 567283625Sdim SequenceIter first_seq = Sequences.begin(); 568283625Sdim SequenceIter last_seq = Sequences.end(); 569283625Sdim SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence, 570283625Sdim DWARFDebugLine::Sequence::orderByLowPC); 571283625Sdim DWARFDebugLine::Sequence found_seq; 572283625Sdim if (seq_pos == last_seq) { 573283625Sdim found_seq = Sequences.back(); 574283625Sdim } else if (seq_pos->LowPC == address) { 575283625Sdim found_seq = *seq_pos; 576283625Sdim } else { 577283625Sdim if (seq_pos == first_seq) 578284236Sdim return UnknownRowIndex; 579283625Sdim found_seq = *(seq_pos - 1); 580283625Sdim } 581284236Sdim return findRowInSeq(found_seq, address); 582283625Sdim} 583283625Sdim 584283625Sdimbool DWARFDebugLine::LineTable::lookupAddressRange( 585283625Sdim uint64_t address, uint64_t size, std::vector<uint32_t> &result) const { 586283625Sdim if (Sequences.empty()) 587283625Sdim return false; 588283625Sdim uint64_t end_addr = address + size; 589283625Sdim // First, find an instruction sequence containing the given address. 590283625Sdim DWARFDebugLine::Sequence sequence; 591283625Sdim sequence.LowPC = address; 592283625Sdim SequenceIter first_seq = Sequences.begin(); 593283625Sdim SequenceIter last_seq = Sequences.end(); 594283625Sdim SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence, 595283625Sdim DWARFDebugLine::Sequence::orderByLowPC); 596283625Sdim if (seq_pos == last_seq || seq_pos->LowPC != address) { 597283625Sdim if (seq_pos == first_seq) 598283625Sdim return false; 599283625Sdim seq_pos--; 600283625Sdim } 601283625Sdim if (!seq_pos->containsPC(address)) 602283625Sdim return false; 603283625Sdim 604283625Sdim SequenceIter start_pos = seq_pos; 605283625Sdim 606283625Sdim // Add the rows from the first sequence to the vector, starting with the 607283625Sdim // index we just calculated 608283625Sdim 609283625Sdim while (seq_pos != last_seq && seq_pos->LowPC < end_addr) { 610284236Sdim const DWARFDebugLine::Sequence &cur_seq = *seq_pos; 611284236Sdim // For the first sequence, we need to find which row in the sequence is the 612284236Sdim // first in our range. 613284236Sdim uint32_t first_row_index = cur_seq.FirstRowIndex; 614284236Sdim if (seq_pos == start_pos) 615284236Sdim first_row_index = findRowInSeq(cur_seq, address); 616283625Sdim 617284236Sdim // Figure out the last row in the range. 618284236Sdim uint32_t last_row_index = findRowInSeq(cur_seq, end_addr - 1); 619284236Sdim if (last_row_index == UnknownRowIndex) 620283625Sdim last_row_index = cur_seq.LastRowIndex - 1; 621283625Sdim 622284236Sdim assert(first_row_index != UnknownRowIndex); 623284236Sdim assert(last_row_index != UnknownRowIndex); 624284236Sdim 625283625Sdim for (uint32_t i = first_row_index; i <= last_row_index; ++i) { 626283625Sdim result.push_back(i); 627283625Sdim } 628283625Sdim 629283625Sdim ++seq_pos; 630283625Sdim } 631283625Sdim 632283625Sdim return true; 633283625Sdim} 634283625Sdim 635283625Sdimbool 636283625SdimDWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, 637283625Sdim const char *CompDir, 638283625Sdim FileLineInfoKind Kind, 639283625Sdim std::string &Result) const { 640283625Sdim if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || 641283625Sdim Kind == FileLineInfoKind::None) 642283625Sdim return false; 643283625Sdim const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; 644283625Sdim const char *FileName = Entry.Name; 645283625Sdim if (Kind != FileLineInfoKind::AbsoluteFilePath || 646283625Sdim sys::path::is_absolute(FileName)) { 647283625Sdim Result = FileName; 648283625Sdim return true; 649283625Sdim } 650283625Sdim 651283625Sdim SmallString<16> FilePath; 652283625Sdim uint64_t IncludeDirIndex = Entry.DirIdx; 653283625Sdim const char *IncludeDir = ""; 654283625Sdim // Be defensive about the contents of Entry. 655283625Sdim if (IncludeDirIndex > 0 && 656283625Sdim IncludeDirIndex <= Prologue.IncludeDirectories.size()) 657283625Sdim IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1]; 658283625Sdim 659283625Sdim // We may still need to append compilation directory of compile unit. 660283625Sdim // We know that FileName is not absolute, the only way to have an 661283625Sdim // absolute path at this point would be if IncludeDir is absolute. 662283625Sdim if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath && 663283625Sdim sys::path::is_relative(IncludeDir)) 664283625Sdim sys::path::append(FilePath, CompDir); 665283625Sdim 666283625Sdim // sys::path::append skips empty strings. 667283625Sdim sys::path::append(FilePath, IncludeDir, FileName); 668283625Sdim Result = FilePath.str(); 669283625Sdim return true; 670283625Sdim} 671283625Sdim 672283625Sdimbool 673283625SdimDWARFDebugLine::LineTable::getFileLineInfoForAddress(uint64_t Address, 674283625Sdim const char *CompDir, 675283625Sdim FileLineInfoKind Kind, 676283625Sdim DILineInfo &Result) const { 677283625Sdim // Get the index of row we're looking for in the line table. 678283625Sdim uint32_t RowIndex = lookupAddress(Address); 679283625Sdim if (RowIndex == -1U) 680283625Sdim return false; 681283625Sdim // Take file number and line/column from the row. 682283625Sdim const auto &Row = Rows[RowIndex]; 683283625Sdim if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName)) 684283625Sdim return false; 685283625Sdim Result.Line = Row.Line; 686283625Sdim Result.Column = Row.Column; 687283625Sdim return true; 688283625Sdim} 689