1 //===- DWARFDebugLine.h -----------------------------------------*- 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 #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H 11 #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H 12 13 #include "llvm/ADT/Optional.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/DebugInfo/DIContext.h" 16 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 17 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 18 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 19 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" 20 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 21 #include "llvm/Support/MD5.h" 22 #include <cstdint> 23 #include <map> 24 #include <string> 25 #include <vector> 26 27 namespace llvm { 28 29 class DWARFUnit; 30 class raw_ostream; 31 32 class DWARFDebugLine { 33 public: 34 struct FileNameEntry { 35 FileNameEntry() = default; 36 37 DWARFFormValue Name; 38 uint64_t DirIdx = 0; 39 uint64_t ModTime = 0; 40 uint64_t Length = 0; 41 MD5::MD5Result Checksum; 42 DWARFFormValue Source; 43 }; 44 45 /// Tracks which optional content types are present in a DWARF file name 46 /// entry format. 47 struct ContentTypeTracker { 48 ContentTypeTracker() = default; 49 50 /// Whether filename entries provide a modification timestamp. 51 bool HasModTime = false; 52 /// Whether filename entries provide a file size. 53 bool HasLength = false; 54 /// For v5, whether filename entries provide an MD5 checksum. 55 bool HasMD5 = false; 56 /// For v5, whether filename entries provide source text. 57 bool HasSource = false; 58 59 /// Update tracked content types with \p ContentType. 60 void trackContentType(dwarf::LineNumberEntryFormat ContentType); 61 }; 62 63 struct Prologue { 64 Prologue(); 65 66 /// The size in bytes of the statement information for this compilation unit 67 /// (not including the total_length field itself). 68 uint64_t TotalLength; 69 /// Version, address size (starting in v5), and DWARF32/64 format; these 70 /// parameters affect interpretation of forms (used in the directory and 71 /// file tables starting with v5). 72 dwarf::FormParams FormParams; 73 /// The number of bytes following the prologue_length field to the beginning 74 /// of the first byte of the statement program itself. 75 uint64_t PrologueLength; 76 /// In v5, size in bytes of a segment selector. 77 uint8_t SegSelectorSize; 78 /// The size in bytes of the smallest target machine instruction. Statement 79 /// program opcodes that alter the address register first multiply their 80 /// operands by this value. 81 uint8_t MinInstLength; 82 /// The maximum number of individual operations that may be encoded in an 83 /// instruction. 84 uint8_t MaxOpsPerInst; 85 /// The initial value of theis_stmtregister. 86 uint8_t DefaultIsStmt; 87 /// This parameter affects the meaning of the special opcodes. See below. 88 int8_t LineBase; 89 /// This parameter affects the meaning of the special opcodes. See below. 90 uint8_t LineRange; 91 /// The number assigned to the first special opcode. 92 uint8_t OpcodeBase; 93 /// This tracks which optional file format content types are present. 94 ContentTypeTracker ContentTypes; 95 std::vector<uint8_t> StandardOpcodeLengths; 96 std::vector<DWARFFormValue> IncludeDirectories; 97 std::vector<FileNameEntry> FileNames; 98 getFormParamsPrologue99 const dwarf::FormParams getFormParams() const { return FormParams; } getVersionPrologue100 uint16_t getVersion() const { return FormParams.Version; } getAddressSizePrologue101 uint8_t getAddressSize() const { return FormParams.AddrSize; } isDWARF64Prologue102 bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } 103 sizeofTotalLengthPrologue104 uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; } 105 sizeofPrologueLengthPrologue106 uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } 107 108 bool totalLengthIsValid() const; 109 110 /// Length of the prologue in bytes. getLengthPrologue111 uint32_t getLength() const { 112 return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) + 113 sizeofPrologueLength(); 114 } 115 116 /// Length of the line table data in bytes (not including the prologue). getStatementTableLengthPrologue117 uint32_t getStatementTableLength() const { 118 return TotalLength + sizeofTotalLength() - getLength(); 119 } 120 getMaxLineIncrementForSpecialOpcodePrologue121 int32_t getMaxLineIncrementForSpecialOpcode() const { 122 return LineBase + (int8_t)LineRange - 1; 123 } 124 125 void clear(); 126 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 127 Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, 128 const DWARFContext &Ctx, const DWARFUnit *U = nullptr); 129 }; 130 131 /// Standard .debug_line state machine structure. 132 struct Row { 133 explicit Row(bool DefaultIsStmt = false); 134 135 /// Called after a row is appended to the matrix. 136 void postAppend(); 137 void reset(bool DefaultIsStmt); 138 void dump(raw_ostream &OS) const; 139 140 static void dumpTableHeader(raw_ostream &OS); 141 orderByAddressRow142 static bool orderByAddress(const Row &LHS, const Row &RHS) { 143 return LHS.Address < RHS.Address; 144 } 145 146 /// The program-counter value corresponding to a machine instruction 147 /// generated by the compiler. 148 uint64_t Address; 149 /// An unsigned integer indicating a source line number. Lines are numbered 150 /// beginning at 1. The compiler may emit the value 0 in cases where an 151 /// instruction cannot be attributed to any source line. 152 uint32_t Line; 153 /// An unsigned integer indicating a column number within a source line. 154 /// Columns are numbered beginning at 1. The value 0 is reserved to indicate 155 /// that a statement begins at the 'left edge' of the line. 156 uint16_t Column; 157 /// An unsigned integer indicating the identity of the source file 158 /// corresponding to a machine instruction. 159 uint16_t File; 160 /// An unsigned integer representing the DWARF path discriminator value 161 /// for this location. 162 uint32_t Discriminator; 163 /// An unsigned integer whose value encodes the applicable instruction set 164 /// architecture for the current instruction. 165 uint8_t Isa; 166 /// A boolean indicating that the current instruction is the beginning of a 167 /// statement. 168 uint8_t IsStmt : 1, 169 /// A boolean indicating that the current instruction is the 170 /// beginning of a basic block. 171 BasicBlock : 1, 172 /// A boolean indicating that the current address is that of the 173 /// first byte after the end of a sequence of target machine 174 /// instructions. 175 EndSequence : 1, 176 /// A boolean indicating that the current address is one (of possibly 177 /// many) where execution should be suspended for an entry breakpoint 178 /// of a function. 179 PrologueEnd : 1, 180 /// A boolean indicating that the current address is one (of possibly 181 /// many) where execution should be suspended for an exit breakpoint 182 /// of a function. 183 EpilogueBegin : 1; 184 }; 185 186 /// Represents a series of contiguous machine instructions. Line table for 187 /// each compilation unit may consist of multiple sequences, which are not 188 /// guaranteed to be in the order of ascending instruction address. 189 struct Sequence { 190 Sequence(); 191 192 /// Sequence describes instructions at address range [LowPC, HighPC) 193 /// and is described by line table rows [FirstRowIndex, LastRowIndex). 194 uint64_t LowPC; 195 uint64_t HighPC; 196 unsigned FirstRowIndex; 197 unsigned LastRowIndex; 198 bool Empty; 199 200 void reset(); 201 orderByLowPCSequence202 static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { 203 return LHS.LowPC < RHS.LowPC; 204 } 205 isValidSequence206 bool isValid() const { 207 return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); 208 } 209 containsPCSequence210 bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } 211 }; 212 213 struct LineTable { 214 LineTable(); 215 216 /// Represents an invalid row 217 const uint32_t UnknownRowIndex = UINT32_MAX; 218 appendRowLineTable219 void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); } 220 appendSequenceLineTable221 void appendSequence(const DWARFDebugLine::Sequence &S) { 222 Sequences.push_back(S); 223 } 224 225 /// Returns the index of the row with file/line info for a given address, 226 /// or UnknownRowIndex if there is no such row. 227 uint32_t lookupAddress(uint64_t Address) const; 228 229 bool lookupAddressRange(uint64_t Address, uint64_t Size, 230 std::vector<uint32_t> &Result) const; 231 232 bool hasFileAtIndex(uint64_t FileIndex) const; 233 234 /// Extracts filename by its index in filename table in prologue. 235 /// Returns true on success. 236 bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, 237 DILineInfoSpecifier::FileLineInfoKind Kind, 238 std::string &Result) const; 239 240 /// Fills the Result argument with the file and line information 241 /// corresponding to Address. Returns true on success. 242 bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, 243 DILineInfoSpecifier::FileLineInfoKind Kind, 244 DILineInfo &Result) const; 245 246 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 247 void clear(); 248 249 /// Parse prologue and all rows. 250 Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, 251 const DWARFContext &Ctx, const DWARFUnit *U, 252 std::function<void(Error)> RecoverableErrorCallback = warn, 253 raw_ostream *OS = nullptr); 254 255 using RowVector = std::vector<Row>; 256 using RowIter = RowVector::const_iterator; 257 using SequenceVector = std::vector<Sequence>; 258 using SequenceIter = SequenceVector::const_iterator; 259 260 struct Prologue Prologue; 261 RowVector Rows; 262 SequenceVector Sequences; 263 264 private: 265 uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, 266 uint64_t Address) const; 267 Optional<StringRef> 268 getSourceByIndex(uint64_t FileIndex, 269 DILineInfoSpecifier::FileLineInfoKind Kind) const; 270 }; 271 272 const LineTable *getLineTable(uint32_t Offset) const; 273 Expected<const LineTable *> getOrParseLineTable( 274 DWARFDataExtractor &DebugLineData, uint32_t Offset, 275 const DWARFContext &Ctx, const DWARFUnit *U, 276 std::function<void(Error)> RecoverableErrorCallback = warn); 277 278 /// Helper to allow for parsing of an entire .debug_line section in sequence. 279 class SectionParser { 280 public: 281 using cu_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range; 282 using tu_range = 283 iterator_range<std::deque<DWARFUnitSection<DWARFTypeUnit>>::iterator>; 284 using LineToUnitMap = std::map<uint64_t, DWARFUnit *>; 285 286 SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs, 287 tu_range TUs); 288 289 /// Get the next line table from the section. Report any issues via the 290 /// callbacks. 291 /// 292 /// \param RecoverableErrorCallback - any issues that don't prevent further 293 /// parsing of the table will be reported through this callback. 294 /// \param UnrecoverableErrorCallback - any issues that prevent further 295 /// parsing of the table will be reported through this callback. 296 /// \param OS - if not null, the parser will print information about the 297 /// table as it parses it. 298 LineTable 299 parseNext(function_ref<void(Error)> RecoverableErrorCallback = warn, 300 function_ref<void(Error)> UnrecoverableErrorCallback = warn, 301 raw_ostream *OS = nullptr); 302 303 /// Skip the current line table and go to the following line table (if 304 /// present) immediately. 305 /// 306 /// \param ErrorCallback - report any prologue parsing issues via this 307 /// callback. 308 void skip(function_ref<void(Error)> ErrorCallback = warn); 309 310 /// Indicates if the parser has parsed as much as possible. 311 /// 312 /// \note Certain problems with the line table structure might mean that 313 /// parsing stops before the end of the section is reached. done()314 bool done() const { return Done; } 315 316 /// Get the offset the parser has reached. getOffset()317 uint32_t getOffset() const { return Offset; } 318 319 private: 320 DWARFUnit *prepareToParse(uint32_t Offset); 321 void moveToNextTable(uint32_t OldOffset, const Prologue &P); 322 323 LineToUnitMap LineToUnit; 324 325 DWARFDataExtractor &DebugLineData; 326 const DWARFContext &Context; 327 uint32_t Offset = 0; 328 bool Done = false; 329 }; 330 331 /// Helper function for DWARFDebugLine parse functions, to report issues 332 /// identified during parsing. 333 /// 334 /// \param Err The Error to report. 335 static void warn(Error Err); 336 337 private: 338 struct ParsingState { 339 ParsingState(struct LineTable *LT); 340 341 void resetRowAndSequence(); 342 void appendRowToMatrix(uint32_t Offset); 343 344 /// Line table we're currently parsing. 345 struct LineTable *LineTable; 346 /// The row number that starts at zero for the prologue, and increases for 347 /// each row added to the matrix. 348 unsigned RowNumber = 0; 349 struct Row Row; 350 struct Sequence Sequence; 351 }; 352 353 using LineTableMapTy = std::map<uint32_t, LineTable>; 354 using LineTableIter = LineTableMapTy::iterator; 355 using LineTableConstIter = LineTableMapTy::const_iterator; 356 357 LineTableMapTy LineTableMap; 358 }; 359 360 } // end namespace llvm 361 362 #endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H 363