LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugLine.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 409 448 91.3 %
Date: 2018-02-17 17:14:17 Functions: 29 29 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFDebugLine.cpp -------------------------------------------------===//
       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 "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
      11             : #include "llvm/ADT/SmallString.h"
      12             : #include "llvm/ADT/SmallVector.h"
      13             : #include "llvm/ADT/StringRef.h"
      14             : #include "llvm/BinaryFormat/Dwarf.h"
      15             : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
      16             : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
      17             : #include "llvm/Support/Format.h"
      18             : #include "llvm/Support/Path.h"
      19             : #include "llvm/Support/raw_ostream.h"
      20             : #include <algorithm>
      21             : #include <cassert>
      22             : #include <cinttypes>
      23             : #include <cstdint>
      24             : #include <cstdio>
      25             : #include <utility>
      26             : 
      27             : using namespace llvm;
      28             : using namespace dwarf;
      29             : 
      30             : using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
      31             : 
      32             : namespace {
      33             : 
      34             : struct ContentDescriptor {
      35             :   dwarf::LineNumberEntryFormat Type;
      36             :   dwarf::Form Form;
      37             : };
      38             : 
      39             : using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
      40             : 
      41             : } // end anonmyous namespace
      42             : 
      43        2714 : DWARFDebugLine::Prologue::Prologue() { clear(); }
      44             : 
      45        5388 : void DWARFDebugLine::Prologue::clear() {
      46        5388 :   TotalLength = PrologueLength = 0;
      47        5388 :   SegSelectorSize = 0;
      48        5388 :   MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
      49        5388 :   OpcodeBase = 0;
      50        5388 :   FormParams = DWARFFormParams({0, 0, DWARF32});
      51        5388 :   HasMD5 = false;
      52             :   StandardOpcodeLengths.clear();
      53             :   IncludeDirectories.clear();
      54             :   FileNames.clear();
      55        5388 : }
      56             : 
      57         302 : void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
      58             :                                     DIDumpOptions DumpOptions) const {
      59         302 :   OS << "Line table prologue:\n"
      60         604 :      << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength)
      61         302 :      << format("         version: %u\n", getVersion());
      62         302 :   if (getVersion() >= 5)
      63          46 :     OS << format("    address_size: %u\n", getAddressSize())
      64          23 :        << format(" seg_select_size: %u\n", SegSelectorSize);
      65         604 :   OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
      66         604 :      << format(" min_inst_length: %u\n", MinInstLength)
      67         906 :      << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
      68         604 :      << format(" default_is_stmt: %u\n", DefaultIsStmt)
      69         604 :      << format("       line_base: %i\n", LineBase)
      70         604 :      << format("      line_range: %u\n", LineRange)
      71         302 :      << format("     opcode_base: %u\n", OpcodeBase);
      72             : 
      73       10468 :   for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
      74        3288 :     OS << format("standard_opcode_lengths[%s] = %u\n",
      75        6576 :                  LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
      76             : 
      77         302 :   if (!IncludeDirectories.empty()) {
      78             :     // DWARF v5 starts directory indexes at 0.
      79          45 :     uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
      80         267 :     for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {
      81         118 :       OS << format("include_directories[%3u] = ", I + DirBase);
      82          59 :       IncludeDirectories[I].dump(OS, DumpOptions);
      83             :       OS << '\n';
      84             :     }
      85             :   }
      86             : 
      87         302 :   if (!FileNames.empty()) {
      88         272 :     if (HasMD5)
      89          12 :       OS << "                Dir  MD5 Checksum                     File Name\n"
      90          12 :          << "                ---- -------------------------------- -----------"
      91             :             "---------------\n";
      92             :     else
      93         260 :       OS << "                Dir  Mod Time   File Len   File Name\n"
      94         260 :          << "                ---- ---------- ---------- -----------"
      95             :             "----------------\n";
      96             :     // DWARF v5 starts file indexes at 0.
      97         272 :     uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
      98        1498 :     for (uint32_t I = 0; I != FileNames.size(); ++I) {
      99             :       const FileNameEntry &FileEntry = FileNames[I];
     100         636 :       OS << format("file_names[%3u] %4" PRIu64 " ", I + FileBase,
     101             :                    FileEntry.DirIdx);
     102         318 :       if (HasMD5)
     103          30 :         OS << FileEntry.Checksum.digest();
     104             :       else
     105         303 :         OS << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64, FileEntry.ModTime,
     106             :                      FileEntry.Length);
     107             :       OS << ' ';
     108         318 :       FileEntry.Name.dump(OS, DumpOptions);
     109             :       OS << '\n';
     110             :     }
     111             :   }
     112         302 : }
     113             : 
     114             : // Parse v2-v4 directory and file tables.
     115             : static void
     116        1182 : parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
     117             :                      uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
     118             :                      std::vector<DWARFFormValue> &IncludeDirectories,
     119             :                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
     120        1896 :   while (*OffsetPtr < EndPrologueOffset) {
     121        1539 :     StringRef S = DebugLineData.getCStrRef(OffsetPtr);
     122        1539 :     if (S.empty())
     123             :       break;
     124             :     DWARFFormValue Dir(dwarf::DW_FORM_string);
     125             :     Dir.setPValue(S.data());
     126         357 :     IncludeDirectories.push_back(Dir);
     127             :   }
     128             : 
     129        4544 :   while (*OffsetPtr < EndPrologueOffset) {
     130        2863 :     StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
     131        2863 :     if (Name.empty())
     132             :       break;
     133             :     DWARFDebugLine::FileNameEntry FileEntry;
     134             :     FileEntry.Name.setForm(dwarf::DW_FORM_string);
     135             :     FileEntry.Name.setPValue(Name.data());
     136        1681 :     FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
     137        1681 :     FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
     138        1681 :     FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
     139        1681 :     FileNames.push_back(FileEntry);
     140             :   }
     141        1182 : }
     142             : 
     143             : // Parse v5 directory/file entry content descriptions.
     144             : // Returns the descriptors, or an empty vector if we did not find a path or
     145             : // ran off the end of the prologue.
     146             : static ContentDescriptors
     147          77 : parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
     148             :                    uint64_t EndPrologueOffset, bool *HasMD5) {
     149             :   ContentDescriptors Descriptors;
     150          77 :   int FormatCount = DebugLineData.getU8(OffsetPtr);
     151             :   bool HasPath = false;
     152         369 :   for (int I = 0; I != FormatCount; ++I) {
     153         146 :     if (*OffsetPtr >= EndPrologueOffset)
     154           0 :       return ContentDescriptors();
     155             :     ContentDescriptor Descriptor;
     156         146 :     Descriptor.Type =
     157         146 :       dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
     158         146 :     Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
     159         146 :     if (Descriptor.Type == dwarf::DW_LNCT_path)
     160             :       HasPath = true;
     161          69 :     else if (Descriptor.Type == dwarf::DW_LNCT_MD5 && HasMD5)
     162          20 :       *HasMD5 = true;
     163         146 :     Descriptors.push_back(Descriptor);
     164             :   }
     165          77 :   return HasPath ? Descriptors : ContentDescriptors();
     166             : }
     167             : 
     168             : static bool
     169          39 : parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
     170             :                      uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
     171             :                      const DWARFFormParams &FormParams, const DWARFContext &Ctx,
     172             :                      const DWARFUnit *U, bool &HasMD5,
     173             :                      std::vector<DWARFFormValue> &IncludeDirectories,
     174             :                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
     175             :   // Get the directory entry description.
     176             :   ContentDescriptors DirDescriptors =
     177          39 :       parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr);
     178          39 :   if (DirDescriptors.empty())
     179             :     return false;
     180             : 
     181             :   // Get the directory entries, according to the format described above.
     182          39 :   int DirEntryCount = DebugLineData.getU8(OffsetPtr);
     183         131 :   for (int I = 0; I != DirEntryCount; ++I) {
     184          47 :     if (*OffsetPtr >= EndPrologueOffset)
     185             :       return false;
     186         139 :     for (auto Descriptor : DirDescriptors) {
     187          47 :       DWARFFormValue Value(Descriptor.Form);
     188          47 :       switch (Descriptor.Type) {
     189          46 :       case DW_LNCT_path:
     190          46 :         if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
     191           1 :           return false;
     192          46 :         IncludeDirectories.push_back(Value);
     193          46 :         break;
     194           1 :       default:
     195           1 :         if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
     196             :           return false;
     197             :       }
     198             :     }
     199             :   }
     200             : 
     201             :   // Get the file entry description.
     202             :   ContentDescriptors FileDescriptors =
     203          38 :       parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, &HasMD5);
     204          38 :   if (FileDescriptors.empty())
     205             :     return false;
     206             : 
     207             :   // Get the file entries, according to the format described above.
     208          38 :   int FileEntryCount = DebugLineData.getU8(OffsetPtr);
     209         128 :   for (int I = 0; I != FileEntryCount; ++I) {
     210          46 :     if (*OffsetPtr >= EndPrologueOffset)
     211           1 :       return false;
     212             :     DWARFDebugLine::FileNameEntry FileEntry;
     213         303 :     for (auto Descriptor : FileDescriptors) {
     214             :       DWARFFormValue Value(Descriptor.Form);
     215         129 :       if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
     216           0 :         return false;
     217         129 :       switch (Descriptor.Type) {
     218          45 :       case DW_LNCT_path:
     219          45 :         FileEntry.Name = Value;
     220          45 :         break;
     221          45 :       case DW_LNCT_directory_index:
     222          45 :         FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
     223          45 :         break;
     224           8 :       case DW_LNCT_timestamp:
     225           8 :         FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
     226           8 :         break;
     227           8 :       case DW_LNCT_size:
     228           8 :         FileEntry.Length = Value.getAsUnsignedConstant().getValue();
     229           8 :         break;
     230             :       case DW_LNCT_MD5:
     231             :         assert(Value.getAsBlock().getValue().size() == 16);
     232          46 :         std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16,
     233             :                                   FileEntry.Checksum.Bytes.begin());
     234          23 :         break;
     235             :       default:
     236             :         break;
     237             :       }
     238             :     }
     239          45 :     FileNames.push_back(FileEntry);
     240             :   }
     241             :   return true;
     242             : }
     243             : 
     244        1357 : bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
     245             :                                      uint32_t *OffsetPtr,
     246             :                                      const DWARFContext &Ctx,
     247             :                                      const DWARFUnit *U) {
     248        1357 :   const uint64_t PrologueOffset = *OffsetPtr;
     249             : 
     250        1357 :   clear();
     251        1357 :   TotalLength = DebugLineData.getU32(OffsetPtr);
     252        1357 :   if (TotalLength == UINT32_MAX) {
     253           6 :     FormParams.Format = dwarf::DWARF64;
     254           6 :     TotalLength = DebugLineData.getU64(OffsetPtr);
     255        1351 :   } else if (TotalLength >= 0xffffff00) {
     256             :     return false;
     257             :   }
     258        1357 :   FormParams.Version = DebugLineData.getU16(OffsetPtr);
     259        1357 :   if (getVersion() < 2)
     260             :     return false;
     261             : 
     262        1221 :   if (getVersion() >= 5) {
     263          39 :     FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
     264             :     assert((DebugLineData.getAddressSize() == 0 ||
     265             :             DebugLineData.getAddressSize() == getAddressSize()) &&
     266             :            "Line table header and data extractor disagree");
     267          39 :     SegSelectorSize = DebugLineData.getU8(OffsetPtr);
     268             :   }
     269             : 
     270        1221 :   PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
     271        1221 :   const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
     272        1221 :   MinInstLength = DebugLineData.getU8(OffsetPtr);
     273        1221 :   if (getVersion() >= 4)
     274         339 :     MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
     275        1221 :   DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
     276        1221 :   LineBase = DebugLineData.getU8(OffsetPtr);
     277        1221 :   LineRange = DebugLineData.getU8(OffsetPtr);
     278        1221 :   OpcodeBase = DebugLineData.getU8(OffsetPtr);
     279             : 
     280        1221 :   StandardOpcodeLengths.reserve(OpcodeBase - 1);
     281       29967 :   for (uint32_t I = 1; I < OpcodeBase; ++I) {
     282       14373 :     uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
     283       14373 :     StandardOpcodeLengths.push_back(OpLen);
     284             :   }
     285             : 
     286        1221 :   if (getVersion() >= 5) {
     287          39 :     if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
     288             :                               FormParams, Ctx, U, HasMD5, IncludeDirectories,
     289             :                               FileNames)) {
     290           2 :       fprintf(stderr,
     291             :               "warning: parsing line table prologue at 0x%8.8" PRIx64
     292             :               " found an invalid directory or file table description at"
     293           2 :               " 0x%8.8" PRIx64 "\n", PrologueOffset, (uint64_t)*OffsetPtr);
     294           2 :       return false;
     295             :     }
     296             :   } else
     297        1182 :     parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
     298             :                          IncludeDirectories, FileNames);
     299             : 
     300        1219 :   if (*OffsetPtr != EndPrologueOffset) {
     301           2 :     fprintf(stderr,
     302             :             "warning: parsing line table prologue at 0x%8.8" PRIx64
     303             :             " should have ended at 0x%8.8" PRIx64
     304             :             " but it ended at 0x%8.8" PRIx64 "\n",
     305             :             PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
     306           2 :     return false;
     307             :   }
     308             :   return true;
     309             : }
     310             : 
     311        1919 : DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
     312             : 
     313        7281 : void DWARFDebugLine::Row::postAppend() {
     314        7281 :   BasicBlock = false;
     315        7281 :   PrologueEnd = false;
     316        7281 :   EpilogueBegin = false;
     317        7281 : }
     318             : 
     319        4285 : void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
     320        4285 :   Address = 0;
     321        4285 :   Line = 1;
     322        4285 :   Column = 0;
     323        4285 :   File = 1;
     324        4285 :   Isa = 0;
     325        4285 :   Discriminator = 0;
     326        4285 :   IsStmt = DefaultIsStmt;
     327        4285 :   BasicBlock = false;
     328        4285 :   EndSequence = false;
     329        4285 :   PrologueEnd = false;
     330        4285 :   EpilogueBegin = false;
     331        4285 : }
     332             : 
     333         124 : void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
     334         124 :   OS << "Address            Line   Column File   ISA Discriminator Flags\n"
     335         124 :      << "------------------ ------ ------ ------ --- ------------- "
     336             :         "-------------\n";
     337         124 : }
     338             : 
     339        1597 : void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
     340        3194 :   OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
     341        3194 :      << format(" %6u %3u %13u ", File, Isa, Discriminator)
     342        1597 :      << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
     343        1597 :      << (PrologueEnd ? " prologue_end" : "")
     344        1597 :      << (EpilogueBegin ? " epilogue_begin" : "")
     345        1597 :      << (EndSequence ? " end_sequence" : "") << '\n';
     346        1597 : }
     347             : 
     348        2587 : DWARFDebugLine::Sequence::Sequence() { reset(); }
     349             : 
     350        6140 : void DWARFDebugLine::Sequence::reset() {
     351        6140 :   LowPC = 0;
     352        6140 :   HighPC = 0;
     353        6140 :   FirstRowIndex = 0;
     354        6140 :   LastRowIndex = 0;
     355        6140 :   Empty = true;
     356        6140 : }
     357             : 
     358        2714 : DWARFDebugLine::LineTable::LineTable() { clear(); }
     359             : 
     360         159 : void DWARFDebugLine::LineTable::dump(raw_ostream &OS,
     361             :                                      DIDumpOptions DumpOptions) const {
     362         159 :   Prologue.dump(OS, DumpOptions);
     363             :   OS << '\n';
     364             : 
     365         159 :   if (!Rows.empty()) {
     366         122 :     Row::dumpTableHeader(OS);
     367         907 :     for (const Row &R : Rows) {
     368         785 :       R.dump(OS);
     369             :     }
     370             :   }
     371         159 : }
     372             : 
     373        2674 : void DWARFDebugLine::LineTable::clear() {
     374        2674 :   Prologue.clear();
     375             :   Rows.clear();
     376             :   Sequences.clear();
     377        2674 : }
     378             : 
     379        1179 : DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
     380        1179 :     : LineTable(LT) {
     381        1179 :   resetRowAndSequence();
     382        1179 : }
     383             : 
     384        2366 : void DWARFDebugLine::ParsingState::resetRowAndSequence() {
     385        2366 :   Row.reset(LineTable->Prologue.DefaultIsStmt);
     386        2366 :   Sequence.reset();
     387        2366 : }
     388             : 
     389        7281 : void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
     390        7281 :   if (Sequence.Empty) {
     391             :     // Record the beginning of instruction sequence.
     392        1187 :     Sequence.Empty = false;
     393        1187 :     Sequence.LowPC = Row.Address;
     394        1187 :     Sequence.FirstRowIndex = RowNumber;
     395             :   }
     396        7281 :   ++RowNumber;
     397        7281 :   LineTable->appendRow(Row);
     398        7281 :   if (Row.EndSequence) {
     399             :     // Record the end of instruction sequence.
     400        1187 :     Sequence.HighPC = Row.Address;
     401        1187 :     Sequence.LastRowIndex = RowNumber;
     402             :     if (Sequence.isValid())
     403        1170 :       LineTable->appendSequence(Sequence);
     404        1187 :     Sequence.reset();
     405             :   }
     406        7281 :   Row.postAppend();
     407        7281 : }
     408             : 
     409             : const DWARFDebugLine::LineTable *
     410        5549 : DWARFDebugLine::getLineTable(uint32_t Offset) const {
     411             :   LineTableConstIter Pos = LineTableMap.find(Offset);
     412        5549 :   if (Pos != LineTableMap.end())
     413        4806 :     return &Pos->second;
     414             :   return nullptr;
     415             : }
     416             : 
     417             : const DWARFDebugLine::LineTable *
     418         890 : DWARFDebugLine::getOrParseLineTable(DWARFDataExtractor &DebugLineData,
     419             :                                     uint32_t Offset, const DWARFContext &Ctx,
     420             :                                     const DWARFUnit *U) {
     421             :   std::pair<LineTableIter, bool> Pos =
     422        1780 :       LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
     423         890 :   LineTable *LT = &Pos.first->second;
     424         890 :   if (Pos.second) {
     425         890 :     if (!LT->parse(DebugLineData, &Offset, Ctx, U))
     426             :       return nullptr;
     427             :   }
     428             :   return LT;
     429             : }
     430             : 
     431        1317 : bool DWARFDebugLine::LineTable::parse(DWARFDataExtractor &DebugLineData,
     432             :                                       uint32_t *OffsetPtr,
     433             :                                       const DWARFContext &Ctx,
     434             :                                       const DWARFUnit *U, raw_ostream *OS) {
     435        1317 :   const uint32_t DebugLineOffset = *OffsetPtr;
     436             : 
     437        1317 :   clear();
     438             : 
     439        1317 :   if (!Prologue.parse(DebugLineData, OffsetPtr, Ctx, U)) {
     440             :     // Restore our offset and return false to indicate failure!
     441         138 :     *OffsetPtr = DebugLineOffset;
     442         138 :     return false;
     443             :   }
     444             : 
     445        1179 :   if (OS) {
     446             :     // The presence of OS signals verbose dumping.
     447         143 :     DIDumpOptions DumpOptions;
     448         143 :     DumpOptions.Verbose = true;
     449         143 :     Prologue.dump(*OS, DumpOptions);
     450             :   }
     451             : 
     452             :   const uint32_t EndOffset =
     453        2358 :       DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
     454             : 
     455             :   // See if we should tell the data extractor the address size.
     456        1179 :   if (DebugLineData.getAddressSize() == 0)
     457             :     DebugLineData.setAddressSize(Prologue.getAddressSize());
     458             :   else
     459             :     assert(Prologue.getAddressSize() == 0 ||
     460             :            Prologue.getAddressSize() == DebugLineData.getAddressSize());
     461             : 
     462        1179 :   ParsingState State(this);
     463             : 
     464       18372 :   while (*OffsetPtr < EndOffset) {
     465       17195 :     if (OS)
     466        1904 :       *OS << format("0x%08.08" PRIx32 ": ", *OffsetPtr);
     467             : 
     468       17195 :     uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
     469             : 
     470       17195 :     if (OS)
     471        1904 :       *OS << format("%02.02" PRIx8 " ", Opcode);
     472             : 
     473       17195 :     if (Opcode == 0) {
     474             :       // Extended Opcodes always start with a zero opcode followed by
     475             :       // a uleb128 length so you can skip ones you don't know about
     476        2755 :       uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
     477        2755 :       uint32_t ExtOffset = *OffsetPtr;
     478             : 
     479             :       // Tolerate zero-length; assume length is correct and soldier on.
     480        2757 :       if (Len == 0) {
     481           2 :         if (OS)
     482           2 :           *OS << "Badly formed extended line op (length 0)\n";
     483             :         continue;
     484             :       }
     485             : 
     486        2753 :       uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
     487        2753 :       if (OS)
     488         223 :         *OS << LNExtendedString(SubOpcode);
     489        2753 :       switch (SubOpcode) {
     490        1187 :       case DW_LNE_end_sequence:
     491             :         // Set the end_sequence register of the state machine to true and
     492             :         // append a row to the matrix using the current values of the
     493             :         // state-machine registers. Then reset the registers to the initial
     494             :         // values specified above. Every statement program sequence must end
     495             :         // with a DW_LNE_end_sequence instruction which creates a row whose
     496             :         // address is that of the byte after the last target machine instruction
     497             :         // of the sequence.
     498        1187 :         State.Row.EndSequence = true;
     499        1187 :         State.appendRowToMatrix(*OffsetPtr);
     500        1187 :         if (OS) {
     501         111 :           *OS << "\n";
     502         111 :           OS->indent(12);
     503         111 :           State.Row.dump(*OS);
     504             :         }
     505        1187 :         State.resetRowAndSequence();
     506        1187 :         break;
     507             : 
     508        1176 :       case DW_LNE_set_address:
     509             :         // Takes a single relocatable address as an operand. The size of the
     510             :         // operand is the size appropriate to hold an address on the target
     511             :         // machine. Set the address register to the value given by the
     512             :         // relocatable address. All of the other statement program opcodes
     513             :         // that affect the address register add a delta to it. This instruction
     514             :         // stores a relocatable value into it instead.
     515             :         //
     516             :         // Make sure the extractor knows the address size.  If not, infer it
     517             :         // from the size of the operand.
     518        1176 :         if (DebugLineData.getAddressSize() == 0)
     519           3 :           DebugLineData.setAddressSize(Len - 1);
     520             :         else
     521             :           assert(DebugLineData.getAddressSize() == Len - 1);
     522        1176 :         State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr);
     523        1176 :         if (OS)
     524         110 :           *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address);
     525             :         break;
     526             : 
     527             :       case DW_LNE_define_file:
     528             :         // Takes 4 arguments. The first is a null terminated string containing
     529             :         // a source file name. The second is an unsigned LEB128 number
     530             :         // representing the directory index of the directory in which the file
     531             :         // was found. The third is an unsigned LEB128 number representing the
     532             :         // time of last modification of the file. The fourth is an unsigned
     533             :         // LEB128 number representing the length in bytes of the file. The time
     534             :         // and length fields may contain LEB128(0) if the information is not
     535             :         // available.
     536             :         //
     537             :         // The directory index represents an entry in the include_directories
     538             :         // section of the statement program prologue. The index is LEB128(0)
     539             :         // if the file was found in the current directory of the compilation,
     540             :         // LEB128(1) if it was found in the first directory in the
     541             :         // include_directories section, and so on. The directory index is
     542             :         // ignored for file names that represent full path names.
     543             :         //
     544             :         // The files are numbered, starting at 1, in the order in which they
     545             :         // appear; the names in the prologue come before names defined by
     546             :         // the DW_LNE_define_file instruction. These numbers are used in the
     547             :         // the file register of the state machine.
     548             :         {
     549             :           FileNameEntry FileEntry;
     550           0 :           const char *Name = DebugLineData.getCStr(OffsetPtr);
     551             :           FileEntry.Name.setForm(dwarf::DW_FORM_string);
     552             :           FileEntry.Name.setPValue(Name);
     553           0 :           FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
     554           0 :           FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
     555           0 :           FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
     556           0 :           Prologue.FileNames.push_back(FileEntry);
     557           0 :           if (OS)
     558           0 :             *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
     559           0 :                 << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)
     560           0 :                 << ", length=" << FileEntry.Length << ")";
     561             :         }
     562           0 :         break;
     563             : 
     564         388 :       case DW_LNE_set_discriminator:
     565         388 :         State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
     566         388 :         if (OS)
     567           0 :           *OS << " (" << State.Row.Discriminator << ")";
     568             :         break;
     569             : 
     570           2 :       default:
     571           2 :         if (OS)
     572           4 :           *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
     573           2 :               << format(" length %" PRIx64, Len);
     574             :         // Len doesn't include the zero opcode byte or the length itself, but
     575             :         // it does include the sub_opcode, so we have to adjust for that.
     576           2 :         (*OffsetPtr) += Len - 1;
     577           2 :         break;
     578             :       }
     579             :       // Make sure the stated and parsed lengths are the same.
     580             :       // Otherwise we have an unparseable line-number program.
     581        2753 :       if (*OffsetPtr - ExtOffset != Len) {
     582           2 :         fprintf(stderr, "Unexpected line op length at offset 0x%8.8" PRIx32
     583             :                 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32 "\n",
     584             :                 ExtOffset, Len, *OffsetPtr - ExtOffset);
     585             :         // Skip the rest of the line-number program.
     586           2 :         *OffsetPtr = EndOffset;
     587             :         return false;
     588             :       }
     589       14440 :     } else if (Opcode < Prologue.OpcodeBase) {
     590        9178 :       if (OS)
     591        1045 :         *OS << LNStandardString(Opcode);
     592        9178 :       switch (Opcode) {
     593             :       // Standard Opcodes
     594         832 :       case DW_LNS_copy:
     595             :         // Takes no arguments. Append a row to the matrix using the
     596             :         // current values of the state-machine registers. Then set
     597             :         // the basic_block register to false.
     598         832 :         State.appendRowToMatrix(*OffsetPtr);
     599         832 :         if (OS) {
     600          64 :           *OS << "\n";
     601          64 :           OS->indent(12);
     602          64 :           State.Row.dump(*OS);
     603          64 :           *OS << "\n";
     604             :         }
     605             :         break;
     606             : 
     607        1559 :       case DW_LNS_advance_pc:
     608             :         // Takes a single unsigned LEB128 operand, multiplies it by the
     609             :         // min_inst_length field of the prologue, and adds the
     610             :         // result to the address register of the state machine.
     611             :         {
     612             :           uint64_t AddrOffset =
     613        1559 :               DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
     614        1559 :           State.Row.Address += AddrOffset;
     615        1559 :           if (OS)
     616         143 :             *OS << " (" << AddrOffset << ")";
     617             :         }
     618             :         break;
     619             : 
     620        1014 :       case DW_LNS_advance_line:
     621             :         // Takes a single signed LEB128 operand and adds that value to
     622             :         // the line register of the state machine.
     623        1014 :         State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
     624        1014 :         if (OS)
     625         226 :           *OS << " (" << State.Row.Line << ")";
     626             :         break;
     627             : 
     628         139 :       case DW_LNS_set_file:
     629             :         // Takes a single unsigned LEB128 operand and stores it in the file
     630             :         // register of the state machine.
     631         139 :         State.Row.File = DebugLineData.getULEB128(OffsetPtr);
     632         139 :         if (OS)
     633          20 :           *OS << " (" << State.Row.File << ")";
     634             :         break;
     635             : 
     636        2181 :       case DW_LNS_set_column:
     637             :         // Takes a single unsigned LEB128 operand and stores it in the
     638             :         // column register of the state machine.
     639        2181 :         State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
     640        2181 :         if (OS)
     641         566 :           *OS << " (" << State.Row.Column << ")";
     642             :         break;
     643             : 
     644        1004 :       case DW_LNS_negate_stmt:
     645             :         // Takes no arguments. Set the is_stmt register of the state
     646             :         // machine to the logical negation of its current value.
     647        1004 :         State.Row.IsStmt = !State.Row.IsStmt;
     648        1004 :         break;
     649             : 
     650           0 :       case DW_LNS_set_basic_block:
     651             :         // Takes no arguments. Set the basic_block register of the
     652             :         // state machine to true
     653           0 :         State.Row.BasicBlock = true;
     654           0 :         break;
     655             : 
     656         862 :       case DW_LNS_const_add_pc:
     657             :         // Takes no arguments. Add to the address register of the state
     658             :         // machine the address increment value corresponding to special
     659             :         // opcode 255. The motivation for DW_LNS_const_add_pc is this:
     660             :         // when the statement program needs to advance the address by a
     661             :         // small amount, it can use a single special opcode, which occupies
     662             :         // a single byte. When it needs to advance the address by up to
     663             :         // twice the range of the last special opcode, it can use
     664             :         // DW_LNS_const_add_pc followed by a special opcode, for a total
     665             :         // of two bytes. Only if it needs to advance the address by more
     666             :         // than twice that range will it need to use both DW_LNS_advance_pc
     667             :         // and a special opcode, requiring three or more bytes.
     668             :         {
     669         862 :           uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
     670             :           uint64_t AddrOffset =
     671         862 :               (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
     672         862 :           State.Row.Address += AddrOffset;
     673         862 :           if (OS)
     674             :             *OS
     675         113 :                 << format(" (0x%16.16" PRIx64 ")", AddrOffset);
     676             :         }
     677             :         break;
     678             : 
     679           0 :       case DW_LNS_fixed_advance_pc:
     680             :         // Takes a single uhalf operand. Add to the address register of
     681             :         // the state machine the value of the (unencoded) operand. This
     682             :         // is the only extended opcode that takes an argument that is not
     683             :         // a variable length number. The motivation for DW_LNS_fixed_advance_pc
     684             :         // is this: existing assemblers cannot emit DW_LNS_advance_pc or
     685             :         // special opcodes because they cannot encode LEB128 numbers or
     686             :         // judge when the computation of a special opcode overflows and
     687             :         // requires the use of DW_LNS_advance_pc. Such assemblers, however,
     688             :         // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
     689             :         {
     690           0 :           uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
     691           0 :           State.Row.Address += PCOffset;
     692           0 :           if (OS)
     693             :             *OS
     694           0 :                 << format(" (0x%16.16" PRIx64 ")", PCOffset);
     695             :         }
     696             :         break;
     697             : 
     698        1587 :       case DW_LNS_set_prologue_end:
     699             :         // Takes no arguments. Set the prologue_end register of the
     700             :         // state machine to true
     701        1587 :         State.Row.PrologueEnd = true;
     702        1587 :         break;
     703             : 
     704           0 :       case DW_LNS_set_epilogue_begin:
     705             :         // Takes no arguments. Set the basic_block register of the
     706             :         // state machine to true
     707           0 :         State.Row.EpilogueBegin = true;
     708           0 :         break;
     709             : 
     710           0 :       case DW_LNS_set_isa:
     711             :         // Takes a single unsigned LEB128 operand and stores it in the
     712             :         // column register of the state machine.
     713           0 :         State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
     714           0 :         if (OS)
     715           0 :           *OS << " (" << State.Row.Isa << ")";
     716             :         break;
     717             : 
     718           0 :       default:
     719             :         // Handle any unknown standard opcodes here. We know the lengths
     720             :         // of such opcodes because they are specified in the prologue
     721             :         // as a multiple of LEB128 operands for each opcode.
     722             :         {
     723             :           assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
     724           0 :           uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
     725           0 :           for (uint8_t I = 0; I < OpcodeLength; ++I) {
     726           0 :             uint64_t Value = DebugLineData.getULEB128(OffsetPtr);
     727           0 :             if (OS)
     728           0 :               *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
     729             :                             Value);
     730           0 :           }
     731             :         }
     732             :         break;
     733             :       }
     734             :     } else {
     735             :       // Special Opcodes
     736             : 
     737             :       // A special opcode value is chosen based on the amount that needs
     738             :       // to be added to the line and address registers. The maximum line
     739             :       // increment for a special opcode is the value of the line_base
     740             :       // field in the header, plus the value of the line_range field,
     741             :       // minus 1 (line base + line range - 1). If the desired line
     742             :       // increment is greater than the maximum line increment, a standard
     743             :       // opcode must be used instead of a special opcode. The "address
     744             :       // advance" is calculated by dividing the desired address increment
     745             :       // by the minimum_instruction_length field from the header. The
     746             :       // special opcode is then calculated using the following formula:
     747             :       //
     748             :       //  opcode = (desired line increment - line_base) +
     749             :       //           (line_range * address advance) + opcode_base
     750             :       //
     751             :       // If the resulting opcode is greater than 255, a standard opcode
     752             :       // must be used instead.
     753             :       //
     754             :       // To decode a special opcode, subtract the opcode_base from the
     755             :       // opcode itself to give the adjusted opcode. The amount to
     756             :       // increment the address register is the result of the adjusted
     757             :       // opcode divided by the line_range multiplied by the
     758             :       // minimum_instruction_length field from the header. That is:
     759             :       //
     760             :       //  address increment = (adjusted opcode / line_range) *
     761             :       //                      minimum_instruction_length
     762             :       //
     763             :       // The amount to increment the line register is the line_base plus
     764             :       // the result of the adjusted opcode modulo the line_range. That is:
     765             :       //
     766             :       // line increment = line_base + (adjusted opcode % line_range)
     767             : 
     768        5262 :       uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
     769        5262 :       uint64_t AddrOffset =
     770        5262 :           (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
     771        5262 :       int32_t LineOffset =
     772        5262 :           Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
     773        5262 :       State.Row.Line += LineOffset;
     774        5262 :       State.Row.Address += AddrOffset;
     775             : 
     776        5262 :       if (OS) {
     777         634 :         *OS << "address += " << ((uint32_t)AdjustOpcode)
     778        1268 :             << ",  line += " << LineOffset << "\n";
     779         634 :         OS->indent(12);
     780         634 :         State.Row.dump(*OS);
     781             :       }
     782             : 
     783        5262 :       State.appendRowToMatrix(*OffsetPtr);
     784             :       // Reset discriminator to 0.
     785        5262 :       State.Row.Discriminator = 0;
     786             :     }
     787       17191 :     if(OS)
     788        1900 :       *OS << "\n";
     789             :   }
     790             : 
     791        1177 :   if (!State.Sequence.Empty) {
     792           0 :     fprintf(stderr, "warning: last sequence in debug line table is not"
     793             :                     "terminated!\n");
     794             :   }
     795             : 
     796             :   // Sort all sequences so that address lookup will work faster.
     797        1177 :   if (!Sequences.empty()) {
     798             :     std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
     799             :     // Note: actually, instruction address ranges of sequences should not
     800             :     // overlap (in shared objects and executables). If they do, the address
     801             :     // lookup would still work, though, but result would be ambiguous.
     802             :     // We don't report warning in this case. For example,
     803             :     // sometimes .so compiled from multiple object files contains a few
     804             :     // rudimentary sequences for address ranges [0x0, 0xsomething).
     805             :   }
     806             : 
     807        1177 :   return EndOffset;
     808             : }
     809             : 
     810             : uint32_t
     811         741 : DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
     812             :                                         uint64_t Address) const {
     813             :   if (!Seq.containsPC(Address))
     814           1 :     return UnknownRowIndex;
     815             :   // Search for instruction address in the rows describing the sequence.
     816             :   // Rows are stored in a vector, so we may use arithmetical operations with
     817             :   // iterators.
     818         740 :   DWARFDebugLine::Row Row;
     819         740 :   Row.Address = Address;
     820         740 :   RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
     821         740 :   RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
     822             :   LineTable::RowIter RowPos = std::lower_bound(
     823             :       FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress);
     824         740 :   if (RowPos == LastRow) {
     825           0 :     return Seq.LastRowIndex - 1;
     826             :   }
     827         740 :   uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
     828         740 :   if (RowPos->Address > Address) {
     829         544 :     if (RowPos == FirstRow)
     830           0 :       return UnknownRowIndex;
     831             :     else
     832         544 :       Index--;
     833             :   }
     834             :   return Index;
     835             : }
     836             : 
     837        2684 : uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const {
     838        2684 :   if (Sequences.empty())
     839        1993 :     return UnknownRowIndex;
     840             :   // First, find an instruction sequence containing the given address.
     841         691 :   DWARFDebugLine::Sequence Sequence;
     842         691 :   Sequence.LowPC = Address;
     843             :   SequenceIter FirstSeq = Sequences.begin();
     844             :   SequenceIter LastSeq = Sequences.end();
     845             :   SequenceIter SeqPos = std::lower_bound(
     846             :       FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
     847         691 :   DWARFDebugLine::Sequence FoundSeq;
     848         691 :   if (SeqPos == LastSeq) {
     849         639 :     FoundSeq = Sequences.back();
     850          52 :   } else if (SeqPos->LowPC == Address) {
     851          35 :     FoundSeq = *SeqPos;
     852             :   } else {
     853          17 :     if (SeqPos == FirstSeq)
     854           2 :       return UnknownRowIndex;
     855          15 :     FoundSeq = *(SeqPos - 1);
     856             :   }
     857         689 :   return findRowInSeq(FoundSeq, Address);
     858             : }
     859             : 
     860          26 : bool DWARFDebugLine::LineTable::lookupAddressRange(
     861             :     uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const {
     862          26 :   if (Sequences.empty())
     863             :     return false;
     864          26 :   uint64_t EndAddr = Address + Size;
     865             :   // First, find an instruction sequence containing the given address.
     866          26 :   DWARFDebugLine::Sequence Sequence;
     867          26 :   Sequence.LowPC = Address;
     868             :   SequenceIter FirstSeq = Sequences.begin();
     869             :   SequenceIter LastSeq = Sequences.end();
     870             :   SequenceIter SeqPos = std::lower_bound(
     871             :       FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
     872          26 :   if (SeqPos == LastSeq || SeqPos->LowPC != Address) {
     873          14 :     if (SeqPos == FirstSeq)
     874             :       return false;
     875             :     SeqPos--;
     876             :   }
     877             :   if (!SeqPos->containsPC(Address))
     878             :     return false;
     879             : 
     880             :   SequenceIter StartPos = SeqPos;
     881             : 
     882             :   // Add the rows from the first sequence to the vector, starting with the
     883             :   // index we just calculated
     884             : 
     885          52 :   while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
     886             :     const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
     887             :     // For the first sequence, we need to find which row in the sequence is the
     888             :     // first in our range.
     889          26 :     uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
     890          26 :     if (SeqPos == StartPos)
     891          26 :       FirstRowIndex = findRowInSeq(CurSeq, Address);
     892             : 
     893             :     // Figure out the last row in the range.
     894          26 :     uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1);
     895          26 :     if (LastRowIndex == UnknownRowIndex)
     896           0 :       LastRowIndex = CurSeq.LastRowIndex - 1;
     897             : 
     898             :     assert(FirstRowIndex != UnknownRowIndex);
     899             :     assert(LastRowIndex != UnknownRowIndex);
     900             : 
     901         142 :     for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
     902         116 :       Result.push_back(I);
     903             :     }
     904             : 
     905             :     ++SeqPos;
     906             :   }
     907             : 
     908             :   return true;
     909             : }
     910             : 
     911        3558 : bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
     912        7116 :   return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
     913             : }
     914             : 
     915        3467 : bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
     916             :                                                    const char *CompDir,
     917             :                                                    FileLineInfoKind Kind,
     918             :                                                    std::string &Result) const {
     919        3467 :   if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
     920             :     return false;
     921        3467 :   const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
     922        6934 :   StringRef FileName = Entry.Name.getAsCString().getValue();
     923        6815 :   if (Kind != FileLineInfoKind::AbsoluteFilePath ||
     924        6815 :       sys::path::is_absolute(FileName)) {
     925         238 :     Result = FileName;
     926         119 :     return true;
     927             :   }
     928             : 
     929             :   SmallString<16> FilePath;
     930        3348 :   uint64_t IncludeDirIndex = Entry.DirIdx;
     931        3348 :   StringRef IncludeDir;
     932             :   // Be defensive about the contents of Entry.
     933        3737 :   if (IncludeDirIndex > 0 &&
     934             :       IncludeDirIndex <= Prologue.IncludeDirectories.size())
     935        1164 :     IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1]
     936         776 :                      .getAsCString()
     937             :                      .getValue();
     938             : 
     939             :   // We may still need to append compilation directory of compile unit.
     940             :   // We know that FileName is not absolute, the only way to have an
     941             :   // absolute path at this point would be if IncludeDir is absolute.
     942        6392 :   if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
     943        3548 :       sys::path::is_relative(IncludeDir))
     944        2844 :     sys::path::append(FilePath, CompDir);
     945             : 
     946             :   // sys::path::append skips empty strings.
     947        3348 :   sys::path::append(FilePath, IncludeDir, FileName);
     948        6696 :   Result = FilePath.str();
     949             :   return true;
     950             : }
     951             : 
     952        2684 : bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
     953             :     uint64_t Address, const char *CompDir, FileLineInfoKind Kind,
     954             :     DILineInfo &Result) const {
     955             :   // Get the index of row we're looking for in the line table.
     956        2684 :   uint32_t RowIndex = lookupAddress(Address);
     957        2684 :   if (RowIndex == -1U)
     958             :     return false;
     959             :   // Take file number and line/column from the row.
     960         688 :   const auto &Row = Rows[RowIndex];
     961         688 :   if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
     962             :     return false;
     963         688 :   Result.Line = Row.Line;
     964         688 :   Result.Column = Row.Column;
     965         688 :   Result.Discriminator = Row.Discriminator;
     966         688 :   return true;
     967             : }

Generated by: LCOV version 1.13