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