brintos

brintos / llvm-project-archived public Read only

0
0
Text · 64.1 KiB · 08b5866 Raw
1689 lines · cpp
1//===- DWARFDebugLine.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"10#include "llvm/ADT/SmallString.h"11#include "llvm/ADT/SmallVector.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/BinaryFormat/Dwarf.h"14#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"15#include "llvm/DebugInfo/DWARF/DWARFDie.h"16#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"17#include "llvm/Support/Errc.h"18#include "llvm/Support/Format.h"19#include "llvm/Support/FormatVariadic.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 28using namespace llvm;29using namespace dwarf;30 31using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;32 33namespace {34 35struct ContentDescriptor {36  dwarf::LineNumberEntryFormat Type;37  dwarf::Form Form;38};39 40using ContentDescriptors = SmallVector<ContentDescriptor, 4>;41 42} // end anonymous namespace43 44static bool versionIsSupported(uint16_t Version) {45  return Version >= 2 && Version <= 5;46}47 48void DWARFDebugLine::ContentTypeTracker::trackContentType(49    dwarf::LineNumberEntryFormat ContentType) {50  switch (ContentType) {51  case dwarf::DW_LNCT_timestamp:52    HasModTime = true;53    break;54  case dwarf::DW_LNCT_size:55    HasLength = true;56    break;57  case dwarf::DW_LNCT_MD5:58    HasMD5 = true;59    break;60  case dwarf::DW_LNCT_LLVM_source:61    HasSource = true;62    break;63  default:64    // We only care about values we consider optional, and new values may be65    // added in the vendor extension range, so we do not match exhaustively.66    break;67  }68}69 70DWARFDebugLine::Prologue::Prologue() { clear(); }71 72bool DWARFDebugLine::Prologue::hasFileAtIndex(uint64_t FileIndex) const {73  uint16_t DwarfVersion = getVersion();74  assert(DwarfVersion != 0 &&75         "line table prologue has no dwarf version information");76  if (DwarfVersion >= 5)77    return FileIndex < FileNames.size();78  return FileIndex != 0 && FileIndex <= FileNames.size();79}80 81std::optional<uint64_t>82DWARFDebugLine::Prologue::getLastValidFileIndex() const {83  if (FileNames.empty())84    return std::nullopt;85  uint16_t DwarfVersion = getVersion();86  assert(DwarfVersion != 0 &&87         "line table prologue has no dwarf version information");88  // In DWARF v5 the file names are 0-indexed.89  if (DwarfVersion >= 5)90    return FileNames.size() - 1;91  return FileNames.size();92}93 94const llvm::DWARFDebugLine::FileNameEntry &95DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const {96  uint16_t DwarfVersion = getVersion();97  assert(DwarfVersion != 0 &&98         "line table prologue has no dwarf version information");99  // In DWARF v5 the file names are 0-indexed.100  if (DwarfVersion >= 5)101    return FileNames[Index];102  return FileNames[Index - 1];103}104 105void DWARFDebugLine::Prologue::clear() {106  TotalLength = PrologueLength = 0;107  SegSelectorSize = 0;108  MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;109  OpcodeBase = 0;110  FormParams = dwarf::FormParams({0, 0, DWARF32});111  ContentTypes = ContentTypeTracker();112  StandardOpcodeLengths.clear();113  IncludeDirectories.clear();114  FileNames.clear();115}116 117void DWARFDebugLine::Prologue::dump(raw_ostream &OS,118                                    DIDumpOptions DumpOptions) const {119  if (!totalLengthIsValid())120    return;121  int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(FormParams.Format);122  OS << "Line table prologue:\n"123     << format("    total_length: 0x%0*" PRIx64 "\n", OffsetDumpWidth,124               TotalLength)125     << "          format: " << dwarf::FormatString(FormParams.Format) << "\n"126     << format("         version: %u\n", getVersion());127  if (!versionIsSupported(getVersion()))128    return;129  if (getVersion() >= 5)130    OS << format("    address_size: %u\n", getAddressSize())131       << format(" seg_select_size: %u\n", SegSelectorSize);132  OS << format(" prologue_length: 0x%0*" PRIx64 "\n", OffsetDumpWidth,133               PrologueLength)134     << format(" min_inst_length: %u\n", MinInstLength)135     << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)136     << format(" default_is_stmt: %u\n", DefaultIsStmt)137     << format("       line_base: %i\n", LineBase)138     << format("      line_range: %u\n", LineRange)139     << format("     opcode_base: %u\n", OpcodeBase);140 141  for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)142    OS << formatv("standard_opcode_lengths[{0}] = {1}\n",143                  static_cast<dwarf::LineNumberOps>(I + 1),144                  StandardOpcodeLengths[I]);145 146  if (!IncludeDirectories.empty()) {147    // DWARF v5 starts directory indexes at 0.148    uint32_t DirBase = getVersion() >= 5 ? 0 : 1;149    for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {150      OS << format("include_directories[%3u] = ", I + DirBase);151      IncludeDirectories[I].dump(OS, DumpOptions);152      OS << '\n';153    }154  }155 156  if (!FileNames.empty()) {157    // DWARF v5 starts file indexes at 0.158    uint32_t FileBase = getVersion() >= 5 ? 0 : 1;159    for (uint32_t I = 0; I != FileNames.size(); ++I) {160      const FileNameEntry &FileEntry = FileNames[I];161      OS << format("file_names[%3u]:\n", I + FileBase);162      OS << "           name: ";163      FileEntry.Name.dump(OS, DumpOptions);164      OS << '\n' << format("      dir_index: %" PRIu64 "\n", FileEntry.DirIdx);165      if (ContentTypes.HasMD5)166        OS << "   md5_checksum: " << FileEntry.Checksum.digest() << '\n';167      if (ContentTypes.HasModTime)168        OS << format("       mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);169      if (ContentTypes.HasLength)170        OS << format("         length: 0x%8.8" PRIx64 "\n", FileEntry.Length);171      if (ContentTypes.HasSource) {172        auto Source = FileEntry.Source.getAsCString();173        if (!Source)174          consumeError(Source.takeError());175        else if ((*Source)[0]) {176          OS << "         source: ";177          FileEntry.Source.dump(OS, DumpOptions);178          OS << '\n';179        }180      }181    }182  }183}184 185// Parse v2-v4 directory and file tables.186static Error187parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,188                     uint64_t *OffsetPtr,189                     DWARFDebugLine::ContentTypeTracker &ContentTypes,190                     std::vector<DWARFFormValue> &IncludeDirectories,191                     std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {192  while (true) {193    Error Err = Error::success();194    StringRef S = DebugLineData.getCStrRef(OffsetPtr, &Err);195    if (Err) {196      consumeError(std::move(Err));197      return createStringError(errc::invalid_argument,198                               "include directories table was not null "199                               "terminated before the end of the prologue");200    }201    if (S.empty())202      break;203    DWARFFormValue Dir =204        DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, S.data());205    IncludeDirectories.push_back(Dir);206  }207 208  ContentTypes.HasModTime = true;209  ContentTypes.HasLength = true;210 211  while (true) {212    Error Err = Error::success();213    StringRef Name = DebugLineData.getCStrRef(OffsetPtr, &Err);214    if (!Err && Name.empty())215      break;216 217    DWARFDebugLine::FileNameEntry FileEntry;218    FileEntry.Name =219        DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name.data());220    FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr, &Err);221    FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr, &Err);222    FileEntry.Length = DebugLineData.getULEB128(OffsetPtr, &Err);223 224    if (Err) {225      consumeError(std::move(Err));226      return createStringError(227          errc::invalid_argument,228          "file names table was not null terminated before "229          "the end of the prologue");230    }231    FileNames.push_back(FileEntry);232  }233 234  return Error::success();235}236 237// Parse v5 directory/file entry content descriptions.238// Returns the descriptors, or an error if we did not find a path or ran off239// the end of the prologue.240static llvm::Expected<ContentDescriptors>241parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,242                   DWARFDebugLine::ContentTypeTracker *ContentTypes) {243  Error Err = Error::success();244  ContentDescriptors Descriptors;245  int FormatCount = DebugLineData.getU8(OffsetPtr, &Err);246  bool HasPath = false;247  for (int I = 0; I != FormatCount && !Err; ++I) {248    ContentDescriptor Descriptor;249    Descriptor.Type =250        dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr, &Err));251    Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr, &Err));252    if (Descriptor.Type == dwarf::DW_LNCT_path)253      HasPath = true;254    if (ContentTypes)255      ContentTypes->trackContentType(Descriptor.Type);256    Descriptors.push_back(Descriptor);257  }258 259  if (Err)260    return createStringError(errc::invalid_argument,261                             "failed to parse entry content descriptors: %s",262                             toString(std::move(Err)).c_str());263 264  if (!HasPath)265    return createStringError(errc::invalid_argument,266                             "failed to parse entry content descriptions"267                             " because no path was found");268  return Descriptors;269}270 271static Error272parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,273                     uint64_t *OffsetPtr, const dwarf::FormParams &FormParams,274                     const DWARFContext &Ctx, const DWARFUnit *U,275                     DWARFDebugLine::ContentTypeTracker &ContentTypes,276                     std::vector<DWARFFormValue> &IncludeDirectories,277                     std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {278  // Get the directory entry description.279  llvm::Expected<ContentDescriptors> DirDescriptors =280      parseV5EntryFormat(DebugLineData, OffsetPtr, nullptr);281  if (!DirDescriptors)282    return DirDescriptors.takeError();283 284  // Get the directory entries, according to the format described above.285  uint64_t DirEntryCount = DebugLineData.getULEB128(OffsetPtr);286  for (uint64_t I = 0; I != DirEntryCount; ++I) {287    for (auto Descriptor : *DirDescriptors) {288      DWARFFormValue Value(Descriptor.Form);289      switch (Descriptor.Type) {290      case DW_LNCT_path:291        if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))292          return createStringError(errc::invalid_argument,293                                   "failed to parse directory entry because "294                                   "extracting the form value failed");295        IncludeDirectories.push_back(Value);296        break;297      default:298        if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))299          return createStringError(errc::invalid_argument,300                                   "failed to parse directory entry because "301                                   "skipping the form value failed");302      }303    }304  }305 306  // Get the file entry description.307  llvm::Expected<ContentDescriptors> FileDescriptors =308      parseV5EntryFormat(DebugLineData, OffsetPtr, &ContentTypes);309  if (!FileDescriptors)310    return FileDescriptors.takeError();311 312  // Get the file entries, according to the format described above.313  uint64_t FileEntryCount = DebugLineData.getULEB128(OffsetPtr);314  for (uint64_t I = 0; I != FileEntryCount; ++I) {315    DWARFDebugLine::FileNameEntry FileEntry;316    for (auto Descriptor : *FileDescriptors) {317      DWARFFormValue Value(Descriptor.Form);318      if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))319        return createStringError(errc::invalid_argument,320                                 "failed to parse file entry because "321                                 "extracting the form value failed");322      switch (Descriptor.Type) {323      case DW_LNCT_path:324        FileEntry.Name = Value;325        break;326      case DW_LNCT_LLVM_source:327        FileEntry.Source = Value;328        break;329      case DW_LNCT_directory_index:330        FileEntry.DirIdx = *Value.getAsUnsignedConstant();331        break;332      case DW_LNCT_timestamp:333        FileEntry.ModTime = *Value.getAsUnsignedConstant();334        break;335      case DW_LNCT_size:336        FileEntry.Length = *Value.getAsUnsignedConstant();337        break;338      case DW_LNCT_MD5:339        if (!Value.getAsBlock() || Value.getAsBlock()->size() != 16)340          return createStringError(341              errc::invalid_argument,342              "failed to parse file entry because the MD5 hash is invalid");343        llvm::uninitialized_copy(*Value.getAsBlock(),344                                 FileEntry.Checksum.begin());345        break;346      default:347        break;348      }349    }350    FileNames.push_back(FileEntry);351  }352  return Error::success();353}354 355uint64_t DWARFDebugLine::Prologue::getLength() const {356  uint64_t Length = PrologueLength + sizeofTotalLength() +357                    sizeof(getVersion()) + sizeofPrologueLength();358  if (getVersion() >= 5)359    Length += 2; // Address + Segment selector sizes.360  return Length;361}362 363Error DWARFDebugLine::Prologue::parse(364    DWARFDataExtractor DebugLineData, uint64_t *OffsetPtr,365    function_ref<void(Error)> RecoverableErrorHandler, const DWARFContext &Ctx,366    const DWARFUnit *U) {367  const uint64_t PrologueOffset = *OffsetPtr;368 369  clear();370  DataExtractor::Cursor Cursor(*OffsetPtr);371  std::tie(TotalLength, FormParams.Format) =372      DebugLineData.getInitialLength(Cursor);373 374  DebugLineData =375      DWARFDataExtractor(DebugLineData, Cursor.tell() + TotalLength);376  FormParams.Version = DebugLineData.getU16(Cursor);377  if (Cursor && !versionIsSupported(getVersion())) {378    // Treat this error as unrecoverable - we cannot be sure what any of379    // the data represents including the length field, so cannot skip it or make380    // any reasonable assumptions.381    *OffsetPtr = Cursor.tell();382    return createStringError(383        errc::not_supported,384        "parsing line table prologue at offset 0x%8.8" PRIx64385        ": unsupported version %" PRIu16,386        PrologueOffset, getVersion());387  }388 389  if (getVersion() >= 5) {390    FormParams.AddrSize = DebugLineData.getU8(Cursor);391    const uint8_t DataAddrSize = DebugLineData.getAddressSize();392    const uint8_t PrologueAddrSize = getAddressSize();393    if (Cursor) {394      if (DataAddrSize == 0) {395        if (PrologueAddrSize != 4 && PrologueAddrSize != 8) {396          RecoverableErrorHandler(createStringError(397              errc::not_supported,398              "parsing line table prologue at offset 0x%8.8" PRIx64399              ": invalid address size %" PRIu8,400              PrologueOffset, PrologueAddrSize));401        }402      } else if (DataAddrSize != PrologueAddrSize) {403        RecoverableErrorHandler(createStringError(404            errc::not_supported,405            "parsing line table prologue at offset 0x%8.8" PRIx64 ": address "406            "size %" PRIu8 " doesn't match architecture address size %" PRIu8,407            PrologueOffset, PrologueAddrSize, DataAddrSize));408      }409    }410    SegSelectorSize = DebugLineData.getU8(Cursor);411  }412 413  PrologueLength =414      DebugLineData.getRelocatedValue(Cursor, sizeofPrologueLength());415  const uint64_t EndPrologueOffset = PrologueLength + Cursor.tell();416  DebugLineData = DWARFDataExtractor(DebugLineData, EndPrologueOffset);417  MinInstLength = DebugLineData.getU8(Cursor);418  if (getVersion() >= 4)419    MaxOpsPerInst = DebugLineData.getU8(Cursor);420  DefaultIsStmt = DebugLineData.getU8(Cursor);421  LineBase = DebugLineData.getU8(Cursor);422  LineRange = DebugLineData.getU8(Cursor);423  OpcodeBase = DebugLineData.getU8(Cursor);424 425  if (Cursor && OpcodeBase == 0) {426    // If the opcode base is 0, we cannot read the standard opcode lengths (of427    // which there are supposed to be one fewer than the opcode base). Assume428    // there are no standard opcodes and continue parsing.429    RecoverableErrorHandler(createStringError(430        errc::invalid_argument,431        "parsing line table prologue at offset 0x%8.8" PRIx64432        " found opcode base of 0. Assuming no standard opcodes",433        PrologueOffset));434  } else if (Cursor) {435    StandardOpcodeLengths.reserve(OpcodeBase - 1);436    for (uint32_t I = 1; I < OpcodeBase; ++I) {437      uint8_t OpLen = DebugLineData.getU8(Cursor);438      StandardOpcodeLengths.push_back(OpLen);439    }440  }441 442  *OffsetPtr = Cursor.tell();443  // A corrupt file name or directory table does not prevent interpretation of444  // the main line program, so check the cursor state now so that its errors can445  // be handled separately.446  if (!Cursor)447    return createStringError(448        errc::invalid_argument,449        "parsing line table prologue at offset 0x%8.8" PRIx64 ": %s",450        PrologueOffset, toString(Cursor.takeError()).c_str());451 452  Error E =453      getVersion() >= 5454          ? parseV5DirFileTables(DebugLineData, OffsetPtr, FormParams, Ctx, U,455                                 ContentTypes, IncludeDirectories, FileNames)456          : parseV2DirFileTables(DebugLineData, OffsetPtr, ContentTypes,457                                 IncludeDirectories, FileNames);458  if (E) {459    RecoverableErrorHandler(joinErrors(460        createStringError(461            errc::invalid_argument,462            "parsing line table prologue at 0x%8.8" PRIx64463            " found an invalid directory or file table description at"464            " 0x%8.8" PRIx64,465            PrologueOffset, *OffsetPtr),466        std::move(E)));467    return Error::success();468  }469 470  assert(*OffsetPtr <= EndPrologueOffset);471  if (*OffsetPtr != EndPrologueOffset) {472    RecoverableErrorHandler(createStringError(473        errc::invalid_argument,474        "unknown data in line table prologue at offset 0x%8.8" PRIx64475        ": parsing ended (at offset 0x%8.8" PRIx64476        ") before reaching the prologue end at offset 0x%8.8" PRIx64,477        PrologueOffset, *OffsetPtr, EndPrologueOffset));478  }479  return Error::success();480}481 482DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }483 484void DWARFDebugLine::Row::postAppend() {485  Discriminator = 0;486  BasicBlock = false;487  PrologueEnd = false;488  EpilogueBegin = false;489}490 491void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {492  Address.Address = 0;493  Address.SectionIndex = object::SectionedAddress::UndefSection;494  Line = 1;495  Column = 0;496  File = 1;497  Isa = 0;498  Discriminator = 0;499  IsStmt = DefaultIsStmt;500  OpIndex = 0;501  BasicBlock = false;502  EndSequence = false;503  PrologueEnd = false;504  EpilogueBegin = false;505}506 507void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS, unsigned Indent) {508  OS.indent(Indent)509      << "Address            Line   Column File   ISA Discriminator OpIndex "510         "Flags\n";511  OS.indent(Indent)512      << "------------------ ------ ------ ------ --- ------------- ------- "513         "-------------\n";514}515 516void DWARFDebugLine::Row::dump(raw_ostream &OS) const {517  OS << format("0x%16.16" PRIx64 " %6u %6u", Address.Address, Line, Column)518     << format(" %6u %3u %13u %7u ", File, Isa, Discriminator, OpIndex)519     << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")520     << (PrologueEnd ? " prologue_end" : "")521     << (EpilogueBegin ? " epilogue_begin" : "")522     << (EndSequence ? " end_sequence" : "") << '\n';523}524 525DWARFDebugLine::Sequence::Sequence() { reset(); }526 527void DWARFDebugLine::Sequence::reset() {528  LowPC = 0;529  HighPC = 0;530  SectionIndex = object::SectionedAddress::UndefSection;531  FirstRowIndex = 0;532  LastRowIndex = 0;533  Empty = true;534  StmtSeqOffset = UINT64_MAX;535}536 537DWARFDebugLine::LineTable::LineTable() { clear(); }538 539void DWARFDebugLine::LineTable::dump(raw_ostream &OS,540                                     DIDumpOptions DumpOptions) const {541  Prologue.dump(OS, DumpOptions);542 543  if (!Rows.empty()) {544    OS << '\n';545    Row::dumpTableHeader(OS, 0);546    for (const Row &R : Rows) {547      R.dump(OS);548    }549  }550 551  // Terminate the table with a final blank line to clearly delineate it from552  // later dumps.553  OS << '\n';554}555 556void DWARFDebugLine::LineTable::clear() {557  Prologue.clear();558  Rows.clear();559  Sequences.clear();560}561 562DWARFDebugLine::ParsingState::ParsingState(563    struct LineTable *LT, uint64_t TableOffset,564    function_ref<void(Error)> ErrorHandler)565    : LineTable(LT), LineTableOffset(TableOffset), ErrorHandler(ErrorHandler) {}566 567void DWARFDebugLine::ParsingState::resetRowAndSequence(uint64_t Offset) {568  Row.reset(LineTable->Prologue.DefaultIsStmt);569  Sequence.reset();570  Sequence.StmtSeqOffset = Offset;571}572 573void DWARFDebugLine::ParsingState::appendRowToMatrix() {574  unsigned RowNumber = LineTable->Rows.size();575  if (Sequence.Empty) {576    // Record the beginning of instruction sequence.577    Sequence.Empty = false;578    Sequence.LowPC = Row.Address.Address;579    Sequence.FirstRowIndex = RowNumber;580  }581  LineTable->appendRow(Row);582  if (Row.EndSequence) {583    // Record the end of instruction sequence.584    Sequence.HighPC = Row.Address.Address;585    Sequence.LastRowIndex = RowNumber + 1;586    Sequence.SectionIndex = Row.Address.SectionIndex;587    if (Sequence.isValid())588      LineTable->appendSequence(Sequence);589    Sequence.reset();590  }591  Row.postAppend();592}593 594const DWARFDebugLine::LineTable *595DWARFDebugLine::getLineTable(uint64_t Offset) const {596  LineTableConstIter Pos = LineTableMap.find(Offset);597  if (Pos != LineTableMap.end())598    return &Pos->second;599  return nullptr;600}601 602Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(603    DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx,604    const DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {605  if (!DebugLineData.isValidOffset(Offset))606    return createStringError(errc::invalid_argument,607                             "offset 0x%8.8" PRIx64608                             " is not a valid debug line section offset",609                             Offset);610 611  std::pair<LineTableIter, bool> Pos =612      LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));613  LineTable *LT = &Pos.first->second;614  if (Pos.second) {615    if (Error Err =616            LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorHandler))617      return std::move(Err);618    return LT;619  }620  return LT;621}622 623void DWARFDebugLine::clearLineTable(uint64_t Offset) {624  LineTableMap.erase(Offset);625}626 627static StringRef getOpcodeName(uint8_t Opcode, uint8_t OpcodeBase) {628  assert(Opcode != 0);629  if (Opcode < OpcodeBase)630    return LNStandardString(Opcode);631  return "special";632}633 634DWARFDebugLine::ParsingState::AddrOpIndexDelta635DWARFDebugLine::ParsingState::advanceAddrOpIndex(uint64_t OperationAdvance,636                                                 uint8_t Opcode,637                                                 uint64_t OpcodeOffset) {638  StringRef OpcodeName = getOpcodeName(Opcode, LineTable->Prologue.OpcodeBase);639  // For versions less than 4, the MaxOpsPerInst member is set to 0, as the640  // maximum_operations_per_instruction field wasn't introduced until DWARFv4.641  // Don't warn about bad values in this situation.642  if (ReportAdvanceAddrProblem && LineTable->Prologue.getVersion() >= 4 &&643      LineTable->Prologue.MaxOpsPerInst == 0)644    ErrorHandler(createStringError(645        errc::invalid_argument,646        "line table program at offset 0x%8.8" PRIx64647        " contains a %s opcode at offset 0x%8.8" PRIx64648        ", but the prologue maximum_operations_per_instruction value is 0"649        ", which is invalid. Assuming a value of 1 instead",650        LineTableOffset, OpcodeName.data(), OpcodeOffset));651  // Although we are able to correctly parse line number programs with652  // MaxOpsPerInst > 1, the rest of DWARFDebugLine and its653  // users have not been updated to handle line information for all operations654  // in a multi-operation instruction, so warn about potentially incorrect655  // results.656  if (ReportAdvanceAddrProblem && LineTable->Prologue.MaxOpsPerInst > 1)657    ErrorHandler(createStringError(658        errc::not_supported,659        "line table program at offset 0x%8.8" PRIx64660        " contains a %s opcode at offset 0x%8.8" PRIx64661        ", but the prologue maximum_operations_per_instruction value is %" PRId8662        ", which is experimentally supported, so line number information "663        "may be incorrect",664        LineTableOffset, OpcodeName.data(), OpcodeOffset,665        LineTable->Prologue.MaxOpsPerInst));666  if (ReportAdvanceAddrProblem && LineTable->Prologue.MinInstLength == 0)667    ErrorHandler(668        createStringError(errc::invalid_argument,669                          "line table program at offset 0x%8.8" PRIx64670                          " contains a %s opcode at offset 0x%8.8" PRIx64671                          ", but the prologue minimum_instruction_length value "672                          "is 0, which prevents any address advancing",673                          LineTableOffset, OpcodeName.data(), OpcodeOffset));674  ReportAdvanceAddrProblem = false;675 676  // Advances the address and op_index according to DWARFv5, section 6.2.5.1:677  //678  // new address = address +679  //   minimum_instruction_length *680  //   ((op_index + operation advance) / maximum_operations_per_instruction)681  //682  // new op_index =683  //   (op_index + operation advance) % maximum_operations_per_instruction684 685  // For versions less than 4, the MaxOpsPerInst member is set to 0, as the686  // maximum_operations_per_instruction field wasn't introduced until DWARFv4.687  uint8_t MaxOpsPerInst =688      std::max(LineTable->Prologue.MaxOpsPerInst, uint8_t{1});689 690  uint64_t AddrOffset = ((Row.OpIndex + OperationAdvance) / MaxOpsPerInst) *691                        LineTable->Prologue.MinInstLength;692  Row.Address.Address += AddrOffset;693 694  uint8_t PrevOpIndex = Row.OpIndex;695  Row.OpIndex = (Row.OpIndex + OperationAdvance) % MaxOpsPerInst;696  int16_t OpIndexDelta = static_cast<int16_t>(Row.OpIndex) - PrevOpIndex;697 698  return {AddrOffset, OpIndexDelta};699}700 701DWARFDebugLine::ParsingState::OpcodeAdvanceResults702DWARFDebugLine::ParsingState::advanceForOpcode(uint8_t Opcode,703                                               uint64_t OpcodeOffset) {704  assert(Opcode == DW_LNS_const_add_pc ||705         Opcode >= LineTable->Prologue.OpcodeBase);706  if (ReportBadLineRange && LineTable->Prologue.LineRange == 0) {707    StringRef OpcodeName =708        getOpcodeName(Opcode, LineTable->Prologue.OpcodeBase);709    ErrorHandler(710        createStringError(errc::not_supported,711                          "line table program at offset 0x%8.8" PRIx64712                          " contains a %s opcode at offset 0x%8.8" PRIx64713                          ", but the prologue line_range value is 0. The "714                          "address and line will not be adjusted",715                          LineTableOffset, OpcodeName.data(), OpcodeOffset));716    ReportBadLineRange = false;717  }718 719  uint8_t OpcodeValue = Opcode;720  if (Opcode == DW_LNS_const_add_pc)721    OpcodeValue = 255;722  uint8_t AdjustedOpcode = OpcodeValue - LineTable->Prologue.OpcodeBase;723  uint64_t OperationAdvance =724      LineTable->Prologue.LineRange != 0725          ? AdjustedOpcode / LineTable->Prologue.LineRange726          : 0;727  AddrOpIndexDelta Advance =728      advanceAddrOpIndex(OperationAdvance, Opcode, OpcodeOffset);729  return {Advance.AddrOffset, Advance.OpIndexDelta, AdjustedOpcode};730}731 732DWARFDebugLine::ParsingState::SpecialOpcodeDelta733DWARFDebugLine::ParsingState::handleSpecialOpcode(uint8_t Opcode,734                                                  uint64_t OpcodeOffset) {735  // A special opcode value is chosen based on the amount that needs736  // to be added to the line and address registers. The maximum line737  // increment for a special opcode is the value of the line_base738  // field in the header, plus the value of the line_range field,739  // minus 1 (line base + line range - 1). If the desired line740  // increment is greater than the maximum line increment, a standard741  // opcode must be used instead of a special opcode. The "address742  // advance" is calculated by dividing the desired address increment743  // by the minimum_instruction_length field from the header. The744  // special opcode is then calculated using the following formula:745  //746  //  opcode = (desired line increment - line_base) +747  //           (line_range * address advance) + opcode_base748  //749  // If the resulting opcode is greater than 255, a standard opcode750  // must be used instead.751  //752  // To decode a special opcode, subtract the opcode_base from the753  // opcode itself to give the adjusted opcode. The amount to754  // increment the address register is the result of the adjusted755  // opcode divided by the line_range multiplied by the756  // minimum_instruction_length field from the header. That is:757  //758  //  address increment = (adjusted opcode / line_range) *759  //                      minimum_instruction_length760  //761  // The amount to increment the line register is the line_base plus762  // the result of the adjusted opcode modulo the line_range. That is:763  //764  // line increment = line_base + (adjusted opcode % line_range)765 766  DWARFDebugLine::ParsingState::OpcodeAdvanceResults AddrAdvanceResult =767      advanceForOpcode(Opcode, OpcodeOffset);768  int32_t LineOffset = 0;769  if (LineTable->Prologue.LineRange != 0)770    LineOffset =771        LineTable->Prologue.LineBase +772        (AddrAdvanceResult.AdjustedOpcode % LineTable->Prologue.LineRange);773  Row.Line += LineOffset;774  return {AddrAdvanceResult.AddrDelta, LineOffset,775          AddrAdvanceResult.OpIndexDelta};776}777 778/// Parse a ULEB128 using the specified \p Cursor. \returns the parsed value on779/// success, or std::nullopt if \p Cursor is in a failing state.780template <typename T>781static std::optional<T> parseULEB128(DWARFDataExtractor &Data,782                                     DataExtractor::Cursor &Cursor) {783  T Value = Data.getULEB128(Cursor);784  if (Cursor)785    return Value;786  return std::nullopt;787}788 789Error DWARFDebugLine::LineTable::parse(790    DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,791    const DWARFContext &Ctx, const DWARFUnit *U,792    function_ref<void(Error)> RecoverableErrorHandler, raw_ostream *OS,793    bool Verbose) {794  assert((OS || !Verbose) && "cannot have verbose output without stream");795  const uint64_t DebugLineOffset = *OffsetPtr;796 797  clear();798 799  Error PrologueErr =800      Prologue.parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U);801 802  if (OS) {803    DIDumpOptions DumpOptions;804    DumpOptions.Verbose = Verbose;805    Prologue.dump(*OS, DumpOptions);806  }807 808  if (PrologueErr) {809    // Ensure there is a blank line after the prologue to clearly delineate it810    // from later dumps.811    if (OS)812      *OS << "\n";813    return PrologueErr;814  }815 816  uint64_t ProgramLength = Prologue.TotalLength + Prologue.sizeofTotalLength();817  if (!DebugLineData.isValidOffsetForDataOfSize(DebugLineOffset,818                                                ProgramLength)) {819    assert(DebugLineData.size() > DebugLineOffset &&820           "prologue parsing should handle invalid offset");821    uint64_t BytesRemaining = DebugLineData.size() - DebugLineOffset;822    RecoverableErrorHandler(823        createStringError(errc::invalid_argument,824                          "line table program with offset 0x%8.8" PRIx64825                          " has length 0x%8.8" PRIx64 " but only 0x%8.8" PRIx64826                          " bytes are available",827                          DebugLineOffset, ProgramLength, BytesRemaining));828    // Continue by capping the length at the number of remaining bytes.829    ProgramLength = BytesRemaining;830  }831 832  // Create a DataExtractor which can only see the data up to the end of the833  // table, to prevent reading past the end.834  const uint64_t EndOffset = DebugLineOffset + ProgramLength;835  DWARFDataExtractor TableData(DebugLineData, EndOffset);836 837  // See if we should tell the data extractor the address size.838  if (TableData.getAddressSize() == 0)839    TableData.setAddressSize(Prologue.getAddressSize());840  else841    assert(Prologue.getAddressSize() == 0 ||842           Prologue.getAddressSize() == TableData.getAddressSize());843 844  ParsingState State(this, DebugLineOffset, RecoverableErrorHandler);845 846  *OffsetPtr = DebugLineOffset + Prologue.getLength();847  if (OS && *OffsetPtr < EndOffset) {848    *OS << '\n';849    Row::dumpTableHeader(*OS, /*Indent=*/Verbose ? 12 : 0);850  }851  // *OffsetPtr points to the end of the prologue - i.e. the start of the first852  // sequence. So initialize the first sequence offset accordingly.853  State.resetRowAndSequence(*OffsetPtr);854 855  bool TombstonedAddress = false;856  auto EmitRow = [&] {857    if (!TombstonedAddress) {858      if (Verbose) {859        *OS << "\n";860        OS->indent(12);861      }862      if (OS)863        State.Row.dump(*OS);864      State.appendRowToMatrix();865    }866  };867  while (*OffsetPtr < EndOffset) {868    DataExtractor::Cursor Cursor(*OffsetPtr);869 870    if (Verbose)871      *OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);872 873    uint64_t OpcodeOffset = *OffsetPtr;874    uint8_t Opcode = TableData.getU8(Cursor);875    size_t RowCount = Rows.size();876 877    if (Cursor && Verbose)878      *OS << format("%02.02" PRIx8 " ", Opcode);879 880    if (Opcode == 0) {881      // Extended Opcodes always start with a zero opcode followed by882      // a uleb128 length so you can skip ones you don't know about883      uint64_t Len = TableData.getULEB128(Cursor);884      uint64_t ExtOffset = Cursor.tell();885 886      // Tolerate zero-length; assume length is correct and soldier on.887      if (Len == 0) {888        if (Cursor && Verbose)889          *OS << "Badly formed extended line op (length 0)\n";890        if (!Cursor) {891          if (Verbose)892            *OS << "\n";893          RecoverableErrorHandler(Cursor.takeError());894        }895        *OffsetPtr = Cursor.tell();896        continue;897      }898 899      uint8_t SubOpcode = TableData.getU8(Cursor);900      // OperandOffset will be the same as ExtOffset, if it was not possible to901      // read the SubOpcode.902      uint64_t OperandOffset = Cursor.tell();903      if (Verbose)904        *OS << LNExtendedString(SubOpcode);905      switch (SubOpcode) {906      case DW_LNE_end_sequence:907        // Set the end_sequence register of the state machine to true and908        // append a row to the matrix using the current values of the909        // state-machine registers. Then reset the registers to the initial910        // values specified above. Every statement program sequence must end911        // with a DW_LNE_end_sequence instruction which creates a row whose912        // address is that of the byte after the last target machine instruction913        // of the sequence.914        State.Row.EndSequence = true;915        // No need to test the Cursor is valid here, since it must be to get916        // into this code path - if it were invalid, the default case would be917        // followed.918        EmitRow();919        // Cursor now points to right after the end_sequence opcode - so points920        // to the start of the next sequence - if one exists.921        State.resetRowAndSequence(Cursor.tell());922        break;923 924      case DW_LNE_set_address:925        // Takes a single relocatable address as an operand. The size of the926        // operand is the size appropriate to hold an address on the target927        // machine. Set the address register to the value given by the928        // relocatable address and set the op_index register to 0. All of the929        // other statement program opcodes that affect the address register930        // add a delta to it. This instruction stores a relocatable value into931        // it instead.932        //933        // Make sure the extractor knows the address size.  If not, infer it934        // from the size of the operand.935        {936          uint8_t ExtractorAddressSize = TableData.getAddressSize();937          uint64_t OpcodeAddressSize = Len - 1;938          if (ExtractorAddressSize != OpcodeAddressSize &&939              ExtractorAddressSize != 0)940            RecoverableErrorHandler(createStringError(941                errc::invalid_argument,942                "mismatching address size at offset 0x%8.8" PRIx64943                " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,944                ExtOffset, ExtractorAddressSize, Len - 1));945 946          // Assume that the line table is correct and temporarily override the947          // address size. If the size is unsupported, give up trying to read948          // the address and continue to the next opcode.949          if (OpcodeAddressSize != 1 && OpcodeAddressSize != 2 &&950              OpcodeAddressSize != 4 && OpcodeAddressSize != 8) {951            RecoverableErrorHandler(createStringError(952                errc::invalid_argument,953                "address size 0x%2.2" PRIx64954                " of DW_LNE_set_address opcode at offset 0x%8.8" PRIx64955                " is unsupported",956                OpcodeAddressSize, ExtOffset));957            TableData.skip(Cursor, OpcodeAddressSize);958          } else {959            TableData.setAddressSize(OpcodeAddressSize);960            State.Row.Address.Address = TableData.getRelocatedAddress(961                Cursor, &State.Row.Address.SectionIndex);962            State.Row.OpIndex = 0;963 964            uint64_t Tombstone =965                dwarf::computeTombstoneAddress(OpcodeAddressSize);966            TombstonedAddress = State.Row.Address.Address == Tombstone;967 968            // Restore the address size if the extractor already had it.969            if (ExtractorAddressSize != 0)970              TableData.setAddressSize(ExtractorAddressSize);971          }972 973          if (Cursor && Verbose) {974            *OS << " (";975            DWARFFormValue::dumpAddress(*OS, OpcodeAddressSize,976                                        State.Row.Address.Address);977            *OS << ')';978          }979        }980        break;981 982      case DW_LNE_define_file:983        // Takes 4 arguments. The first is a null terminated string containing984        // a source file name. The second is an unsigned LEB128 number985        // representing the directory index of the directory in which the file986        // was found. The third is an unsigned LEB128 number representing the987        // time of last modification of the file. The fourth is an unsigned988        // LEB128 number representing the length in bytes of the file. The time989        // and length fields may contain LEB128(0) if the information is not990        // available.991        //992        // The directory index represents an entry in the include_directories993        // section of the statement program prologue. The index is LEB128(0)994        // if the file was found in the current directory of the compilation,995        // LEB128(1) if it was found in the first directory in the996        // include_directories section, and so on. The directory index is997        // ignored for file names that represent full path names.998        //999        // The files are numbered, starting at 1, in the order in which they1000        // appear; the names in the prologue come before names defined by1001        // the DW_LNE_define_file instruction. These numbers are used in the1002        // the file register of the state machine.1003        {1004          FileNameEntry FileEntry;1005          const char *Name = TableData.getCStr(Cursor);1006          FileEntry.Name =1007              DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name);1008          FileEntry.DirIdx = TableData.getULEB128(Cursor);1009          FileEntry.ModTime = TableData.getULEB128(Cursor);1010          FileEntry.Length = TableData.getULEB128(Cursor);1011          Prologue.FileNames.push_back(FileEntry);1012          if (Cursor && Verbose)1013            *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="1014                << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)1015                << ", length=" << FileEntry.Length << ")";1016        }1017        break;1018 1019      case DW_LNE_set_discriminator:1020        State.Row.Discriminator = TableData.getULEB128(Cursor);1021        if (Cursor && Verbose)1022          *OS << " (" << State.Row.Discriminator << ")";1023        break;1024 1025      default:1026        if (Cursor && Verbose)1027          *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)1028              << format(" length %" PRIx64, Len);1029        // Len doesn't include the zero opcode byte or the length itself, but1030        // it does include the sub_opcode, so we have to adjust for that.1031        TableData.skip(Cursor, Len - 1);1032        break;1033      }1034      // Make sure the length as recorded in the table and the standard length1035      // for the opcode match. If they don't, continue from the end as claimed1036      // by the table. Similarly, continue from the claimed end in the event of1037      // a parsing error.1038      uint64_t End = ExtOffset + Len;1039      if (Cursor && Cursor.tell() != End)1040        RecoverableErrorHandler(createStringError(1041            errc::illegal_byte_sequence,1042            "unexpected line op length at offset 0x%8.8" PRIx641043            " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64,1044            ExtOffset, Len, Cursor.tell() - ExtOffset));1045      if (!Cursor && Verbose) {1046        DWARFDataExtractor::Cursor ByteCursor(OperandOffset);1047        uint8_t Byte = TableData.getU8(ByteCursor);1048        if (ByteCursor) {1049          *OS << " (<parsing error>";1050          do {1051            *OS << format(" %2.2" PRIx8, Byte);1052            Byte = TableData.getU8(ByteCursor);1053          } while (ByteCursor);1054          *OS << ")";1055        }1056 1057        // The only parse failure in this case should be if the end was reached.1058        // In that case, throw away the error, as the main Cursor's error will1059        // be sufficient.1060        consumeError(ByteCursor.takeError());1061      }1062      *OffsetPtr = End;1063    } else if (Opcode < Prologue.OpcodeBase) {1064      if (Verbose)1065        *OS << LNStandardString(Opcode);1066      switch (Opcode) {1067      // Standard Opcodes1068      case DW_LNS_copy:1069        // Takes no arguments. Append a row to the matrix using the1070        // current values of the state-machine registers.1071        EmitRow();1072        break;1073 1074      case DW_LNS_advance_pc:1075        // Takes a single unsigned LEB128 operand as the operation advance1076        // and modifies the address and op_index registers of the state machine1077        // according to that.1078        if (std::optional<uint64_t> Operand =1079                parseULEB128<uint64_t>(TableData, Cursor)) {1080          ParsingState::AddrOpIndexDelta Advance =1081              State.advanceAddrOpIndex(*Operand, Opcode, OpcodeOffset);1082          if (Verbose)1083            *OS << " (addr += " << Advance.AddrOffset1084                << ", op-index += " << Advance.OpIndexDelta << ")";1085        }1086        break;1087 1088      case DW_LNS_advance_line:1089        // Takes a single signed LEB128 operand and adds that value to1090        // the line register of the state machine.1091        {1092          int64_t LineDelta = TableData.getSLEB128(Cursor);1093          if (Cursor) {1094            State.Row.Line += LineDelta;1095            if (Verbose)1096              *OS << " (" << State.Row.Line << ")";1097          }1098        }1099        break;1100 1101      case DW_LNS_set_file:1102        // Takes a single unsigned LEB128 operand and stores it in the file1103        // register of the state machine.1104        if (std::optional<uint16_t> File =1105                parseULEB128<uint16_t>(TableData, Cursor)) {1106          State.Row.File = *File;1107          if (Verbose)1108            *OS << " (" << State.Row.File << ")";1109        }1110        break;1111 1112      case DW_LNS_set_column:1113        // Takes a single unsigned LEB128 operand and stores it in the1114        // column register of the state machine.1115        if (std::optional<uint16_t> Column =1116                parseULEB128<uint16_t>(TableData, Cursor)) {1117          State.Row.Column = *Column;1118          if (Verbose)1119            *OS << " (" << State.Row.Column << ")";1120        }1121        break;1122 1123      case DW_LNS_negate_stmt:1124        // Takes no arguments. Set the is_stmt register of the state1125        // machine to the logical negation of its current value.1126        State.Row.IsStmt = !State.Row.IsStmt;1127        break;1128 1129      case DW_LNS_set_basic_block:1130        // Takes no arguments. Set the basic_block register of the1131        // state machine to true1132        State.Row.BasicBlock = true;1133        break;1134 1135      case DW_LNS_const_add_pc:1136        // Takes no arguments. Advance the address and op_index registers of1137        // the state machine by the increments corresponding to special1138        // opcode 255. The motivation for DW_LNS_const_add_pc is this:1139        // when the statement program needs to advance the address by a1140        // small amount, it can use a single special opcode, which occupies1141        // a single byte. When it needs to advance the address by up to1142        // twice the range of the last special opcode, it can use1143        // DW_LNS_const_add_pc followed by a special opcode, for a total1144        // of two bytes. Only if it needs to advance the address by more1145        // than twice that range will it need to use both DW_LNS_advance_pc1146        // and a special opcode, requiring three or more bytes.1147        {1148          ParsingState::OpcodeAdvanceResults Advance =1149              State.advanceForOpcode(Opcode, OpcodeOffset);1150          if (Verbose)1151            *OS << format(" (addr += 0x%16.16" PRIx64 ", op-index += %" PRIu81152                          ")",1153                          Advance.AddrDelta, Advance.OpIndexDelta);1154        }1155        break;1156 1157      case DW_LNS_fixed_advance_pc:1158        // Takes a single uhalf operand. Add to the address register of1159        // the state machine the value of the (unencoded) operand and set1160        // the op_index register to 0. This is the only extended opcode that1161        // takes an argument that is not a variable length number.1162        // The motivation for DW_LNS_fixed_advance_pc is this: existing1163        // assemblers cannot emit DW_LNS_advance_pc or special opcodes because1164        // they cannot encode LEB128 numbers or judge when the computation1165        // of a special opcode overflows and requires the use of1166        // DW_LNS_advance_pc. Such assemblers, however, can use1167        // DW_LNS_fixed_advance_pc instead, sacrificing compression.1168        {1169          uint16_t PCOffset = TableData.getRelocatedValue(Cursor, 2);1170          if (Cursor) {1171            State.Row.Address.Address += PCOffset;1172            State.Row.OpIndex = 0;1173            if (Verbose)1174              *OS << format(" (addr += 0x%4.4" PRIx16 ", op-index = 0)",1175                            PCOffset);1176          }1177        }1178        break;1179 1180      case DW_LNS_set_prologue_end:1181        // Takes no arguments. Set the prologue_end register of the1182        // state machine to true1183        State.Row.PrologueEnd = true;1184        break;1185 1186      case DW_LNS_set_epilogue_begin:1187        // Takes no arguments. Set the basic_block register of the1188        // state machine to true1189        State.Row.EpilogueBegin = true;1190        break;1191 1192      case DW_LNS_set_isa:1193        // Takes a single unsigned LEB128 operand and stores it in the1194        // ISA register of the state machine.1195        if (std::optional<uint8_t> Isa =1196                parseULEB128<uint8_t>(TableData, Cursor)) {1197          State.Row.Isa = *Isa;1198          if (Verbose)1199            *OS << " (" << (uint64_t)State.Row.Isa << ")";1200        }1201        break;1202 1203      default:1204        // Handle any unknown standard opcodes here. We know the lengths1205        // of such opcodes because they are specified in the prologue1206        // as a multiple of LEB128 operands for each opcode.1207        {1208          assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());1209          if (Verbose)1210            *OS << "Unrecognized standard opcode";1211          uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];1212          std::vector<uint64_t> Operands;1213          for (uint8_t I = 0; I < OpcodeLength; ++I) {1214            if (std::optional<uint64_t> Value =1215                    parseULEB128<uint64_t>(TableData, Cursor))1216              Operands.push_back(*Value);1217            else1218              break;1219          }1220          if (Verbose && !Operands.empty()) {1221            *OS << " (operands: ";1222            bool First = true;1223            for (uint64_t Value : Operands) {1224              if (!First)1225                *OS << ", ";1226              First = false;1227              *OS << format("0x%16.16" PRIx64, Value);1228            }1229            if (Verbose)1230              *OS << ')';1231          }1232        }1233        break;1234      }1235 1236      *OffsetPtr = Cursor.tell();1237    } else {1238      // Special Opcodes.1239      ParsingState::SpecialOpcodeDelta Delta =1240          State.handleSpecialOpcode(Opcode, OpcodeOffset);1241 1242      if (Verbose)1243        *OS << "address += " << Delta.Address << ",  line += " << Delta.Line1244            << ",  op-index += " << Delta.OpIndex;1245      EmitRow();1246      *OffsetPtr = Cursor.tell();1247    }1248 1249    // When a row is added to the matrix, it is also dumped, which includes a1250    // new line already, so don't add an extra one.1251    if (Verbose && Rows.size() == RowCount)1252      *OS << "\n";1253 1254    // Most parse failures other than when parsing extended opcodes are due to1255    // failures to read ULEBs. Bail out of parsing, since we don't know where to1256    // continue reading from as there is no stated length for such byte1257    // sequences. Print the final trailing new line if needed before doing so.1258    if (!Cursor && Opcode != 0) {1259      if (Verbose)1260        *OS << "\n";1261      return Cursor.takeError();1262    }1263 1264    if (!Cursor)1265      RecoverableErrorHandler(Cursor.takeError());1266  }1267 1268  if (!State.Sequence.Empty)1269    RecoverableErrorHandler(createStringError(1270        errc::illegal_byte_sequence,1271        "last sequence in debug line table at offset 0x%8.8" PRIx641272        " is not terminated",1273        DebugLineOffset));1274 1275  // Sort all sequences so that address lookup will work faster.1276  if (!Sequences.empty()) {1277    llvm::stable_sort(Sequences, Sequence::orderByHighPC);1278    // Note: actually, instruction address ranges of sequences should not1279    // overlap (in shared objects and executables). If they do, the address1280    // lookup would still work, though, but result would be ambiguous.1281    // We don't report warning in this case. For example,1282    // sometimes .so compiled from multiple object files contains a few1283    // rudimentary sequences for address ranges [0x0, 0xsomething).1284    // Address ranges may also overlap when using ICF.1285  }1286 1287  // Terminate the table with a final blank line to clearly delineate it from1288  // later dumps.1289  if (OS)1290    *OS << "\n";1291 1292  return Error::success();1293}1294 1295uint32_t DWARFDebugLine::LineTable::findRowInSeq(1296    const DWARFDebugLine::Sequence &Seq,1297    object::SectionedAddress Address) const {1298  if (!Seq.containsPC(Address))1299    return UnknownRowIndex;1300  assert(Seq.SectionIndex == Address.SectionIndex);1301  // In some cases, e.g. first instruction in a function, the compiler generates1302  // two entries, both with the same address. We want the last one.1303  //1304  // In general we want a non-empty range: the last row whose address is less1305  // than or equal to Address. This can be computed as upper_bound - 1.1306  //1307  // TODO: This function, and its users, needs to be update to return multiple1308  // rows for bundles with multiple op-indexes.1309  DWARFDebugLine::Row Row;1310  Row.Address = Address;1311  RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;1312  RowIter LastRow = Rows.begin() + Seq.LastRowIndex;1313  assert(FirstRow->Address.Address <= Row.Address.Address &&1314         Row.Address.Address < LastRow[-1].Address.Address);1315  RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1, Row,1316                                    DWARFDebugLine::Row::orderByAddress) -1317                   1;1318  assert(Seq.SectionIndex == RowPos->Address.SectionIndex);1319  return RowPos - Rows.begin();1320}1321 1322uint32_t1323DWARFDebugLine::LineTable::lookupAddress(object::SectionedAddress Address,1324                                         bool *IsApproximateLine) const {1325 1326  // Search for relocatable addresses1327  uint32_t Result = lookupAddressImpl(Address, IsApproximateLine);1328 1329  if (Result != UnknownRowIndex ||1330      Address.SectionIndex == object::SectionedAddress::UndefSection)1331    return Result;1332 1333  // Search for absolute addresses1334  Address.SectionIndex = object::SectionedAddress::UndefSection;1335  return lookupAddressImpl(Address, IsApproximateLine);1336}1337 1338uint32_t1339DWARFDebugLine::LineTable::lookupAddressImpl(object::SectionedAddress Address,1340                                             bool *IsApproximateLine) const {1341  assert((!IsApproximateLine || !*IsApproximateLine) &&1342         "Make sure IsApproximateLine is appropriately "1343         "initialized, if provided");1344  // First, find an instruction sequence containing the given address.1345  DWARFDebugLine::Sequence Sequence;1346  Sequence.SectionIndex = Address.SectionIndex;1347  Sequence.HighPC = Address.Address;1348  SequenceIter It = llvm::upper_bound(Sequences, Sequence,1349                                      DWARFDebugLine::Sequence::orderByHighPC);1350  if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex)1351    return UnknownRowIndex;1352 1353  uint32_t RowIndex = findRowInSeq(*It, Address);1354  if (RowIndex == UnknownRowIndex || !IsApproximateLine)1355    return RowIndex;1356 1357  // Approximation will only be attempted if a valid RowIndex exists.1358  uint32_t ApproxRowIndex = RowIndex;1359  // Approximation Loop1360  for (; ApproxRowIndex >= It->FirstRowIndex; --ApproxRowIndex) {1361    if (Rows[ApproxRowIndex].Line)1362      return ApproxRowIndex;1363    *IsApproximateLine = true;1364  }1365  // Approximation Loop fails to find the valid ApproxRowIndex1366  if (ApproxRowIndex < It->FirstRowIndex)1367    *IsApproximateLine = false;1368 1369  return RowIndex;1370}1371 1372bool DWARFDebugLine::LineTable::lookupAddressRange(1373    object::SectionedAddress Address, uint64_t Size,1374    std::vector<uint32_t> &Result,1375    std::optional<uint64_t> StmtSequenceOffset) const {1376 1377  // Search for relocatable addresses1378  if (lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset))1379    return true;1380 1381  if (Address.SectionIndex == object::SectionedAddress::UndefSection)1382    return false;1383 1384  // Search for absolute addresses1385  Address.SectionIndex = object::SectionedAddress::UndefSection;1386  return lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset);1387}1388 1389bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(1390    object::SectionedAddress Address, uint64_t Size,1391    std::vector<uint32_t> &Result,1392    std::optional<uint64_t> StmtSequenceOffset) const {1393  if (Sequences.empty())1394    return false;1395  uint64_t EndAddr = Address.Address + Size;1396  // First, find an instruction sequence containing the given address.1397  DWARFDebugLine::Sequence Sequence;1398  Sequence.SectionIndex = Address.SectionIndex;1399  Sequence.HighPC = Address.Address;1400  SequenceIter LastSeq = Sequences.end();1401  SequenceIter SeqPos;1402 1403  if (StmtSequenceOffset) {1404    // If we have a statement sequence offset, find the specific sequence.1405    // Linear search for sequence with matching StmtSeqOffset1406    SeqPos = std::find_if(Sequences.begin(), LastSeq,1407                          [&](const DWARFDebugLine::Sequence &S) {1408                            return S.StmtSeqOffset == *StmtSequenceOffset;1409                          });1410 1411    // If sequence not found, return false1412    if (SeqPos == LastSeq)1413      return false;1414 1415    // Set LastSeq to the next sequence since we only want the one matching1416    // sequence (sequences are guaranteed to have unique StmtSeqOffset)1417    LastSeq = SeqPos + 1;1418  } else {1419    // No specific sequence requested, find first sequence containing address1420    SeqPos = std::upper_bound(Sequences.begin(), LastSeq, Sequence,1421                              DWARFDebugLine::Sequence::orderByHighPC);1422    if (SeqPos == LastSeq)1423      return false;1424  }1425 1426  // If the start sequence doesn't contain the address, nothing to do1427  if (!SeqPos->containsPC(Address))1428    return false;1429 1430  SequenceIter StartPos = SeqPos;1431 1432  // Process sequences that overlap with the desired range1433  while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {1434    const DWARFDebugLine::Sequence &CurSeq = *SeqPos;1435    // For the first sequence, we need to find which row in the sequence is the1436    // first in our range.1437    uint32_t FirstRowIndex = CurSeq.FirstRowIndex;1438    if (SeqPos == StartPos)1439      FirstRowIndex = findRowInSeq(CurSeq, Address);1440 1441    // Figure out the last row in the range.1442    uint32_t LastRowIndex =1443        findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex});1444    if (LastRowIndex == UnknownRowIndex)1445      LastRowIndex = CurSeq.LastRowIndex - 1;1446 1447    assert(FirstRowIndex != UnknownRowIndex);1448    assert(LastRowIndex != UnknownRowIndex);1449 1450    for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {1451      Result.push_back(I);1452    }1453 1454    ++SeqPos;1455  }1456 1457  return true;1458}1459 1460std::optional<StringRef>1461DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,1462                                            FileLineInfoKind Kind) const {1463  if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex))1464    return std::nullopt;1465  const FileNameEntry &Entry = Prologue.getFileNameEntry(FileIndex);1466  if (auto E = dwarf::toString(Entry.Source))1467    return StringRef(*E);1468  return std::nullopt;1469}1470 1471static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {1472  // Debug info can contain paths from any OS, not necessarily1473  // an OS we're currently running on. Moreover different compilation units can1474  // be compiled on different operating systems and linked together later.1475  return sys::path::is_absolute(Path, sys::path::Style::posix) ||1476         sys::path::is_absolute(Path, sys::path::Style::windows);1477}1478 1479bool DWARFDebugLine::Prologue::getFileNameByIndex(1480    uint64_t FileIndex, StringRef CompDir, FileLineInfoKind Kind,1481    std::string &Result, sys::path::Style Style) const {1482  if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))1483    return false;1484  const FileNameEntry &Entry = getFileNameEntry(FileIndex);1485  auto E = dwarf::toString(Entry.Name);1486  if (!E)1487    return false;1488  StringRef FileName = *E;1489  if (Kind == FileLineInfoKind::RawValue ||1490      isPathAbsoluteOnWindowsOrPosix(FileName)) {1491    Result = std::string(FileName);1492    return true;1493  }1494  if (Kind == FileLineInfoKind::BaseNameOnly) {1495    Result = std::string(llvm::sys::path::filename(FileName));1496    return true;1497  }1498 1499  SmallString<16> FilePath;1500  StringRef IncludeDir;1501  // Be defensive about the contents of Entry.1502  if (getVersion() >= 5) {1503    // DirIdx 0 is the compilation directory, so don't include it for1504    // relative names.1505    if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) &&1506        Entry.DirIdx < IncludeDirectories.size())1507      IncludeDir = dwarf::toStringRef(IncludeDirectories[Entry.DirIdx]);1508  } else {1509    if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size())1510      IncludeDir = dwarf::toStringRef(IncludeDirectories[Entry.DirIdx - 1]);1511  }1512 1513  // For absolute paths only, include the compilation directory of compile unit,1514  // unless v5 DirIdx == 0 (IncludeDir indicates the compilation directory). We1515  // know that FileName is not absolute, the only way to have an absolute path1516  // at this point would be if IncludeDir is absolute.1517  if (Kind == FileLineInfoKind::AbsoluteFilePath &&1518      (getVersion() < 5 || Entry.DirIdx != 0) && !CompDir.empty() &&1519      !isPathAbsoluteOnWindowsOrPosix(IncludeDir))1520    sys::path::append(FilePath, Style, CompDir);1521 1522  assert((Kind == FileLineInfoKind::AbsoluteFilePath ||1523          Kind == FileLineInfoKind::RelativeFilePath) &&1524         "invalid FileLineInfo Kind");1525 1526  // sys::path::append skips empty strings.1527  sys::path::append(FilePath, Style, IncludeDir, FileName);1528  Result = std::string(FilePath);1529  return true;1530}1531 1532bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(1533    object::SectionedAddress Address, bool Approximate, const char *CompDir,1534    FileLineInfoKind Kind, DILineInfo &Result) const {1535  // Get the index of row we're looking for in the line table.1536  uint32_t RowIndex =1537      lookupAddress(Address, Approximate ? &Result.IsApproximateLine : nullptr);1538  if (RowIndex == -1U)1539    return false;1540  // Take file number and line/column from the row.1541  const auto &Row = Rows[RowIndex];1542  if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))1543    return false;1544  Result.Line = Row.Line;1545  Result.Column = Row.Column;1546  Result.Discriminator = Row.Discriminator;1547  Result.Source = getSourceByIndex(Row.File, Kind);1548  return true;1549}1550 1551bool DWARFDebugLine::LineTable::getDirectoryForEntry(1552    const FileNameEntry &Entry, std::string &Directory) const {1553  if (Prologue.getVersion() >= 5) {1554    if (Entry.DirIdx < Prologue.IncludeDirectories.size()) {1555      Directory =1556          dwarf::toString(Prologue.IncludeDirectories[Entry.DirIdx], "");1557      return true;1558    }1559    return false;1560  }1561  if (0 < Entry.DirIdx && Entry.DirIdx <= Prologue.IncludeDirectories.size()) {1562    Directory =1563        dwarf::toString(Prologue.IncludeDirectories[Entry.DirIdx - 1], "");1564    return true;1565  }1566  return false;1567}1568 1569// We want to supply the Unit associated with a .debug_line[.dwo] table when1570// we dump it, if possible, but still dump the table even if there isn't a Unit.1571// Therefore, collect up handles on all the Units that point into the1572// line-table section.1573static DWARFDebugLine::SectionParser::LineToUnitMap1574buildLineToUnitMap(DWARFUnitVector::iterator_range Units) {1575  DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit;1576  for (const auto &U : Units)1577    if (auto CUDIE = U->getUnitDIE())1578      if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))1579        LineToUnit.insert(std::make_pair(*StmtOffset, &*U));1580  return LineToUnit;1581}1582 1583DWARFDebugLine::SectionParser::SectionParser(1584    DWARFDataExtractor &Data, const DWARFContext &C,1585    DWARFUnitVector::iterator_range Units)1586    : DebugLineData(Data), Context(C) {1587  LineToUnit = buildLineToUnitMap(Units);1588  if (!DebugLineData.isValidOffset(Offset))1589    Done = true;1590}1591 1592bool DWARFDebugLine::Prologue::totalLengthIsValid() const {1593  return TotalLength != 0u;1594}1595 1596DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(1597    function_ref<void(Error)> RecoverableErrorHandler,1598    function_ref<void(Error)> UnrecoverableErrorHandler, raw_ostream *OS,1599    bool Verbose) {1600  assert(DebugLineData.isValidOffset(Offset) &&1601         "parsing should have terminated");1602  DWARFUnit *U = prepareToParse(Offset);1603  uint64_t OldOffset = Offset;1604  LineTable LT;1605  if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,1606                           RecoverableErrorHandler, OS, Verbose))1607    UnrecoverableErrorHandler(std::move(Err));1608  moveToNextTable(OldOffset, LT.Prologue);1609  return LT;1610}1611 1612void DWARFDebugLine::SectionParser::skip(1613    function_ref<void(Error)> RecoverableErrorHandler,1614    function_ref<void(Error)> UnrecoverableErrorHandler) {1615  assert(DebugLineData.isValidOffset(Offset) &&1616         "parsing should have terminated");1617  DWARFUnit *U = prepareToParse(Offset);1618  uint64_t OldOffset = Offset;1619  LineTable LT;1620  if (Error Err = LT.Prologue.parse(DebugLineData, &Offset,1621                                    RecoverableErrorHandler, Context, U))1622    UnrecoverableErrorHandler(std::move(Err));1623  moveToNextTable(OldOffset, LT.Prologue);1624}1625 1626DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint64_t Offset) {1627  DWARFUnit *U = nullptr;1628  auto It = LineToUnit.find(Offset);1629  if (It != LineToUnit.end())1630    U = It->second;1631  DebugLineData.setAddressSize(U ? U->getAddressByteSize() : 0);1632  return U;1633}1634 1635bool DWARFDebugLine::SectionParser::hasValidVersion(uint64_t Offset) {1636  DataExtractor::Cursor Cursor(Offset);1637  auto [TotalLength, _] = DebugLineData.getInitialLength(Cursor);1638  DWARFDataExtractor HeaderData(DebugLineData, Cursor.tell() + TotalLength);1639  uint16_t Version = HeaderData.getU16(Cursor);1640  if (!Cursor) {1641    // Ignore any error here.1642    // If this is not the end of the section parseNext() will still be1643    // attempted, where this error will occur again (and can be handled).1644    consumeError(Cursor.takeError());1645    return false;1646  }1647  return versionIsSupported(Version);1648}1649 1650void DWARFDebugLine::SectionParser::moveToNextTable(uint64_t OldOffset,1651                                                    const Prologue &P) {1652  // If the length field is not valid, we don't know where the next table is, so1653  // cannot continue to parse. Mark the parser as done, and leave the Offset1654  // value as it currently is. This will be the end of the bad length field.1655  if (!P.totalLengthIsValid()) {1656    Done = true;1657    return;1658  }1659 1660  Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();1661  if (!DebugLineData.isValidOffset(Offset)) {1662    Done = true;1663    return;1664  }1665 1666  // Heuristic: If the version is valid, then this is probably a line table.1667  // Otherwise, the offset might need alignment (to a 4 or 8 byte boundary).1668  if (hasValidVersion(Offset))1669    return;1670 1671  // ARM C/C++ Compiler aligns each line table to word boundaries and pads out1672  // the .debug_line section to a word multiple. Note that in the specification1673  // this does not seem forbidden since each unit has a DW_AT_stmt_list.1674  for (unsigned Align : {4, 8}) {1675    uint64_t AlignedOffset = alignTo(Offset, Align);1676    if (!DebugLineData.isValidOffset(AlignedOffset)) {1677      // This is almost certainly not another line table but some alignment1678      // padding. This assumes the alignments tested are ordered, and are1679      // smaller than the header size (which is true for 4 and 8).1680      Done = true;1681      return;1682    }1683    if (hasValidVersion(AlignedOffset)) {1684      Offset = AlignedOffset;1685      break;1686    }1687  }1688}1689