LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugLine.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 374 416 89.9 %
Date: 2017-09-14 15:23:50 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/DWARFContext.h"
      16             : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
      17             : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
      18             : #include "llvm/Support/Format.h"
      19             : #include "llvm/Support/Path.h"
      20             : #include "llvm/Support/raw_ostream.h"
      21             : #include <algorithm>
      22             : #include <cassert>
      23             : #include <cinttypes>
      24             : #include <cstdint>
      25             : #include <cstdio>
      26             : #include <utility>
      27             : 
      28             : using namespace llvm;
      29             : using namespace dwarf;
      30             : 
      31             : using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
      32             : 
      33             : namespace {
      34             : 
      35             : struct ContentDescriptor {
      36             :   dwarf::LineNumberEntryFormat Type;
      37             :   dwarf::Form Form;
      38             : };
      39             : 
      40             : using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
      41             : 
      42             : } // end anonmyous namespace
      43             : 
      44        5376 : DWARFDebugLine::Prologue::Prologue() { clear(); }
      45             : 
      46        5270 : void DWARFDebugLine::Prologue::clear() {
      47        5270 :   TotalLength = PrologueLength = 0;
      48        5270 :   SegSelectorSize = 0;
      49        5270 :   MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
      50        5270 :   OpcodeBase = 0;
      51        5270 :   FormParams = DWARFFormParams({0, 0, DWARF32});
      52       10540 :   StandardOpcodeLengths.clear();
      53       10540 :   IncludeDirectories.clear();
      54       10540 :   FileNames.clear();
      55        5270 : }
      56             : 
      57         250 : void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
      58         250 :   OS << "Line table prologue:\n"
      59         750 :      << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength)
      60         500 :      << format("         version: %u\n", getVersion());
      61         250 :   if (getVersion() >= 5)
      62           3 :     OS << format("    address_size: %u\n", getAddressSize())
      63           2 :        << format(" seg_select_size: %u\n", SegSelectorSize);
      64         750 :   OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
      65         750 :      << format(" min_inst_length: %u\n", MinInstLength)
      66         750 :      << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
      67         750 :      << format(" default_is_stmt: %u\n", DefaultIsStmt)
      68         750 :      << format("       line_base: %i\n", LineBase)
      69         750 :      << format("      line_range: %u\n", LineRange)
      70         500 :      << format("     opcode_base: %u\n", OpcodeBase);
      71             : 
      72        5756 :   for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
      73        2628 :     OS << format("standard_opcode_lengths[%s] = %u\n",
      74       10512 :                  LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
      75             : 
      76         500 :   if (!IncludeDirectories.empty())
      77         101 :     for (uint32_t I = 0; I != IncludeDirectories.size(); ++I)
      78          69 :       OS << format("include_directories[%3u] = '", I + 1)
      79          46 :          << IncludeDirectories[I] << "'\n";
      80             : 
      81         500 :   if (!FileNames.empty()) {
      82         221 :     OS << "                Dir  Mod Time   File Len   File Name\n"
      83         221 :        << "                ---- ---------- ---------- -----------"
      84             :           "----------------\n";
      85         958 :     for (uint32_t I = 0; I != FileNames.size(); ++I) {
      86         516 :       const FileNameEntry &FileEntry = FileNames[I];
      87         774 :       OS << format("file_names[%3u] %4" PRIu64 " ", I + 1, FileEntry.DirIdx)
      88         774 :          << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ", FileEntry.ModTime,
      89         258 :                    FileEntry.Length)
      90         516 :          << FileEntry.Name << '\n';
      91             :     }
      92             :   }
      93         250 : }
      94             : 
      95             : // Parse v2-v4 directory and file tables.
      96             : static void
      97        1088 : parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
      98             :                      uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
      99             :                      std::vector<StringRef> &IncludeDirectories,
     100             :                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
     101        7062 :   while (*OffsetPtr < EndPrologueOffset) {
     102        4075 :     StringRef S = DebugLineData.getCStrRef(OffsetPtr);
     103        4075 :     if (S.empty())
     104             :       break;
     105        2987 :     IncludeDirectories.push_back(S);
     106             :   }
     107             : 
     108       58866 :   while (*OffsetPtr < EndPrologueOffset) {
     109       29977 :     StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
     110       29977 :     if (Name.empty())
     111             :       break;
     112       28889 :     DWARFDebugLine::FileNameEntry FileEntry;
     113       28889 :     FileEntry.Name = Name;
     114       28889 :     FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
     115       28889 :     FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
     116       28889 :     FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
     117       28889 :     FileNames.push_back(FileEntry);
     118             :   }
     119        1088 : }
     120             : 
     121             : // Parse v5 directory/file entry content descriptions.
     122             : // Returns the descriptors, or an empty vector if we did not find a path or
     123             : // ran off the end of the prologue.
     124             : static ContentDescriptors
     125           2 : parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
     126             :                    uint64_t EndPrologueOffset) {
     127           4 :   ContentDescriptors Descriptors;
     128           2 :   int FormatCount = DebugLineData.getU8(OffsetPtr);
     129           2 :   bool HasPath = false;
     130           7 :   for (int I = 0; I != FormatCount; ++I) {
     131           5 :     if (*OffsetPtr >= EndPrologueOffset)
     132           0 :       return ContentDescriptors();
     133             :     ContentDescriptor Descriptor;
     134           5 :     Descriptor.Type =
     135           5 :       dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
     136           5 :     Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
     137           5 :     if (Descriptor.Type == dwarf::DW_LNCT_path)
     138           2 :       HasPath = true;
     139           5 :     Descriptors.push_back(Descriptor);
     140             :   }
     141           2 :   return HasPath ? Descriptors : ContentDescriptors();
     142             : }
     143             : 
     144             : static bool
     145           1 : parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
     146             :                      uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
     147             :                      const DWARFFormParams &FormParams,
     148             :                      std::vector<StringRef> &IncludeDirectories,
     149             :                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
     150             :   // Get the directory entry description.
     151             :   ContentDescriptors DirDescriptors =
     152           2 :     parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset);
     153           1 :   if (DirDescriptors.empty())
     154             :     return false;
     155             : 
     156             :   // Get the directory entries, according to the format described above.
     157           1 :   int DirEntryCount = DebugLineData.getU8(OffsetPtr);
     158           3 :   for (int I = 0; I != DirEntryCount; ++I) {
     159           2 :     if (*OffsetPtr >= EndPrologueOffset)
     160             :       return false;
     161           8 :     for (auto Descriptor : DirDescriptors) {
     162           4 :       DWARFFormValue Value(Descriptor.Form);
     163           2 :       switch (Descriptor.Type) {
     164           2 :       case DW_LNCT_path:
     165           2 :         if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr))
     166           0 :           return false;
     167          10 :         IncludeDirectories.push_back(Value.getAsCString().getValue());
     168           2 :         break;
     169           0 :       default:
     170           0 :         if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
     171             :           return false;
     172             :       }
     173             :     }
     174             :   }
     175             : 
     176             :   // Get the file entry description.
     177             :   ContentDescriptors FileDescriptors =
     178           1 :     parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset);
     179           1 :   if (FileDescriptors.empty())
     180             :     return false;
     181             : 
     182             :   // Get the file entries, according to the format described above.
     183           1 :   int FileEntryCount = DebugLineData.getU8(OffsetPtr);
     184           3 :   for (int I = 0; I != FileEntryCount; ++I) {
     185           2 :     if (*OffsetPtr >= EndPrologueOffset)
     186           0 :       return false;
     187           2 :     DWARFDebugLine::FileNameEntry FileEntry;
     188          14 :     for (auto Descriptor : FileDescriptors) {
     189          16 :       DWARFFormValue Value(Descriptor.Form);
     190           8 :       if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr))
     191           0 :         return false;
     192           8 :       switch (Descriptor.Type) {
     193           2 :       case DW_LNCT_path:
     194           8 :         FileEntry.Name = Value.getAsCString().getValue();
     195           2 :         break;
     196           2 :       case DW_LNCT_directory_index:
     197           6 :         FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
     198           2 :         break;
     199           2 :       case DW_LNCT_timestamp:
     200           6 :         FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
     201           2 :         break;
     202           2 :       case DW_LNCT_size:
     203           6 :         FileEntry.Length = Value.getAsUnsignedConstant().getValue();
     204           2 :         break;
     205             :       // FIXME: Add MD5
     206             :       default:
     207             :         break;
     208             :       }
     209             :     }
     210           2 :     FileNames.push_back(FileEntry);
     211             :   }
     212             :   return true;
     213             : }
     214             : 
     215        1374 : bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
     216             :                                      uint32_t *OffsetPtr) {
     217        1374 :   const uint64_t PrologueOffset = *OffsetPtr;
     218             : 
     219        1374 :   clear();
     220        1374 :   TotalLength = DebugLineData.getU32(OffsetPtr);
     221        1374 :   if (TotalLength == UINT32_MAX) {
     222           1 :     FormParams.Format = dwarf::DWARF64;
     223           1 :     TotalLength = DebugLineData.getU64(OffsetPtr);
     224        1373 :   } else if (TotalLength >= 0xffffff00) {
     225             :     return false;
     226             :   }
     227        1374 :   FormParams.Version = DebugLineData.getU16(OffsetPtr);
     228        1374 :   if (getVersion() < 2)
     229             :     return false;
     230             : 
     231        1089 :   if (getVersion() >= 5) {
     232           1 :     FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
     233             :     assert(getAddressSize() == DebugLineData.getAddressSize() &&
     234             :            "Line table header and data extractor disagree");
     235           1 :     SegSelectorSize = DebugLineData.getU8(OffsetPtr);
     236             :   }
     237             : 
     238        2178 :   PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
     239        1089 :   const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
     240        1089 :   MinInstLength = DebugLineData.getU8(OffsetPtr);
     241        1089 :   if (getVersion() >= 4)
     242           6 :     MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
     243        1089 :   DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
     244        1089 :   LineBase = DebugLineData.getU8(OffsetPtr);
     245        1089 :   LineRange = DebugLineData.getU8(OffsetPtr);
     246        1089 :   OpcodeBase = DebugLineData.getU8(OffsetPtr);
     247             : 
     248        1089 :   StandardOpcodeLengths.reserve(OpcodeBase - 1);
     249       13701 :   for (uint32_t I = 1; I < OpcodeBase; ++I) {
     250       12612 :     uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
     251       12612 :     StandardOpcodeLengths.push_back(OpLen);
     252             :   }
     253             : 
     254        1089 :   if (getVersion() >= 5) {
     255           3 :     if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
     256           2 :                               getFormParams(), IncludeDirectories, FileNames)) {
     257           0 :       fprintf(stderr,
     258             :               "warning: parsing line table prologue at 0x%8.8" PRIx64
     259             :               " found an invalid directory or file table description at"
     260           0 :               " 0x%8.8" PRIx64 "\n", PrologueOffset, (uint64_t)*OffsetPtr);
     261           0 :       return false;
     262             :     }
     263             :   } else
     264        1088 :     parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
     265             :                          IncludeDirectories, FileNames);
     266             : 
     267        1089 :   if (*OffsetPtr != EndPrologueOffset) {
     268           0 :     fprintf(stderr,
     269             :             "warning: parsing line table prologue at 0x%8.8" PRIx64
     270             :             " should have ended at 0x%8.8" PRIx64
     271             :             " but it ended at 0x%8.8" PRIx64 "\n",
     272             :             PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
     273           0 :     return false;
     274             :   }
     275             :   return true;
     276             : }
     277             : 
     278        2012 : DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
     279             : 
     280      425937 : void DWARFDebugLine::Row::postAppend() {
     281      425937 :   BasicBlock = false;
     282      425937 :   PrologueEnd = false;
     283      425937 :   EpilogueBegin = false;
     284      425937 : }
     285             : 
     286       13165 : void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
     287       13165 :   Address = 0;
     288       13165 :   Line = 1;
     289       13165 :   Column = 0;
     290       13165 :   File = 1;
     291       13165 :   Isa = 0;
     292       13165 :   Discriminator = 0;
     293       13165 :   IsStmt = DefaultIsStmt;
     294       13165 :   BasicBlock = false;
     295       13165 :   EndSequence = false;
     296       13165 :   PrologueEnd = false;
     297       13165 :   EpilogueBegin = false;
     298       13165 : }
     299             : 
     300         182 : void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
     301         182 :   OS << "Address            Line   Column File   ISA Discriminator Flags\n"
     302         182 :      << "------------------ ------ ------ ------ --- ------------- "
     303             :         "-------------\n";
     304         182 : }
     305             : 
     306        1413 : void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
     307        4239 :   OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
     308        4239 :      << format(" %6u %3u %13u ", File, Isa, Discriminator)
     309        1413 :      << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
     310        1413 :      << (PrologueEnd ? " prologue_end" : "")
     311        1413 :      << (EpilogueBegin ? " epilogue_begin" : "")
     312        2826 :      << (EndSequence ? " end_sequence" : "") << '\n';
     313        1413 : }
     314             : 
     315        2891 : DWARFDebugLine::Sequence::Sequence() { reset(); }
     316             : 
     317       24138 : void DWARFDebugLine::Sequence::reset() {
     318       24138 :   LowPC = 0;
     319       24138 :   HighPC = 0;
     320       24138 :   FirstRowIndex = 0;
     321       24138 :   LastRowIndex = 0;
     322       24138 :   Empty = true;
     323       24138 : }
     324             : 
     325        4032 : DWARFDebugLine::LineTable::LineTable() { clear(); }
     326             : 
     327         250 : void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
     328         250 :   Prologue.dump(OS);
     329         250 :   OS << '\n';
     330             : 
     331         500 :   if (!Rows.empty()) {
     332         180 :     Row::dumpTableHeader(OS);
     333        2130 :     for (const Row &R : Rows) {
     334        1410 :       R.dump(OS);
     335             :     }
     336             :   }
     337         250 : }
     338             : 
     339        2552 : void DWARFDebugLine::LineTable::clear() {
     340        2552 :   Prologue.clear();
     341        5104 :   Rows.clear();
     342        5104 :   Sequences.clear();
     343        2552 : }
     344             : 
     345        1059 : DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
     346        1059 :     : LineTable(LT) {
     347        1059 :   resetRowAndSequence();
     348        1059 : }
     349             : 
     350       11153 : void DWARFDebugLine::ParsingState::resetRowAndSequence() {
     351       11153 :   Row.reset(LineTable->Prologue.DefaultIsStmt);
     352       11153 :   Sequence.reset();
     353       11153 : }
     354             : 
     355      425937 : void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
     356      425937 :   if (Sequence.Empty) {
     357             :     // Record the beginning of instruction sequence.
     358       10095 :     Sequence.Empty = false;
     359       10095 :     Sequence.LowPC = Row.Address;
     360       10095 :     Sequence.FirstRowIndex = RowNumber;
     361             :   }
     362      425937 :   ++RowNumber;
     363      851874 :   LineTable->appendRow(Row);
     364      425937 :   if (Row.EndSequence) {
     365             :     // Record the end of instruction sequence.
     366       10094 :     Sequence.HighPC = Row.Address;
     367       10094 :     Sequence.LastRowIndex = RowNumber;
     368       20178 :     if (Sequence.isValid())
     369       10084 :       LineTable->appendSequence(Sequence);
     370       10094 :     Sequence.reset();
     371             :   }
     372      425937 :   Row.postAppend();
     373      425937 : }
     374             : 
     375             : const DWARFDebugLine::LineTable *
     376        3441 : DWARFDebugLine::getLineTable(uint32_t Offset) const {
     377        6882 :   LineTableConstIter Pos = LineTableMap.find(Offset);
     378        6882 :   if (Pos != LineTableMap.end())
     379        2718 :     return &Pos->second;
     380             :   return nullptr;
     381             : }
     382             : 
     383             : const DWARFDebugLine::LineTable *
     384         841 : DWARFDebugLine::getOrParseLineTable(const DWARFDataExtractor &DebugLineData,
     385             :                                     uint32_t Offset) {
     386             :   std::pair<LineTableIter, bool> Pos =
     387        3364 :       LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
     388         841 :   LineTable *LT = &Pos.first->second;
     389         841 :   if (Pos.second) {
     390         841 :     if (!LT->parse(DebugLineData, &Offset))
     391             :       return nullptr;
     392             :   }
     393             :   return LT;
     394             : }
     395             : 
     396        1178 : bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData,
     397             :                                       uint32_t *OffsetPtr) {
     398        1178 :   const uint32_t DebugLineOffset = *OffsetPtr;
     399             : 
     400        1178 :   clear();
     401             : 
     402        1178 :   if (!Prologue.parse(DebugLineData, OffsetPtr)) {
     403             :     // Restore our offset and return false to indicate failure!
     404         119 :     *OffsetPtr = DebugLineOffset;
     405         119 :     return false;
     406             :   }
     407             : 
     408             :   const uint32_t EndOffset =
     409        2118 :       DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
     410             : 
     411        1059 :   ParsingState State(this);
     412             : 
     413     1098417 :   while (*OffsetPtr < EndOffset) {
     414     1097358 :     uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
     415             : 
     416     1097358 :     if (Opcode == 0) {
     417             :       // Extended Opcodes always start with a zero opcode followed by
     418             :       // a uleb128 length so you can skip ones you don't know about
     419       33951 :       uint32_t ExtOffset = *OffsetPtr;
     420       33951 :       uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
     421       33951 :       uint32_t ArgSize = Len - (*OffsetPtr - ExtOffset);
     422             : 
     423       33951 :       uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
     424       33951 :       switch (SubOpcode) {
     425       10094 :       case DW_LNE_end_sequence:
     426             :         // Set the end_sequence register of the state machine to true and
     427             :         // append a row to the matrix using the current values of the
     428             :         // state-machine registers. Then reset the registers to the initial
     429             :         // values specified above. Every statement program sequence must end
     430             :         // with a DW_LNE_end_sequence instruction which creates a row whose
     431             :         // address is that of the byte after the last target machine instruction
     432             :         // of the sequence.
     433       10094 :         State.Row.EndSequence = true;
     434       10094 :         State.appendRowToMatrix(*OffsetPtr);
     435       10094 :         State.resetRowAndSequence();
     436       10094 :         break;
     437             : 
     438       10086 :       case DW_LNE_set_address:
     439             :         // Takes a single relocatable address as an operand. The size of the
     440             :         // operand is the size appropriate to hold an address on the target
     441             :         // machine. Set the address register to the value given by the
     442             :         // relocatable address. All of the other statement program opcodes
     443             :         // that affect the address register add a delta to it. This instruction
     444             :         // stores a relocatable value into it instead.
     445       10086 :         State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr);
     446       10086 :         break;
     447             : 
     448           0 :       case DW_LNE_define_file:
     449             :         // Takes 4 arguments. The first is a null terminated string containing
     450             :         // a source file name. The second is an unsigned LEB128 number
     451             :         // representing the directory index of the directory in which the file
     452             :         // was found. The third is an unsigned LEB128 number representing the
     453             :         // time of last modification of the file. The fourth is an unsigned
     454             :         // LEB128 number representing the length in bytes of the file. The time
     455             :         // and length fields may contain LEB128(0) if the information is not
     456             :         // available.
     457             :         //
     458             :         // The directory index represents an entry in the include_directories
     459             :         // section of the statement program prologue. The index is LEB128(0)
     460             :         // if the file was found in the current directory of the compilation,
     461             :         // LEB128(1) if it was found in the first directory in the
     462             :         // include_directories section, and so on. The directory index is
     463             :         // ignored for file names that represent full path names.
     464             :         //
     465             :         // The files are numbered, starting at 1, in the order in which they
     466             :         // appear; the names in the prologue come before names defined by
     467             :         // the DW_LNE_define_file instruction. These numbers are used in the
     468             :         // the file register of the state machine.
     469             :         {
     470           0 :           FileNameEntry FileEntry;
     471           0 :           FileEntry.Name = DebugLineData.getCStr(OffsetPtr);
     472           0 :           FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
     473           0 :           FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
     474           0 :           FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
     475           0 :           Prologue.FileNames.push_back(FileEntry);
     476             :         }
     477           0 :         break;
     478             : 
     479       13771 :       case DW_LNE_set_discriminator:
     480       13771 :         State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
     481       13771 :         break;
     482             : 
     483           0 :       default:
     484             :         // Length doesn't include the zero opcode byte or the length itself, but
     485             :         // it does include the sub_opcode, so we have to adjust for that below
     486           0 :         (*OffsetPtr) += ArgSize;
     487           0 :         break;
     488             :       }
     489     1063407 :     } else if (Opcode < Prologue.OpcodeBase) {
     490      687052 :       switch (Opcode) {
     491             :       // Standard Opcodes
     492       39488 :       case DW_LNS_copy:
     493             :         // Takes no arguments. Append a row to the matrix using the
     494             :         // current values of the state-machine registers. Then set
     495             :         // the basic_block register to false.
     496       39488 :         State.appendRowToMatrix(*OffsetPtr);
     497       39488 :         break;
     498             : 
     499       47189 :       case DW_LNS_advance_pc:
     500             :         // Takes a single unsigned LEB128 operand, multiplies it by the
     501             :         // min_inst_length field of the prologue, and adds the
     502             :         // result to the address register of the state machine.
     503       47189 :         State.Row.Address +=
     504       47189 :             DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
     505       47189 :         break;
     506             : 
     507      295974 :       case DW_LNS_advance_line:
     508             :         // Takes a single signed LEB128 operand and adds that value to
     509             :         // the line register of the state machine.
     510      295974 :         State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
     511      295974 :         break;
     512             : 
     513      202944 :       case DW_LNS_set_file:
     514             :         // Takes a single unsigned LEB128 operand and stores it in the file
     515             :         // register of the state machine.
     516      202944 :         State.Row.File = DebugLineData.getULEB128(OffsetPtr);
     517      202944 :         break;
     518             : 
     519        1920 :       case DW_LNS_set_column:
     520             :         // Takes a single unsigned LEB128 operand and stores it in the
     521             :         // column register of the state machine.
     522        1920 :         State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
     523        1920 :         break;
     524             : 
     525        5798 :       case DW_LNS_negate_stmt:
     526             :         // Takes no arguments. Set the is_stmt register of the state
     527             :         // machine to the logical negation of its current value.
     528        5798 :         State.Row.IsStmt = !State.Row.IsStmt;
     529        5798 :         break;
     530             : 
     531           0 :       case DW_LNS_set_basic_block:
     532             :         // Takes no arguments. Set the basic_block register of the
     533             :         // state machine to true
     534           0 :         State.Row.BasicBlock = true;
     535           0 :         break;
     536             : 
     537       92425 :       case DW_LNS_const_add_pc:
     538             :         // Takes no arguments. Add to the address register of the state
     539             :         // machine the address increment value corresponding to special
     540             :         // opcode 255. The motivation for DW_LNS_const_add_pc is this:
     541             :         // when the statement program needs to advance the address by a
     542             :         // small amount, it can use a single special opcode, which occupies
     543             :         // a single byte. When it needs to advance the address by up to
     544             :         // twice the range of the last special opcode, it can use
     545             :         // DW_LNS_const_add_pc followed by a special opcode, for a total
     546             :         // of two bytes. Only if it needs to advance the address by more
     547             :         // than twice that range will it need to use both DW_LNS_advance_pc
     548             :         // and a special opcode, requiring three or more bytes.
     549             :         {
     550       92425 :           uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
     551       92425 :           uint64_t AddrOffset =
     552       92425 :               (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
     553       92425 :           State.Row.Address += AddrOffset;
     554             :         }
     555       92425 :         break;
     556             : 
     557           0 :       case DW_LNS_fixed_advance_pc:
     558             :         // Takes a single uhalf operand. Add to the address register of
     559             :         // the state machine the value of the (unencoded) operand. This
     560             :         // is the only extended opcode that takes an argument that is not
     561             :         // a variable length number. The motivation for DW_LNS_fixed_advance_pc
     562             :         // is this: existing assemblers cannot emit DW_LNS_advance_pc or
     563             :         // special opcodes because they cannot encode LEB128 numbers or
     564             :         // judge when the computation of a special opcode overflows and
     565             :         // requires the use of DW_LNS_advance_pc. Such assemblers, however,
     566             :         // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
     567           0 :         State.Row.Address += DebugLineData.getU16(OffsetPtr);
     568           0 :         break;
     569             : 
     570        1314 :       case DW_LNS_set_prologue_end:
     571             :         // Takes no arguments. Set the prologue_end register of the
     572             :         // state machine to true
     573        1314 :         State.Row.PrologueEnd = true;
     574        1314 :         break;
     575             : 
     576           0 :       case DW_LNS_set_epilogue_begin:
     577             :         // Takes no arguments. Set the basic_block register of the
     578             :         // state machine to true
     579           0 :         State.Row.EpilogueBegin = true;
     580           0 :         break;
     581             : 
     582           0 :       case DW_LNS_set_isa:
     583             :         // Takes a single unsigned LEB128 operand and stores it in the
     584             :         // column register of the state machine.
     585           0 :         State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
     586           0 :         break;
     587             : 
     588           0 :       default:
     589             :         // Handle any unknown standard opcodes here. We know the lengths
     590             :         // of such opcodes because they are specified in the prologue
     591             :         // as a multiple of LEB128 operands for each opcode.
     592             :         {
     593             :           assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
     594           0 :           uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
     595           0 :           for (uint8_t I = 0; I < OpcodeLength; ++I)
     596           0 :             DebugLineData.getULEB128(OffsetPtr);
     597             :         }
     598             :         break;
     599             :       }
     600             :     } else {
     601             :       // Special Opcodes
     602             : 
     603             :       // A special opcode value is chosen based on the amount that needs
     604             :       // to be added to the line and address registers. The maximum line
     605             :       // increment for a special opcode is the value of the line_base
     606             :       // field in the header, plus the value of the line_range field,
     607             :       // minus 1 (line base + line range - 1). If the desired line
     608             :       // increment is greater than the maximum line increment, a standard
     609             :       // opcode must be used instead of a special opcode. The "address
     610             :       // advance" is calculated by dividing the desired address increment
     611             :       // by the minimum_instruction_length field from the header. The
     612             :       // special opcode is then calculated using the following formula:
     613             :       //
     614             :       //  opcode = (desired line increment - line_base) +
     615             :       //           (line_range * address advance) + opcode_base
     616             :       //
     617             :       // If the resulting opcode is greater than 255, a standard opcode
     618             :       // must be used instead.
     619             :       //
     620             :       // To decode a special opcode, subtract the opcode_base from the
     621             :       // opcode itself to give the adjusted opcode. The amount to
     622             :       // increment the address register is the result of the adjusted
     623             :       // opcode divided by the line_range multiplied by the
     624             :       // minimum_instruction_length field from the header. That is:
     625             :       //
     626             :       //  address increment = (adjusted opcode / line_range) *
     627             :       //                      minimum_instruction_length
     628             :       //
     629             :       // The amount to increment the line register is the line_base plus
     630             :       // the result of the adjusted opcode modulo the line_range. That is:
     631             :       //
     632             :       // line increment = line_base + (adjusted opcode % line_range)
     633             : 
     634      376355 :       uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
     635      376355 :       uint64_t AddrOffset =
     636      376355 :           (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
     637      376355 :       int32_t LineOffset =
     638      376355 :           Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
     639      376355 :       State.Row.Line += LineOffset;
     640      376355 :       State.Row.Address += AddrOffset;
     641      376355 :       State.appendRowToMatrix(*OffsetPtr);
     642             :       // Reset discriminator to 0.
     643      376355 :       State.Row.Discriminator = 0;
     644             :     }
     645             :   }
     646             : 
     647        1059 :   if (!State.Sequence.Empty) {
     648           1 :     fprintf(stderr, "warning: last sequence in debug line table is not"
     649             :                     "terminated!\n");
     650             :   }
     651             : 
     652             :   // Sort all sequences so that address lookup will work faster.
     653        2118 :   if (!Sequences.empty()) {
     654        2763 :     std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
     655             :     // Note: actually, instruction address ranges of sequences should not
     656             :     // overlap (in shared objects and executables). If they do, the address
     657             :     // lookup would still work, though, but result would be ambiguous.
     658             :     // We don't report warning in this case. For example,
     659             :     // sometimes .so compiled from multiple object files contains a few
     660             :     // rudimentary sequences for address ranges [0x0, 0xsomething).
     661             :   }
     662             : 
     663        1059 :   return EndOffset;
     664             : }
     665             : 
     666             : uint32_t
     667         953 : DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
     668             :                                         uint64_t Address) const {
     669        1906 :   if (!Seq.containsPC(Address))
     670           0 :     return UnknownRowIndex;
     671             :   // Search for instruction address in the rows describing the sequence.
     672             :   // Rows are stored in a vector, so we may use arithmetical operations with
     673             :   // iterators.
     674         953 :   DWARFDebugLine::Row Row;
     675         953 :   Row.Address = Address;
     676        2859 :   RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
     677        2859 :   RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
     678             :   LineTable::RowIter RowPos = std::lower_bound(
     679         953 :       FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress);
     680         953 :   if (RowPos == LastRow) {
     681           0 :     return Seq.LastRowIndex - 1;
     682             :   }
     683        1906 :   uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
     684         953 :   if (RowPos->Address > Address) {
     685         702 :     if (RowPos == FirstRow)
     686           0 :       return UnknownRowIndex;
     687             :     else
     688         702 :       Index--;
     689             :   }
     690             :   return Index;
     691             : }
     692             : 
     693        1058 : uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const {
     694        2116 :   if (Sequences.empty())
     695         155 :     return UnknownRowIndex;
     696             :   // First, find an instruction sequence containing the given address.
     697         903 :   DWARFDebugLine::Sequence Sequence;
     698         903 :   Sequence.LowPC = Address;
     699        1806 :   SequenceIter FirstSeq = Sequences.begin();
     700        1806 :   SequenceIter LastSeq = Sequences.end();
     701             :   SequenceIter SeqPos = std::lower_bound(
     702         903 :       FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
     703         903 :   DWARFDebugLine::Sequence FoundSeq;
     704         903 :   if (SeqPos == LastSeq) {
     705        1310 :     FoundSeq = Sequences.back();
     706         248 :   } else if (SeqPos->LowPC == Address) {
     707          36 :     FoundSeq = *SeqPos;
     708             :   } else {
     709         212 :     if (SeqPos == FirstSeq)
     710           2 :       return UnknownRowIndex;
     711         210 :     FoundSeq = *(SeqPos - 1);
     712             :   }
     713         901 :   return findRowInSeq(FoundSeq, Address);
     714             : }
     715             : 
     716          26 : bool DWARFDebugLine::LineTable::lookupAddressRange(
     717             :     uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const {
     718          52 :   if (Sequences.empty())
     719             :     return false;
     720          26 :   uint64_t EndAddr = Address + Size;
     721             :   // First, find an instruction sequence containing the given address.
     722          26 :   DWARFDebugLine::Sequence Sequence;
     723          26 :   Sequence.LowPC = Address;
     724          52 :   SequenceIter FirstSeq = Sequences.begin();
     725          52 :   SequenceIter LastSeq = Sequences.end();
     726             :   SequenceIter SeqPos = std::lower_bound(
     727          26 :       FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
     728          26 :   if (SeqPos == LastSeq || SeqPos->LowPC != Address) {
     729          14 :     if (SeqPos == FirstSeq)
     730             :       return false;
     731          14 :     SeqPos--;
     732             :   }
     733          26 :   if (!SeqPos->containsPC(Address))
     734             :     return false;
     735             : 
     736             :   SequenceIter StartPos = SeqPos;
     737             : 
     738             :   // Add the rows from the first sequence to the vector, starting with the
     739             :   // index we just calculated
     740             : 
     741          52 :   while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
     742          26 :     const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
     743             :     // For the first sequence, we need to find which row in the sequence is the
     744             :     // first in our range.
     745          26 :     uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
     746          26 :     if (SeqPos == StartPos)
     747          26 :       FirstRowIndex = findRowInSeq(CurSeq, Address);
     748             : 
     749             :     // Figure out the last row in the range.
     750          26 :     uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1);
     751          26 :     if (LastRowIndex == UnknownRowIndex)
     752           0 :       LastRowIndex = CurSeq.LastRowIndex - 1;
     753             : 
     754             :     assert(FirstRowIndex != UnknownRowIndex);
     755             :     assert(LastRowIndex != UnknownRowIndex);
     756             : 
     757         142 :     for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
     758         116 :       Result.push_back(I);
     759             :     }
     760             : 
     761             :     ++SeqPos;
     762             :   }
     763             : 
     764             :   return true;
     765             : }
     766             : 
     767        3526 : bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
     768        7052 :   return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
     769             : }
     770             : 
     771        3447 : bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
     772             :                                                    const char *CompDir,
     773             :                                                    FileLineInfoKind Kind,
     774             :                                                    std::string &Result) const {
     775        3447 :   if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
     776             :     return false;
     777        6894 :   const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
     778        3447 :   StringRef FileName = Entry.Name;
     779        6778 :   if (Kind != FileLineInfoKind::AbsoluteFilePath ||
     780        6778 :       sys::path::is_absolute(FileName)) {
     781         232 :     Result = FileName;
     782         116 :     return true;
     783             :   }
     784             : 
     785        3331 :   SmallString<16> FilePath;
     786        3331 :   uint64_t IncludeDirIndex = Entry.DirIdx;
     787        3331 :   StringRef IncludeDir;
     788             :   // Be defensive about the contents of Entry.
     789        3965 :   if (IncludeDirIndex > 0 &&
     790         634 :       IncludeDirIndex <= Prologue.IncludeDirectories.size())
     791        1266 :     IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1];
     792             : 
     793             :   // We may still need to append compilation directory of compile unit.
     794             :   // We know that FileName is not absolute, the only way to have an
     795             :   // absolute path at this point would be if IncludeDir is absolute.
     796        6373 :   if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
     797        3785 :       sys::path::is_relative(IncludeDir))
     798       10352 :     sys::path::append(FilePath, CompDir);
     799             : 
     800             :   // sys::path::append skips empty strings.
     801       13324 :   sys::path::append(FilePath, IncludeDir, FileName);
     802        9993 :   Result = FilePath.str();
     803        3331 :   return true;
     804             : }
     805             : 
     806        1058 : bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
     807             :     uint64_t Address, const char *CompDir, FileLineInfoKind Kind,
     808             :     DILineInfo &Result) const {
     809             :   // Get the index of row we're looking for in the line table.
     810        1058 :   uint32_t RowIndex = lookupAddress(Address);
     811        1058 :   if (RowIndex == -1U)
     812             :     return false;
     813             :   // Take file number and line/column from the row.
     814        1802 :   const auto &Row = Rows[RowIndex];
     815         901 :   if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
     816             :     return false;
     817         901 :   Result.Line = Row.Line;
     818         901 :   Result.Column = Row.Column;
     819         901 :   Result.Discriminator = Row.Discriminator;
     820         901 :   return true;
     821             : }

Generated by: LCOV version 1.13