1 //===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 11 12 #include "llvm/ADT/Optional.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/BinaryFormat/Dwarf.h" 15 #include "llvm/DebugInfo/DIContext.h" 16 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 17 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 18 #include "llvm/Support/MD5.h" 19 #include "llvm/Support/Path.h" 20 #include <cstdint> 21 #include <map> 22 #include <string> 23 #include <vector> 24 25 namespace llvm { 26 27 class raw_ostream; 28 29 class DWARFDebugLine { 30 public: 31 struct FileNameEntry { 32 FileNameEntry() = default; 33 34 DWARFFormValue Name; 35 uint64_t DirIdx = 0; 36 uint64_t ModTime = 0; 37 uint64_t Length = 0; 38 MD5::MD5Result Checksum; 39 DWARFFormValue Source; 40 }; 41 42 /// Tracks which optional content types are present in a DWARF file name 43 /// entry format. 44 struct ContentTypeTracker { 45 ContentTypeTracker() = default; 46 47 /// Whether filename entries provide a modification timestamp. 48 bool HasModTime = false; 49 /// Whether filename entries provide a file size. 50 bool HasLength = false; 51 /// For v5, whether filename entries provide an MD5 checksum. 52 bool HasMD5 = false; 53 /// For v5, whether filename entries provide source text. 54 bool HasSource = false; 55 56 /// Update tracked content types with \p ContentType. 57 void trackContentType(dwarf::LineNumberEntryFormat ContentType); 58 }; 59 60 struct Prologue { 61 Prologue(); 62 63 /// The size in bytes of the statement information for this compilation unit 64 /// (not including the total_length field itself). 65 uint64_t TotalLength; 66 /// Version, address size (starting in v5), and DWARF32/64 format; these 67 /// parameters affect interpretation of forms (used in the directory and 68 /// file tables starting with v5). 69 dwarf::FormParams FormParams; 70 /// The number of bytes following the prologue_length field to the beginning 71 /// of the first byte of the statement program itself. 72 uint64_t PrologueLength; 73 /// In v5, size in bytes of a segment selector. 74 uint8_t SegSelectorSize; 75 /// The size in bytes of the smallest target machine instruction. Statement 76 /// program opcodes that alter the address register first multiply their 77 /// operands by this value. 78 uint8_t MinInstLength; 79 /// The maximum number of individual operations that may be encoded in an 80 /// instruction. 81 uint8_t MaxOpsPerInst; 82 /// The initial value of theis_stmtregister. 83 uint8_t DefaultIsStmt; 84 /// This parameter affects the meaning of the special opcodes. See below. 85 int8_t LineBase; 86 /// This parameter affects the meaning of the special opcodes. See below. 87 uint8_t LineRange; 88 /// The number assigned to the first special opcode. 89 uint8_t OpcodeBase; 90 /// This tracks which optional file format content types are present. 91 ContentTypeTracker ContentTypes; 92 std::vector<uint8_t> StandardOpcodeLengths; 93 std::vector<DWARFFormValue> IncludeDirectories; 94 std::vector<FileNameEntry> FileNames; 95 96 const dwarf::FormParams getFormParams() const { return FormParams; } 97 uint16_t getVersion() const { return FormParams.Version; } 98 uint8_t getAddressSize() const { return FormParams.AddrSize; } 99 bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } 100 101 uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; } 102 103 uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } 104 105 bool totalLengthIsValid() const; 106 107 /// Length of the prologue in bytes. 108 uint64_t getLength() const; 109 110 /// Get DWARF-version aware access to the file name entry at the provided 111 /// index. 112 const llvm::DWARFDebugLine::FileNameEntry & 113 getFileNameEntry(uint64_t Index) const; 114 115 bool hasFileAtIndex(uint64_t FileIndex) const; 116 117 Optional<uint64_t> getLastValidFileIndex() const; 118 119 bool 120 getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, 121 DILineInfoSpecifier::FileLineInfoKind Kind, 122 std::string &Result, 123 sys::path::Style Style = sys::path::Style::native) const; 124 125 void clear(); 126 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 127 Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr, 128 function_ref<void(Error)> RecoverableErrorHandler, 129 const DWARFContext &Ctx, const DWARFUnit *U = nullptr); 130 }; 131 132 /// Standard .debug_line state machine structure. 133 struct Row { 134 explicit Row(bool DefaultIsStmt = false); 135 136 /// Called after a row is appended to the matrix. 137 void postAppend(); 138 void reset(bool DefaultIsStmt); 139 void dump(raw_ostream &OS) const; 140 141 static void dumpTableHeader(raw_ostream &OS, unsigned Indent); 142 143 static bool orderByAddress(const Row &LHS, const Row &RHS) { 144 return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) < 145 std::tie(RHS.Address.SectionIndex, RHS.Address.Address); 146 } 147 148 /// The program-counter value corresponding to a machine instruction 149 /// generated by the compiler and section index pointing to the section 150 /// containg this PC. If relocation information is present then section 151 /// index is the index of the section which contains above address. 152 /// Otherwise this is object::SectionedAddress::Undef value. 153 object::SectionedAddress Address; 154 /// An unsigned integer indicating a source line number. Lines are numbered 155 /// beginning at 1. The compiler may emit the value 0 in cases where an 156 /// instruction cannot be attributed to any source line. 157 uint32_t Line; 158 /// An unsigned integer indicating a column number within a source line. 159 /// Columns are numbered beginning at 1. The value 0 is reserved to indicate 160 /// that a statement begins at the 'left edge' of the line. 161 uint16_t Column; 162 /// An unsigned integer indicating the identity of the source file 163 /// corresponding to a machine instruction. 164 uint16_t File; 165 /// An unsigned integer representing the DWARF path discriminator value 166 /// for this location. 167 uint32_t Discriminator; 168 /// An unsigned integer whose value encodes the applicable instruction set 169 /// architecture for the current instruction. 170 uint8_t Isa; 171 /// A boolean indicating that the current instruction is the beginning of a 172 /// statement. 173 uint8_t IsStmt : 1, 174 /// A boolean indicating that the current instruction is the 175 /// beginning of a basic block. 176 BasicBlock : 1, 177 /// A boolean indicating that the current address is that of the 178 /// first byte after the end of a sequence of target machine 179 /// instructions. 180 EndSequence : 1, 181 /// A boolean indicating that the current address is one (of possibly 182 /// many) where execution should be suspended for an entry breakpoint 183 /// of a function. 184 PrologueEnd : 1, 185 /// A boolean indicating that the current address is one (of possibly 186 /// many) where execution should be suspended for an exit breakpoint 187 /// of a function. 188 EpilogueBegin : 1; 189 }; 190 191 /// Represents a series of contiguous machine instructions. Line table for 192 /// each compilation unit may consist of multiple sequences, which are not 193 /// guaranteed to be in the order of ascending instruction address. 194 struct Sequence { 195 Sequence(); 196 197 /// Sequence describes instructions at address range [LowPC, HighPC) 198 /// and is described by line table rows [FirstRowIndex, LastRowIndex). 199 uint64_t LowPC; 200 uint64_t HighPC; 201 /// If relocation information is present then this is the index of the 202 /// section which contains above addresses. Otherwise this is 203 /// object::SectionedAddress::Undef value. 204 uint64_t SectionIndex; 205 unsigned FirstRowIndex; 206 unsigned LastRowIndex; 207 bool Empty; 208 209 void reset(); 210 211 static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS) { 212 return std::tie(LHS.SectionIndex, LHS.HighPC) < 213 std::tie(RHS.SectionIndex, RHS.HighPC); 214 } 215 216 bool isValid() const { 217 return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); 218 } 219 220 bool containsPC(object::SectionedAddress PC) const { 221 return SectionIndex == PC.SectionIndex && 222 (LowPC <= PC.Address && PC.Address < HighPC); 223 } 224 }; 225 226 struct LineTable { 227 LineTable(); 228 229 /// Represents an invalid row 230 const uint32_t UnknownRowIndex = UINT32_MAX; 231 232 void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); } 233 234 void appendSequence(const DWARFDebugLine::Sequence &S) { 235 Sequences.push_back(S); 236 } 237 238 /// Returns the index of the row with file/line info for a given address, 239 /// or UnknownRowIndex if there is no such row. 240 uint32_t lookupAddress(object::SectionedAddress Address) const; 241 242 bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, 243 std::vector<uint32_t> &Result) const; 244 245 bool hasFileAtIndex(uint64_t FileIndex) const { 246 return Prologue.hasFileAtIndex(FileIndex); 247 } 248 249 Optional<uint64_t> getLastValidFileIndex() const { 250 return Prologue.getLastValidFileIndex(); 251 } 252 253 /// Extracts filename by its index in filename table in prologue. 254 /// In Dwarf 4, the files are 1-indexed and the current compilation file 255 /// name is not represented in the list. In DWARF v5, the files are 256 /// 0-indexed and the primary source file has the index 0. 257 /// Returns true on success. 258 bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, 259 DILineInfoSpecifier::FileLineInfoKind Kind, 260 std::string &Result) const { 261 return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result); 262 } 263 264 /// Fills the Result argument with the file and line information 265 /// corresponding to Address. Returns true on success. 266 bool getFileLineInfoForAddress(object::SectionedAddress Address, 267 const char *CompDir, 268 DILineInfoSpecifier::FileLineInfoKind Kind, 269 DILineInfo &Result) const; 270 271 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; 272 void clear(); 273 274 /// Parse prologue and all rows. 275 Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, 276 const DWARFContext &Ctx, const DWARFUnit *U, 277 function_ref<void(Error)> RecoverableErrorHandler, 278 raw_ostream *OS = nullptr, bool Verbose = false); 279 280 using RowVector = std::vector<Row>; 281 using RowIter = RowVector::const_iterator; 282 using SequenceVector = std::vector<Sequence>; 283 using SequenceIter = SequenceVector::const_iterator; 284 285 struct Prologue Prologue; 286 RowVector Rows; 287 SequenceVector Sequences; 288 289 private: 290 uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, 291 object::SectionedAddress Address) const; 292 Optional<StringRef> 293 getSourceByIndex(uint64_t FileIndex, 294 DILineInfoSpecifier::FileLineInfoKind Kind) const; 295 296 uint32_t lookupAddressImpl(object::SectionedAddress Address) const; 297 298 bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size, 299 std::vector<uint32_t> &Result) const; 300 }; 301 302 const LineTable *getLineTable(uint64_t Offset) const; 303 Expected<const LineTable *> 304 getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset, 305 const DWARFContext &Ctx, const DWARFUnit *U, 306 function_ref<void(Error)> RecoverableErrorHandler); 307 void clearLineTable(uint64_t Offset); 308 309 /// Helper to allow for parsing of an entire .debug_line section in sequence. 310 class SectionParser { 311 public: 312 using LineToUnitMap = std::map<uint64_t, DWARFUnit *>; 313 314 SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, 315 DWARFUnitVector::iterator_range Units); 316 317 /// Get the next line table from the section. Report any issues via the 318 /// handlers. 319 /// 320 /// \param RecoverableErrorHandler - any issues that don't prevent further 321 /// parsing of the table will be reported through this handler. 322 /// \param UnrecoverableErrorHandler - any issues that prevent further 323 /// parsing of the table will be reported through this handler. 324 /// \param OS - if not null, the parser will print information about the 325 /// table as it parses it. 326 /// \param Verbose - if true, the parser will print verbose information when 327 /// printing to the output. 328 LineTable parseNext(function_ref<void(Error)> RecoverableErrorHandler, 329 function_ref<void(Error)> UnrecoverableErrorHandler, 330 raw_ostream *OS = nullptr, bool Verbose = false); 331 332 /// Skip the current line table and go to the following line table (if 333 /// present) immediately. 334 /// 335 /// \param RecoverableErrorHandler - report any recoverable prologue 336 /// parsing issues via this handler. 337 /// \param UnrecoverableErrorHandler - report any unrecoverable prologue 338 /// parsing issues via this handler. 339 void skip(function_ref<void(Error)> RecoverableErrorHandler, 340 function_ref<void(Error)> UnrecoverableErrorHandler); 341 342 /// Indicates if the parser has parsed as much as possible. 343 /// 344 /// \note Certain problems with the line table structure might mean that 345 /// parsing stops before the end of the section is reached. 346 bool done() const { return Done; } 347 348 /// Get the offset the parser has reached. 349 uint64_t getOffset() const { return Offset; } 350 351 private: 352 DWARFUnit *prepareToParse(uint64_t Offset); 353 void moveToNextTable(uint64_t OldOffset, const Prologue &P); 354 355 LineToUnitMap LineToUnit; 356 357 DWARFDataExtractor &DebugLineData; 358 const DWARFContext &Context; 359 uint64_t Offset = 0; 360 bool Done = false; 361 }; 362 363 private: 364 struct ParsingState { 365 ParsingState(struct LineTable *LT, uint64_t TableOffset, 366 function_ref<void(Error)> ErrorHandler); 367 368 void resetRowAndSequence(); 369 void appendRowToMatrix(); 370 371 /// Advance the address by the \p OperationAdvance value. \returns the 372 /// amount advanced by. 373 uint64_t advanceAddr(uint64_t OperationAdvance, uint8_t Opcode, 374 uint64_t OpcodeOffset); 375 376 struct AddrAndAdjustedOpcode { 377 uint64_t AddrDelta; 378 uint8_t AdjustedOpcode; 379 }; 380 381 /// Advance the address as required by the specified \p Opcode. 382 /// \returns the amount advanced by and the calculated adjusted opcode. 383 AddrAndAdjustedOpcode advanceAddrForOpcode(uint8_t Opcode, 384 uint64_t OpcodeOffset); 385 386 struct AddrAndLineDelta { 387 uint64_t Address; 388 int32_t Line; 389 }; 390 391 /// Advance the line and address as required by the specified special \p 392 /// Opcode. \returns the address and line delta. 393 AddrAndLineDelta handleSpecialOpcode(uint8_t Opcode, uint64_t OpcodeOffset); 394 395 /// Line table we're currently parsing. 396 struct LineTable *LineTable; 397 struct Row Row; 398 struct Sequence Sequence; 399 400 private: 401 uint64_t LineTableOffset; 402 403 bool ReportAdvanceAddrProblem = true; 404 bool ReportBadLineRange = true; 405 function_ref<void(Error)> ErrorHandler; 406 }; 407 408 using LineTableMapTy = std::map<uint64_t, LineTable>; 409 using LineTableIter = LineTableMapTy::iterator; 410 using LineTableConstIter = LineTableMapTy::const_iterator; 411 412 LineTableMapTy LineTableMap; 413 }; 414 415 } // end namespace llvm 416 417 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H 418