xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
10b57cec5SDimitry Andric //===- DWARFDebugLine.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
100b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
110b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
120b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
130b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
140b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
170b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
180b57cec5SDimitry Andric #include "llvm/Support/Format.h"
190b57cec5SDimitry Andric #include "llvm/Support/WithColor.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <algorithm>
220b57cec5SDimitry Andric #include <cassert>
230b57cec5SDimitry Andric #include <cinttypes>
240b57cec5SDimitry Andric #include <cstdint>
250b57cec5SDimitry Andric #include <cstdio>
260b57cec5SDimitry Andric #include <utility>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric using namespace dwarf;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace {
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric struct ContentDescriptor {
360b57cec5SDimitry Andric   dwarf::LineNumberEntryFormat Type;
370b57cec5SDimitry Andric   dwarf::Form Form;
380b57cec5SDimitry Andric };
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric } // end anonmyous namespace
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric void DWARFDebugLine::ContentTypeTracker::trackContentType(
450b57cec5SDimitry Andric     dwarf::LineNumberEntryFormat ContentType) {
460b57cec5SDimitry Andric   switch (ContentType) {
470b57cec5SDimitry Andric   case dwarf::DW_LNCT_timestamp:
480b57cec5SDimitry Andric     HasModTime = true;
490b57cec5SDimitry Andric     break;
500b57cec5SDimitry Andric   case dwarf::DW_LNCT_size:
510b57cec5SDimitry Andric     HasLength = true;
520b57cec5SDimitry Andric     break;
530b57cec5SDimitry Andric   case dwarf::DW_LNCT_MD5:
540b57cec5SDimitry Andric     HasMD5 = true;
550b57cec5SDimitry Andric     break;
560b57cec5SDimitry Andric   case dwarf::DW_LNCT_LLVM_source:
570b57cec5SDimitry Andric     HasSource = true;
580b57cec5SDimitry Andric     break;
590b57cec5SDimitry Andric   default:
600b57cec5SDimitry Andric     // We only care about values we consider optional, and new values may be
610b57cec5SDimitry Andric     // added in the vendor extension range, so we do not match exhaustively.
620b57cec5SDimitry Andric     break;
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric DWARFDebugLine::Prologue::Prologue() { clear(); }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric bool DWARFDebugLine::Prologue::hasFileAtIndex(uint64_t FileIndex) const {
690b57cec5SDimitry Andric   uint16_t DwarfVersion = getVersion();
700b57cec5SDimitry Andric   assert(DwarfVersion != 0 &&
710b57cec5SDimitry Andric          "line table prologue has no dwarf version information");
720b57cec5SDimitry Andric   if (DwarfVersion >= 5)
730b57cec5SDimitry Andric     return FileIndex < FileNames.size();
740b57cec5SDimitry Andric   return FileIndex != 0 && FileIndex <= FileNames.size();
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric const llvm::DWARFDebugLine::FileNameEntry &
780b57cec5SDimitry Andric DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const {
790b57cec5SDimitry Andric   uint16_t DwarfVersion = getVersion();
800b57cec5SDimitry Andric   assert(DwarfVersion != 0 &&
810b57cec5SDimitry Andric          "line table prologue has no dwarf version information");
820b57cec5SDimitry Andric   // In DWARF v5 the file names are 0-indexed.
830b57cec5SDimitry Andric   if (DwarfVersion >= 5)
840b57cec5SDimitry Andric     return FileNames[Index];
850b57cec5SDimitry Andric   return FileNames[Index - 1];
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric void DWARFDebugLine::Prologue::clear() {
890b57cec5SDimitry Andric   TotalLength = PrologueLength = 0;
900b57cec5SDimitry Andric   SegSelectorSize = 0;
910b57cec5SDimitry Andric   MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
920b57cec5SDimitry Andric   OpcodeBase = 0;
930b57cec5SDimitry Andric   FormParams = dwarf::FormParams({0, 0, DWARF32});
940b57cec5SDimitry Andric   ContentTypes = ContentTypeTracker();
950b57cec5SDimitry Andric   StandardOpcodeLengths.clear();
960b57cec5SDimitry Andric   IncludeDirectories.clear();
970b57cec5SDimitry Andric   FileNames.clear();
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
1010b57cec5SDimitry Andric                                     DIDumpOptions DumpOptions) const {
1020b57cec5SDimitry Andric   OS << "Line table prologue:\n"
1030b57cec5SDimitry Andric      << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength)
1040b57cec5SDimitry Andric      << format("         version: %u\n", getVersion());
1050b57cec5SDimitry Andric   if (getVersion() >= 5)
1060b57cec5SDimitry Andric     OS << format("    address_size: %u\n", getAddressSize())
1070b57cec5SDimitry Andric        << format(" seg_select_size: %u\n", SegSelectorSize);
1080b57cec5SDimitry Andric   OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
1090b57cec5SDimitry Andric      << format(" min_inst_length: %u\n", MinInstLength)
1100b57cec5SDimitry Andric      << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
1110b57cec5SDimitry Andric      << format(" default_is_stmt: %u\n", DefaultIsStmt)
1120b57cec5SDimitry Andric      << format("       line_base: %i\n", LineBase)
1130b57cec5SDimitry Andric      << format("      line_range: %u\n", LineRange)
1140b57cec5SDimitry Andric      << format("     opcode_base: %u\n", OpcodeBase);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
1170b57cec5SDimitry Andric     OS << format("standard_opcode_lengths[%s] = %u\n",
1180b57cec5SDimitry Andric                  LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   if (!IncludeDirectories.empty()) {
1210b57cec5SDimitry Andric     // DWARF v5 starts directory indexes at 0.
1220b57cec5SDimitry Andric     uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
1230b57cec5SDimitry Andric     for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {
1240b57cec5SDimitry Andric       OS << format("include_directories[%3u] = ", I + DirBase);
1250b57cec5SDimitry Andric       IncludeDirectories[I].dump(OS, DumpOptions);
1260b57cec5SDimitry Andric       OS << '\n';
1270b57cec5SDimitry Andric     }
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   if (!FileNames.empty()) {
1310b57cec5SDimitry Andric     // DWARF v5 starts file indexes at 0.
1320b57cec5SDimitry Andric     uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
1330b57cec5SDimitry Andric     for (uint32_t I = 0; I != FileNames.size(); ++I) {
1340b57cec5SDimitry Andric       const FileNameEntry &FileEntry = FileNames[I];
1350b57cec5SDimitry Andric       OS <<   format("file_names[%3u]:\n", I + FileBase);
1360b57cec5SDimitry Andric       OS <<          "           name: ";
1370b57cec5SDimitry Andric       FileEntry.Name.dump(OS, DumpOptions);
1380b57cec5SDimitry Andric       OS << '\n'
1390b57cec5SDimitry Andric          <<   format("      dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
1400b57cec5SDimitry Andric       if (ContentTypes.HasMD5)
1410b57cec5SDimitry Andric         OS <<        "   md5_checksum: " << FileEntry.Checksum.digest() << '\n';
1420b57cec5SDimitry Andric       if (ContentTypes.HasModTime)
1430b57cec5SDimitry Andric         OS << format("       mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
1440b57cec5SDimitry Andric       if (ContentTypes.HasLength)
1450b57cec5SDimitry Andric         OS << format("         length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
1460b57cec5SDimitry Andric       if (ContentTypes.HasSource) {
1470b57cec5SDimitry Andric         OS <<        "         source: ";
1480b57cec5SDimitry Andric         FileEntry.Source.dump(OS, DumpOptions);
1490b57cec5SDimitry Andric         OS << '\n';
1500b57cec5SDimitry Andric       }
1510b57cec5SDimitry Andric     }
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric // Parse v2-v4 directory and file tables.
1560b57cec5SDimitry Andric static void
1570b57cec5SDimitry Andric parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
158*8bcb0991SDimitry Andric                      uint64_t *OffsetPtr, uint64_t EndPrologueOffset,
1590b57cec5SDimitry Andric                      DWARFDebugLine::ContentTypeTracker &ContentTypes,
1600b57cec5SDimitry Andric                      std::vector<DWARFFormValue> &IncludeDirectories,
1610b57cec5SDimitry Andric                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
1620b57cec5SDimitry Andric   while (*OffsetPtr < EndPrologueOffset) {
1630b57cec5SDimitry Andric     StringRef S = DebugLineData.getCStrRef(OffsetPtr);
1640b57cec5SDimitry Andric     if (S.empty())
1650b57cec5SDimitry Andric       break;
1660b57cec5SDimitry Andric     DWARFFormValue Dir =
1670b57cec5SDimitry Andric         DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, S.data());
1680b57cec5SDimitry Andric     IncludeDirectories.push_back(Dir);
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   while (*OffsetPtr < EndPrologueOffset) {
1720b57cec5SDimitry Andric     StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
1730b57cec5SDimitry Andric     if (Name.empty())
1740b57cec5SDimitry Andric       break;
1750b57cec5SDimitry Andric     DWARFDebugLine::FileNameEntry FileEntry;
1760b57cec5SDimitry Andric     FileEntry.Name =
1770b57cec5SDimitry Andric         DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name.data());
1780b57cec5SDimitry Andric     FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
1790b57cec5SDimitry Andric     FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
1800b57cec5SDimitry Andric     FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
1810b57cec5SDimitry Andric     FileNames.push_back(FileEntry);
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   ContentTypes.HasModTime = true;
1850b57cec5SDimitry Andric   ContentTypes.HasLength = true;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric // Parse v5 directory/file entry content descriptions.
189*8bcb0991SDimitry Andric // Returns the descriptors, or an error if we did not find a path or ran off
190*8bcb0991SDimitry Andric // the end of the prologue.
191*8bcb0991SDimitry Andric static llvm::Expected<ContentDescriptors>
192*8bcb0991SDimitry Andric parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
193*8bcb0991SDimitry Andric                    uint64_t EndPrologueOffset,
194*8bcb0991SDimitry Andric                    DWARFDebugLine::ContentTypeTracker *ContentTypes) {
1950b57cec5SDimitry Andric   ContentDescriptors Descriptors;
1960b57cec5SDimitry Andric   int FormatCount = DebugLineData.getU8(OffsetPtr);
1970b57cec5SDimitry Andric   bool HasPath = false;
1980b57cec5SDimitry Andric   for (int I = 0; I != FormatCount; ++I) {
1990b57cec5SDimitry Andric     if (*OffsetPtr >= EndPrologueOffset)
200*8bcb0991SDimitry Andric       return createStringError(
201*8bcb0991SDimitry Andric           errc::invalid_argument,
202*8bcb0991SDimitry Andric           "failed to parse entry content descriptions at offset "
203*8bcb0991SDimitry Andric           "0x%8.8" PRIx64
204*8bcb0991SDimitry Andric           " because offset extends beyond the prologue end at offset "
205*8bcb0991SDimitry Andric           "0x%8.8" PRIx64,
206*8bcb0991SDimitry Andric           *OffsetPtr, EndPrologueOffset);
2070b57cec5SDimitry Andric     ContentDescriptor Descriptor;
2080b57cec5SDimitry Andric     Descriptor.Type =
2090b57cec5SDimitry Andric       dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
2100b57cec5SDimitry Andric     Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
2110b57cec5SDimitry Andric     if (Descriptor.Type == dwarf::DW_LNCT_path)
2120b57cec5SDimitry Andric       HasPath = true;
2130b57cec5SDimitry Andric     if (ContentTypes)
2140b57cec5SDimitry Andric       ContentTypes->trackContentType(Descriptor.Type);
2150b57cec5SDimitry Andric     Descriptors.push_back(Descriptor);
2160b57cec5SDimitry Andric   }
217*8bcb0991SDimitry Andric 
218*8bcb0991SDimitry Andric   if (!HasPath)
219*8bcb0991SDimitry Andric     return createStringError(errc::invalid_argument,
220*8bcb0991SDimitry Andric                              "failed to parse entry content descriptions"
221*8bcb0991SDimitry Andric                              " because no path was found");
222*8bcb0991SDimitry Andric   return Descriptors;
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
225*8bcb0991SDimitry Andric static Error
2260b57cec5SDimitry Andric parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
227*8bcb0991SDimitry Andric                      uint64_t *OffsetPtr, uint64_t EndPrologueOffset,
2280b57cec5SDimitry Andric                      const dwarf::FormParams &FormParams,
2290b57cec5SDimitry Andric                      const DWARFContext &Ctx, const DWARFUnit *U,
2300b57cec5SDimitry Andric                      DWARFDebugLine::ContentTypeTracker &ContentTypes,
2310b57cec5SDimitry Andric                      std::vector<DWARFFormValue> &IncludeDirectories,
2320b57cec5SDimitry Andric                      std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
2330b57cec5SDimitry Andric   // Get the directory entry description.
234*8bcb0991SDimitry Andric   llvm::Expected<ContentDescriptors> DirDescriptors =
2350b57cec5SDimitry Andric       parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr);
236*8bcb0991SDimitry Andric   if (!DirDescriptors)
237*8bcb0991SDimitry Andric     return DirDescriptors.takeError();
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   // Get the directory entries, according to the format described above.
2400b57cec5SDimitry Andric   int DirEntryCount = DebugLineData.getU8(OffsetPtr);
2410b57cec5SDimitry Andric   for (int I = 0; I != DirEntryCount; ++I) {
2420b57cec5SDimitry Andric     if (*OffsetPtr >= EndPrologueOffset)
243*8bcb0991SDimitry Andric       return createStringError(
244*8bcb0991SDimitry Andric           errc::invalid_argument,
245*8bcb0991SDimitry Andric           "failed to parse directory entry at offset "
246*8bcb0991SDimitry Andric           "0x%8.8" PRIx64
247*8bcb0991SDimitry Andric           " because offset extends beyond the prologue end at offset "
248*8bcb0991SDimitry Andric           "0x%8.8" PRIx64,
249*8bcb0991SDimitry Andric           *OffsetPtr, EndPrologueOffset);
250*8bcb0991SDimitry Andric     for (auto Descriptor : *DirDescriptors) {
2510b57cec5SDimitry Andric       DWARFFormValue Value(Descriptor.Form);
2520b57cec5SDimitry Andric       switch (Descriptor.Type) {
2530b57cec5SDimitry Andric       case DW_LNCT_path:
2540b57cec5SDimitry Andric         if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
255*8bcb0991SDimitry Andric           return createStringError(errc::invalid_argument,
256*8bcb0991SDimitry Andric                                    "failed to parse directory entry because "
257*8bcb0991SDimitry Andric                                    "extracting the form value failed.");
2580b57cec5SDimitry Andric         IncludeDirectories.push_back(Value);
2590b57cec5SDimitry Andric         break;
2600b57cec5SDimitry Andric       default:
2610b57cec5SDimitry Andric         if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
262*8bcb0991SDimitry Andric           return createStringError(errc::invalid_argument,
263*8bcb0991SDimitry Andric                                    "failed to parse directory entry because "
264*8bcb0991SDimitry Andric                                    "skipping the form value failed.");
2650b57cec5SDimitry Andric       }
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   // Get the file entry description.
270*8bcb0991SDimitry Andric   llvm::Expected<ContentDescriptors> FileDescriptors = parseV5EntryFormat(
271*8bcb0991SDimitry Andric       DebugLineData, OffsetPtr, EndPrologueOffset, &ContentTypes);
272*8bcb0991SDimitry Andric   if (!FileDescriptors)
273*8bcb0991SDimitry Andric     return FileDescriptors.takeError();
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   // Get the file entries, according to the format described above.
2760b57cec5SDimitry Andric   int FileEntryCount = DebugLineData.getU8(OffsetPtr);
2770b57cec5SDimitry Andric   for (int I = 0; I != FileEntryCount; ++I) {
2780b57cec5SDimitry Andric     if (*OffsetPtr >= EndPrologueOffset)
279*8bcb0991SDimitry Andric       return createStringError(
280*8bcb0991SDimitry Andric           errc::invalid_argument,
281*8bcb0991SDimitry Andric           "failed to parse file entry at offset "
282*8bcb0991SDimitry Andric           "0x%8.8" PRIx64
283*8bcb0991SDimitry Andric           " because offset extends beyond the prologue end at offset "
284*8bcb0991SDimitry Andric           "0x%8.8" PRIx64,
285*8bcb0991SDimitry Andric           *OffsetPtr, EndPrologueOffset);
2860b57cec5SDimitry Andric     DWARFDebugLine::FileNameEntry FileEntry;
287*8bcb0991SDimitry Andric     for (auto Descriptor : *FileDescriptors) {
2880b57cec5SDimitry Andric       DWARFFormValue Value(Descriptor.Form);
2890b57cec5SDimitry Andric       if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
290*8bcb0991SDimitry Andric         return createStringError(errc::invalid_argument,
291*8bcb0991SDimitry Andric                                  "failed to parse file entry because "
292*8bcb0991SDimitry Andric                                  "extracting the form value failed.");
2930b57cec5SDimitry Andric       switch (Descriptor.Type) {
2940b57cec5SDimitry Andric       case DW_LNCT_path:
2950b57cec5SDimitry Andric         FileEntry.Name = Value;
2960b57cec5SDimitry Andric         break;
2970b57cec5SDimitry Andric       case DW_LNCT_LLVM_source:
2980b57cec5SDimitry Andric         FileEntry.Source = Value;
2990b57cec5SDimitry Andric         break;
3000b57cec5SDimitry Andric       case DW_LNCT_directory_index:
3010b57cec5SDimitry Andric         FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
3020b57cec5SDimitry Andric         break;
3030b57cec5SDimitry Andric       case DW_LNCT_timestamp:
3040b57cec5SDimitry Andric         FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
3050b57cec5SDimitry Andric         break;
3060b57cec5SDimitry Andric       case DW_LNCT_size:
3070b57cec5SDimitry Andric         FileEntry.Length = Value.getAsUnsignedConstant().getValue();
3080b57cec5SDimitry Andric         break;
3090b57cec5SDimitry Andric       case DW_LNCT_MD5:
310*8bcb0991SDimitry Andric         if (!Value.getAsBlock() || Value.getAsBlock().getValue().size() != 16)
311*8bcb0991SDimitry Andric           return createStringError(
312*8bcb0991SDimitry Andric               errc::invalid_argument,
313*8bcb0991SDimitry Andric               "failed to parse file entry because the MD5 hash is invalid");
3140b57cec5SDimitry Andric         std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16,
3150b57cec5SDimitry Andric                                   FileEntry.Checksum.Bytes.begin());
3160b57cec5SDimitry Andric         break;
3170b57cec5SDimitry Andric       default:
3180b57cec5SDimitry Andric         break;
3190b57cec5SDimitry Andric       }
3200b57cec5SDimitry Andric     }
3210b57cec5SDimitry Andric     FileNames.push_back(FileEntry);
3220b57cec5SDimitry Andric   }
323*8bcb0991SDimitry Andric   return Error::success();
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
327*8bcb0991SDimitry Andric                                       uint64_t *OffsetPtr,
3280b57cec5SDimitry Andric                                       const DWARFContext &Ctx,
3290b57cec5SDimitry Andric                                       const DWARFUnit *U) {
3300b57cec5SDimitry Andric   const uint64_t PrologueOffset = *OffsetPtr;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   clear();
3330b57cec5SDimitry Andric   TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr);
334*8bcb0991SDimitry Andric   if (TotalLength == dwarf::DW_LENGTH_DWARF64) {
3350b57cec5SDimitry Andric     FormParams.Format = dwarf::DWARF64;
3360b57cec5SDimitry Andric     TotalLength = DebugLineData.getU64(OffsetPtr);
337*8bcb0991SDimitry Andric   } else if (TotalLength >= dwarf::DW_LENGTH_lo_reserved) {
3380b57cec5SDimitry Andric     return createStringError(errc::invalid_argument,
3390b57cec5SDimitry Andric         "parsing line table prologue at offset 0x%8.8" PRIx64
3400b57cec5SDimitry Andric         " unsupported reserved unit length found of value 0x%8.8" PRIx64,
3410b57cec5SDimitry Andric         PrologueOffset, TotalLength);
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric   FormParams.Version = DebugLineData.getU16(OffsetPtr);
3440b57cec5SDimitry Andric   if (getVersion() < 2)
3450b57cec5SDimitry Andric     return createStringError(errc::not_supported,
3460b57cec5SDimitry Andric                        "parsing line table prologue at offset 0x%8.8" PRIx64
3470b57cec5SDimitry Andric                        " found unsupported version 0x%2.2" PRIx16,
3480b57cec5SDimitry Andric                        PrologueOffset, getVersion());
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   if (getVersion() >= 5) {
3510b57cec5SDimitry Andric     FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
3520b57cec5SDimitry Andric     assert((DebugLineData.getAddressSize() == 0 ||
3530b57cec5SDimitry Andric             DebugLineData.getAddressSize() == getAddressSize()) &&
3540b57cec5SDimitry Andric            "Line table header and data extractor disagree");
3550b57cec5SDimitry Andric     SegSelectorSize = DebugLineData.getU8(OffsetPtr);
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   PrologueLength =
3590b57cec5SDimitry Andric       DebugLineData.getRelocatedValue(sizeofPrologueLength(), OffsetPtr);
3600b57cec5SDimitry Andric   const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
3610b57cec5SDimitry Andric   MinInstLength = DebugLineData.getU8(OffsetPtr);
3620b57cec5SDimitry Andric   if (getVersion() >= 4)
3630b57cec5SDimitry Andric     MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
3640b57cec5SDimitry Andric   DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
3650b57cec5SDimitry Andric   LineBase = DebugLineData.getU8(OffsetPtr);
3660b57cec5SDimitry Andric   LineRange = DebugLineData.getU8(OffsetPtr);
3670b57cec5SDimitry Andric   OpcodeBase = DebugLineData.getU8(OffsetPtr);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   StandardOpcodeLengths.reserve(OpcodeBase - 1);
3700b57cec5SDimitry Andric   for (uint32_t I = 1; I < OpcodeBase; ++I) {
3710b57cec5SDimitry Andric     uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
3720b57cec5SDimitry Andric     StandardOpcodeLengths.push_back(OpLen);
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   if (getVersion() >= 5) {
376*8bcb0991SDimitry Andric     if (Error e = parseV5DirFileTables(
377*8bcb0991SDimitry Andric             DebugLineData, OffsetPtr, EndPrologueOffset, FormParams, Ctx, U,
378*8bcb0991SDimitry Andric             ContentTypes, IncludeDirectories, FileNames)) {
379*8bcb0991SDimitry Andric       return joinErrors(
380*8bcb0991SDimitry Andric           createStringError(
381*8bcb0991SDimitry Andric               errc::invalid_argument,
3820b57cec5SDimitry Andric               "parsing line table prologue at 0x%8.8" PRIx64
3830b57cec5SDimitry Andric               " found an invalid directory or file table description at"
3840b57cec5SDimitry Andric               " 0x%8.8" PRIx64,
385*8bcb0991SDimitry Andric               PrologueOffset, *OffsetPtr),
386*8bcb0991SDimitry Andric           std::move(e));
3870b57cec5SDimitry Andric     }
3880b57cec5SDimitry Andric   } else
3890b57cec5SDimitry Andric     parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
3900b57cec5SDimitry Andric                          ContentTypes, IncludeDirectories, FileNames);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   if (*OffsetPtr != EndPrologueOffset)
3930b57cec5SDimitry Andric     return createStringError(errc::invalid_argument,
3940b57cec5SDimitry Andric                        "parsing line table prologue at 0x%8.8" PRIx64
3950b57cec5SDimitry Andric                        " should have ended at 0x%8.8" PRIx64
3960b57cec5SDimitry Andric                        " but it ended at 0x%8.8" PRIx64,
397*8bcb0991SDimitry Andric                        PrologueOffset, EndPrologueOffset, *OffsetPtr);
3980b57cec5SDimitry Andric   return Error::success();
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric void DWARFDebugLine::Row::postAppend() {
4040b57cec5SDimitry Andric   Discriminator = 0;
4050b57cec5SDimitry Andric   BasicBlock = false;
4060b57cec5SDimitry Andric   PrologueEnd = false;
4070b57cec5SDimitry Andric   EpilogueBegin = false;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
4110b57cec5SDimitry Andric   Address.Address = 0;
4120b57cec5SDimitry Andric   Address.SectionIndex = object::SectionedAddress::UndefSection;
4130b57cec5SDimitry Andric   Line = 1;
4140b57cec5SDimitry Andric   Column = 0;
4150b57cec5SDimitry Andric   File = 1;
4160b57cec5SDimitry Andric   Isa = 0;
4170b57cec5SDimitry Andric   Discriminator = 0;
4180b57cec5SDimitry Andric   IsStmt = DefaultIsStmt;
4190b57cec5SDimitry Andric   BasicBlock = false;
4200b57cec5SDimitry Andric   EndSequence = false;
4210b57cec5SDimitry Andric   PrologueEnd = false;
4220b57cec5SDimitry Andric   EpilogueBegin = false;
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
4260b57cec5SDimitry Andric   OS << "Address            Line   Column File   ISA Discriminator Flags\n"
4270b57cec5SDimitry Andric      << "------------------ ------ ------ ------ --- ------------- "
4280b57cec5SDimitry Andric         "-------------\n";
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
4320b57cec5SDimitry Andric   OS << format("0x%16.16" PRIx64 " %6u %6u", Address.Address, Line, Column)
4330b57cec5SDimitry Andric      << format(" %6u %3u %13u ", File, Isa, Discriminator)
4340b57cec5SDimitry Andric      << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
4350b57cec5SDimitry Andric      << (PrologueEnd ? " prologue_end" : "")
4360b57cec5SDimitry Andric      << (EpilogueBegin ? " epilogue_begin" : "")
4370b57cec5SDimitry Andric      << (EndSequence ? " end_sequence" : "") << '\n';
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric DWARFDebugLine::Sequence::Sequence() { reset(); }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric void DWARFDebugLine::Sequence::reset() {
4430b57cec5SDimitry Andric   LowPC = 0;
4440b57cec5SDimitry Andric   HighPC = 0;
4450b57cec5SDimitry Andric   SectionIndex = object::SectionedAddress::UndefSection;
4460b57cec5SDimitry Andric   FirstRowIndex = 0;
4470b57cec5SDimitry Andric   LastRowIndex = 0;
4480b57cec5SDimitry Andric   Empty = true;
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric DWARFDebugLine::LineTable::LineTable() { clear(); }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric void DWARFDebugLine::LineTable::dump(raw_ostream &OS,
4540b57cec5SDimitry Andric                                      DIDumpOptions DumpOptions) const {
4550b57cec5SDimitry Andric   Prologue.dump(OS, DumpOptions);
4560b57cec5SDimitry Andric   OS << '\n';
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   if (!Rows.empty()) {
4590b57cec5SDimitry Andric     Row::dumpTableHeader(OS);
4600b57cec5SDimitry Andric     for (const Row &R : Rows) {
4610b57cec5SDimitry Andric       R.dump(OS);
4620b57cec5SDimitry Andric     }
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric void DWARFDebugLine::LineTable::clear() {
4670b57cec5SDimitry Andric   Prologue.clear();
4680b57cec5SDimitry Andric   Rows.clear();
4690b57cec5SDimitry Andric   Sequences.clear();
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
4730b57cec5SDimitry Andric     : LineTable(LT) {
4740b57cec5SDimitry Andric   resetRowAndSequence();
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric void DWARFDebugLine::ParsingState::resetRowAndSequence() {
4780b57cec5SDimitry Andric   Row.reset(LineTable->Prologue.DefaultIsStmt);
4790b57cec5SDimitry Andric   Sequence.reset();
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric void DWARFDebugLine::ParsingState::appendRowToMatrix() {
4830b57cec5SDimitry Andric   unsigned RowNumber = LineTable->Rows.size();
4840b57cec5SDimitry Andric   if (Sequence.Empty) {
4850b57cec5SDimitry Andric     // Record the beginning of instruction sequence.
4860b57cec5SDimitry Andric     Sequence.Empty = false;
4870b57cec5SDimitry Andric     Sequence.LowPC = Row.Address.Address;
4880b57cec5SDimitry Andric     Sequence.FirstRowIndex = RowNumber;
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric   LineTable->appendRow(Row);
4910b57cec5SDimitry Andric   if (Row.EndSequence) {
4920b57cec5SDimitry Andric     // Record the end of instruction sequence.
4930b57cec5SDimitry Andric     Sequence.HighPC = Row.Address.Address;
4940b57cec5SDimitry Andric     Sequence.LastRowIndex = RowNumber + 1;
4950b57cec5SDimitry Andric     Sequence.SectionIndex = Row.Address.SectionIndex;
4960b57cec5SDimitry Andric     if (Sequence.isValid())
4970b57cec5SDimitry Andric       LineTable->appendSequence(Sequence);
4980b57cec5SDimitry Andric     Sequence.reset();
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric   Row.postAppend();
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric const DWARFDebugLine::LineTable *
504*8bcb0991SDimitry Andric DWARFDebugLine::getLineTable(uint64_t Offset) const {
5050b57cec5SDimitry Andric   LineTableConstIter Pos = LineTableMap.find(Offset);
5060b57cec5SDimitry Andric   if (Pos != LineTableMap.end())
5070b57cec5SDimitry Andric     return &Pos->second;
5080b57cec5SDimitry Andric   return nullptr;
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(
512*8bcb0991SDimitry Andric     DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx,
5130b57cec5SDimitry Andric     const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) {
5140b57cec5SDimitry Andric   if (!DebugLineData.isValidOffset(Offset))
515*8bcb0991SDimitry Andric     return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx64
5160b57cec5SDimitry Andric                        " is not a valid debug line section offset",
5170b57cec5SDimitry Andric                        Offset);
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   std::pair<LineTableIter, bool> Pos =
5200b57cec5SDimitry Andric       LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
5210b57cec5SDimitry Andric   LineTable *LT = &Pos.first->second;
5220b57cec5SDimitry Andric   if (Pos.second) {
5230b57cec5SDimitry Andric     if (Error Err =
5240b57cec5SDimitry Andric             LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback))
5250b57cec5SDimitry Andric       return std::move(Err);
5260b57cec5SDimitry Andric     return LT;
5270b57cec5SDimitry Andric   }
5280b57cec5SDimitry Andric   return LT;
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric Error DWARFDebugLine::LineTable::parse(
532*8bcb0991SDimitry Andric     DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
5330b57cec5SDimitry Andric     const DWARFContext &Ctx, const DWARFUnit *U,
5340b57cec5SDimitry Andric     std::function<void(Error)> RecoverableErrorCallback, raw_ostream *OS) {
535*8bcb0991SDimitry Andric   const uint64_t DebugLineOffset = *OffsetPtr;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   clear();
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr, Ctx, U);
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   if (OS) {
5420b57cec5SDimitry Andric     // The presence of OS signals verbose dumping.
5430b57cec5SDimitry Andric     DIDumpOptions DumpOptions;
5440b57cec5SDimitry Andric     DumpOptions.Verbose = true;
5450b57cec5SDimitry Andric     Prologue.dump(*OS, DumpOptions);
5460b57cec5SDimitry Andric   }
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   if (PrologueErr)
5490b57cec5SDimitry Andric     return PrologueErr;
5500b57cec5SDimitry Andric 
551*8bcb0991SDimitry Andric   const uint64_t EndOffset =
5520b57cec5SDimitry Andric       DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   // See if we should tell the data extractor the address size.
5550b57cec5SDimitry Andric   if (DebugLineData.getAddressSize() == 0)
5560b57cec5SDimitry Andric     DebugLineData.setAddressSize(Prologue.getAddressSize());
5570b57cec5SDimitry Andric   else
5580b57cec5SDimitry Andric     assert(Prologue.getAddressSize() == 0 ||
5590b57cec5SDimitry Andric            Prologue.getAddressSize() == DebugLineData.getAddressSize());
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   ParsingState State(this);
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   while (*OffsetPtr < EndOffset) {
5640b57cec5SDimitry Andric     if (OS)
565*8bcb0991SDimitry Andric       *OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric     uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric     if (OS)
5700b57cec5SDimitry Andric       *OS << format("%02.02" PRIx8 " ", Opcode);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric     if (Opcode == 0) {
5730b57cec5SDimitry Andric       // Extended Opcodes always start with a zero opcode followed by
5740b57cec5SDimitry Andric       // a uleb128 length so you can skip ones you don't know about
5750b57cec5SDimitry Andric       uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
576*8bcb0991SDimitry Andric       uint64_t ExtOffset = *OffsetPtr;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric       // Tolerate zero-length; assume length is correct and soldier on.
5790b57cec5SDimitry Andric       if (Len == 0) {
5800b57cec5SDimitry Andric         if (OS)
5810b57cec5SDimitry Andric           *OS << "Badly formed extended line op (length 0)\n";
5820b57cec5SDimitry Andric         continue;
5830b57cec5SDimitry Andric       }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric       uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
5860b57cec5SDimitry Andric       if (OS)
5870b57cec5SDimitry Andric         *OS << LNExtendedString(SubOpcode);
5880b57cec5SDimitry Andric       switch (SubOpcode) {
5890b57cec5SDimitry Andric       case DW_LNE_end_sequence:
5900b57cec5SDimitry Andric         // Set the end_sequence register of the state machine to true and
5910b57cec5SDimitry Andric         // append a row to the matrix using the current values of the
5920b57cec5SDimitry Andric         // state-machine registers. Then reset the registers to the initial
5930b57cec5SDimitry Andric         // values specified above. Every statement program sequence must end
5940b57cec5SDimitry Andric         // with a DW_LNE_end_sequence instruction which creates a row whose
5950b57cec5SDimitry Andric         // address is that of the byte after the last target machine instruction
5960b57cec5SDimitry Andric         // of the sequence.
5970b57cec5SDimitry Andric         State.Row.EndSequence = true;
5980b57cec5SDimitry Andric         State.appendRowToMatrix();
5990b57cec5SDimitry Andric         if (OS) {
6000b57cec5SDimitry Andric           *OS << "\n";
6010b57cec5SDimitry Andric           OS->indent(12);
6020b57cec5SDimitry Andric           State.Row.dump(*OS);
6030b57cec5SDimitry Andric         }
6040b57cec5SDimitry Andric         State.resetRowAndSequence();
6050b57cec5SDimitry Andric         break;
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric       case DW_LNE_set_address:
6080b57cec5SDimitry Andric         // Takes a single relocatable address as an operand. The size of the
6090b57cec5SDimitry Andric         // operand is the size appropriate to hold an address on the target
6100b57cec5SDimitry Andric         // machine. Set the address register to the value given by the
6110b57cec5SDimitry Andric         // relocatable address. All of the other statement program opcodes
6120b57cec5SDimitry Andric         // that affect the address register add a delta to it. This instruction
6130b57cec5SDimitry Andric         // stores a relocatable value into it instead.
6140b57cec5SDimitry Andric         //
6150b57cec5SDimitry Andric         // Make sure the extractor knows the address size.  If not, infer it
6160b57cec5SDimitry Andric         // from the size of the operand.
6170b57cec5SDimitry Andric         if (DebugLineData.getAddressSize() == 0)
6180b57cec5SDimitry Andric           DebugLineData.setAddressSize(Len - 1);
6190b57cec5SDimitry Andric         else if (DebugLineData.getAddressSize() != Len - 1) {
6200b57cec5SDimitry Andric           return createStringError(errc::invalid_argument,
621*8bcb0991SDimitry Andric                              "mismatching address size at offset 0x%8.8" PRIx64
6220b57cec5SDimitry Andric                              " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,
6230b57cec5SDimitry Andric                              ExtOffset, DebugLineData.getAddressSize(),
6240b57cec5SDimitry Andric                              Len - 1);
6250b57cec5SDimitry Andric         }
6260b57cec5SDimitry Andric         State.Row.Address.Address = DebugLineData.getRelocatedAddress(
6270b57cec5SDimitry Andric             OffsetPtr, &State.Row.Address.SectionIndex);
6280b57cec5SDimitry Andric         if (OS)
6290b57cec5SDimitry Andric           *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address);
6300b57cec5SDimitry Andric         break;
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric       case DW_LNE_define_file:
6330b57cec5SDimitry Andric         // Takes 4 arguments. The first is a null terminated string containing
6340b57cec5SDimitry Andric         // a source file name. The second is an unsigned LEB128 number
6350b57cec5SDimitry Andric         // representing the directory index of the directory in which the file
6360b57cec5SDimitry Andric         // was found. The third is an unsigned LEB128 number representing the
6370b57cec5SDimitry Andric         // time of last modification of the file. The fourth is an unsigned
6380b57cec5SDimitry Andric         // LEB128 number representing the length in bytes of the file. The time
6390b57cec5SDimitry Andric         // and length fields may contain LEB128(0) if the information is not
6400b57cec5SDimitry Andric         // available.
6410b57cec5SDimitry Andric         //
6420b57cec5SDimitry Andric         // The directory index represents an entry in the include_directories
6430b57cec5SDimitry Andric         // section of the statement program prologue. The index is LEB128(0)
6440b57cec5SDimitry Andric         // if the file was found in the current directory of the compilation,
6450b57cec5SDimitry Andric         // LEB128(1) if it was found in the first directory in the
6460b57cec5SDimitry Andric         // include_directories section, and so on. The directory index is
6470b57cec5SDimitry Andric         // ignored for file names that represent full path names.
6480b57cec5SDimitry Andric         //
6490b57cec5SDimitry Andric         // The files are numbered, starting at 1, in the order in which they
6500b57cec5SDimitry Andric         // appear; the names in the prologue come before names defined by
6510b57cec5SDimitry Andric         // the DW_LNE_define_file instruction. These numbers are used in the
6520b57cec5SDimitry Andric         // the file register of the state machine.
6530b57cec5SDimitry Andric         {
6540b57cec5SDimitry Andric           FileNameEntry FileEntry;
6550b57cec5SDimitry Andric           const char *Name = DebugLineData.getCStr(OffsetPtr);
6560b57cec5SDimitry Andric           FileEntry.Name =
6570b57cec5SDimitry Andric               DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name);
6580b57cec5SDimitry Andric           FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
6590b57cec5SDimitry Andric           FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
6600b57cec5SDimitry Andric           FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
6610b57cec5SDimitry Andric           Prologue.FileNames.push_back(FileEntry);
6620b57cec5SDimitry Andric           if (OS)
6630b57cec5SDimitry Andric             *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
6640b57cec5SDimitry Andric                 << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)
6650b57cec5SDimitry Andric                 << ", length=" << FileEntry.Length << ")";
6660b57cec5SDimitry Andric         }
6670b57cec5SDimitry Andric         break;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric       case DW_LNE_set_discriminator:
6700b57cec5SDimitry Andric         State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
6710b57cec5SDimitry Andric         if (OS)
6720b57cec5SDimitry Andric           *OS << " (" << State.Row.Discriminator << ")";
6730b57cec5SDimitry Andric         break;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric       default:
6760b57cec5SDimitry Andric         if (OS)
6770b57cec5SDimitry Andric           *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
6780b57cec5SDimitry Andric               << format(" length %" PRIx64, Len);
6790b57cec5SDimitry Andric         // Len doesn't include the zero opcode byte or the length itself, but
6800b57cec5SDimitry Andric         // it does include the sub_opcode, so we have to adjust for that.
6810b57cec5SDimitry Andric         (*OffsetPtr) += Len - 1;
6820b57cec5SDimitry Andric         break;
6830b57cec5SDimitry Andric       }
6840b57cec5SDimitry Andric       // Make sure the stated and parsed lengths are the same.
6850b57cec5SDimitry Andric       // Otherwise we have an unparseable line-number program.
6860b57cec5SDimitry Andric       if (*OffsetPtr - ExtOffset != Len)
6870b57cec5SDimitry Andric         return createStringError(errc::illegal_byte_sequence,
688*8bcb0991SDimitry Andric                            "unexpected line op length at offset 0x%8.8" PRIx64
689*8bcb0991SDimitry Andric                            " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64,
6900b57cec5SDimitry Andric                            ExtOffset, Len, *OffsetPtr - ExtOffset);
6910b57cec5SDimitry Andric     } else if (Opcode < Prologue.OpcodeBase) {
6920b57cec5SDimitry Andric       if (OS)
6930b57cec5SDimitry Andric         *OS << LNStandardString(Opcode);
6940b57cec5SDimitry Andric       switch (Opcode) {
6950b57cec5SDimitry Andric       // Standard Opcodes
6960b57cec5SDimitry Andric       case DW_LNS_copy:
6970b57cec5SDimitry Andric         // Takes no arguments. Append a row to the matrix using the
6980b57cec5SDimitry Andric         // current values of the state-machine registers.
6990b57cec5SDimitry Andric         if (OS) {
7000b57cec5SDimitry Andric           *OS << "\n";
7010b57cec5SDimitry Andric           OS->indent(12);
7020b57cec5SDimitry Andric           State.Row.dump(*OS);
7030b57cec5SDimitry Andric           *OS << "\n";
7040b57cec5SDimitry Andric         }
7050b57cec5SDimitry Andric         State.appendRowToMatrix();
7060b57cec5SDimitry Andric         break;
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric       case DW_LNS_advance_pc:
7090b57cec5SDimitry Andric         // Takes a single unsigned LEB128 operand, multiplies it by the
7100b57cec5SDimitry Andric         // min_inst_length field of the prologue, and adds the
7110b57cec5SDimitry Andric         // result to the address register of the state machine.
7120b57cec5SDimitry Andric         {
7130b57cec5SDimitry Andric           uint64_t AddrOffset =
7140b57cec5SDimitry Andric               DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
7150b57cec5SDimitry Andric           State.Row.Address.Address += AddrOffset;
7160b57cec5SDimitry Andric           if (OS)
7170b57cec5SDimitry Andric             *OS << " (" << AddrOffset << ")";
7180b57cec5SDimitry Andric         }
7190b57cec5SDimitry Andric         break;
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric       case DW_LNS_advance_line:
7220b57cec5SDimitry Andric         // Takes a single signed LEB128 operand and adds that value to
7230b57cec5SDimitry Andric         // the line register of the state machine.
7240b57cec5SDimitry Andric         State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
7250b57cec5SDimitry Andric         if (OS)
7260b57cec5SDimitry Andric           *OS << " (" << State.Row.Line << ")";
7270b57cec5SDimitry Andric         break;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric       case DW_LNS_set_file:
7300b57cec5SDimitry Andric         // Takes a single unsigned LEB128 operand and stores it in the file
7310b57cec5SDimitry Andric         // register of the state machine.
7320b57cec5SDimitry Andric         State.Row.File = DebugLineData.getULEB128(OffsetPtr);
7330b57cec5SDimitry Andric         if (OS)
7340b57cec5SDimitry Andric           *OS << " (" << State.Row.File << ")";
7350b57cec5SDimitry Andric         break;
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric       case DW_LNS_set_column:
7380b57cec5SDimitry Andric         // Takes a single unsigned LEB128 operand and stores it in the
7390b57cec5SDimitry Andric         // column register of the state machine.
7400b57cec5SDimitry Andric         State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
7410b57cec5SDimitry Andric         if (OS)
7420b57cec5SDimitry Andric           *OS << " (" << State.Row.Column << ")";
7430b57cec5SDimitry Andric         break;
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric       case DW_LNS_negate_stmt:
7460b57cec5SDimitry Andric         // Takes no arguments. Set the is_stmt register of the state
7470b57cec5SDimitry Andric         // machine to the logical negation of its current value.
7480b57cec5SDimitry Andric         State.Row.IsStmt = !State.Row.IsStmt;
7490b57cec5SDimitry Andric         break;
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric       case DW_LNS_set_basic_block:
7520b57cec5SDimitry Andric         // Takes no arguments. Set the basic_block register of the
7530b57cec5SDimitry Andric         // state machine to true
7540b57cec5SDimitry Andric         State.Row.BasicBlock = true;
7550b57cec5SDimitry Andric         break;
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric       case DW_LNS_const_add_pc:
7580b57cec5SDimitry Andric         // Takes no arguments. Add to the address register of the state
7590b57cec5SDimitry Andric         // machine the address increment value corresponding to special
7600b57cec5SDimitry Andric         // opcode 255. The motivation for DW_LNS_const_add_pc is this:
7610b57cec5SDimitry Andric         // when the statement program needs to advance the address by a
7620b57cec5SDimitry Andric         // small amount, it can use a single special opcode, which occupies
7630b57cec5SDimitry Andric         // a single byte. When it needs to advance the address by up to
7640b57cec5SDimitry Andric         // twice the range of the last special opcode, it can use
7650b57cec5SDimitry Andric         // DW_LNS_const_add_pc followed by a special opcode, for a total
7660b57cec5SDimitry Andric         // of two bytes. Only if it needs to advance the address by more
7670b57cec5SDimitry Andric         // than twice that range will it need to use both DW_LNS_advance_pc
7680b57cec5SDimitry Andric         // and a special opcode, requiring three or more bytes.
7690b57cec5SDimitry Andric         {
7700b57cec5SDimitry Andric           uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
7710b57cec5SDimitry Andric           uint64_t AddrOffset =
7720b57cec5SDimitry Andric               (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
7730b57cec5SDimitry Andric           State.Row.Address.Address += AddrOffset;
7740b57cec5SDimitry Andric           if (OS)
7750b57cec5SDimitry Andric             *OS
7760b57cec5SDimitry Andric                 << format(" (0x%16.16" PRIx64 ")", AddrOffset);
7770b57cec5SDimitry Andric         }
7780b57cec5SDimitry Andric         break;
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric       case DW_LNS_fixed_advance_pc:
7810b57cec5SDimitry Andric         // Takes a single uhalf operand. Add to the address register of
7820b57cec5SDimitry Andric         // the state machine the value of the (unencoded) operand. This
7830b57cec5SDimitry Andric         // is the only extended opcode that takes an argument that is not
7840b57cec5SDimitry Andric         // a variable length number. The motivation for DW_LNS_fixed_advance_pc
7850b57cec5SDimitry Andric         // is this: existing assemblers cannot emit DW_LNS_advance_pc or
7860b57cec5SDimitry Andric         // special opcodes because they cannot encode LEB128 numbers or
7870b57cec5SDimitry Andric         // judge when the computation of a special opcode overflows and
7880b57cec5SDimitry Andric         // requires the use of DW_LNS_advance_pc. Such assemblers, however,
7890b57cec5SDimitry Andric         // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
7900b57cec5SDimitry Andric         {
7910b57cec5SDimitry Andric           uint16_t PCOffset = DebugLineData.getRelocatedValue(2, OffsetPtr);
7920b57cec5SDimitry Andric           State.Row.Address.Address += PCOffset;
7930b57cec5SDimitry Andric           if (OS)
7940b57cec5SDimitry Andric             *OS
7950b57cec5SDimitry Andric                 << format(" (0x%4.4" PRIx16 ")", PCOffset);
7960b57cec5SDimitry Andric         }
7970b57cec5SDimitry Andric         break;
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric       case DW_LNS_set_prologue_end:
8000b57cec5SDimitry Andric         // Takes no arguments. Set the prologue_end register of the
8010b57cec5SDimitry Andric         // state machine to true
8020b57cec5SDimitry Andric         State.Row.PrologueEnd = true;
8030b57cec5SDimitry Andric         break;
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric       case DW_LNS_set_epilogue_begin:
8060b57cec5SDimitry Andric         // Takes no arguments. Set the basic_block register of the
8070b57cec5SDimitry Andric         // state machine to true
8080b57cec5SDimitry Andric         State.Row.EpilogueBegin = true;
8090b57cec5SDimitry Andric         break;
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric       case DW_LNS_set_isa:
8120b57cec5SDimitry Andric         // Takes a single unsigned LEB128 operand and stores it in the
8130b57cec5SDimitry Andric         // column register of the state machine.
8140b57cec5SDimitry Andric         State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
8150b57cec5SDimitry Andric         if (OS)
8160b57cec5SDimitry Andric           *OS << " (" << State.Row.Isa << ")";
8170b57cec5SDimitry Andric         break;
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric       default:
8200b57cec5SDimitry Andric         // Handle any unknown standard opcodes here. We know the lengths
8210b57cec5SDimitry Andric         // of such opcodes because they are specified in the prologue
8220b57cec5SDimitry Andric         // as a multiple of LEB128 operands for each opcode.
8230b57cec5SDimitry Andric         {
8240b57cec5SDimitry Andric           assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
8250b57cec5SDimitry Andric           uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
8260b57cec5SDimitry Andric           for (uint8_t I = 0; I < OpcodeLength; ++I) {
8270b57cec5SDimitry Andric             uint64_t Value = DebugLineData.getULEB128(OffsetPtr);
8280b57cec5SDimitry Andric             if (OS)
8290b57cec5SDimitry Andric               *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
8300b57cec5SDimitry Andric                             Value);
8310b57cec5SDimitry Andric           }
8320b57cec5SDimitry Andric         }
8330b57cec5SDimitry Andric         break;
8340b57cec5SDimitry Andric       }
8350b57cec5SDimitry Andric     } else {
8360b57cec5SDimitry Andric       // Special Opcodes
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric       // A special opcode value is chosen based on the amount that needs
8390b57cec5SDimitry Andric       // to be added to the line and address registers. The maximum line
8400b57cec5SDimitry Andric       // increment for a special opcode is the value of the line_base
8410b57cec5SDimitry Andric       // field in the header, plus the value of the line_range field,
8420b57cec5SDimitry Andric       // minus 1 (line base + line range - 1). If the desired line
8430b57cec5SDimitry Andric       // increment is greater than the maximum line increment, a standard
8440b57cec5SDimitry Andric       // opcode must be used instead of a special opcode. The "address
8450b57cec5SDimitry Andric       // advance" is calculated by dividing the desired address increment
8460b57cec5SDimitry Andric       // by the minimum_instruction_length field from the header. The
8470b57cec5SDimitry Andric       // special opcode is then calculated using the following formula:
8480b57cec5SDimitry Andric       //
8490b57cec5SDimitry Andric       //  opcode = (desired line increment - line_base) +
8500b57cec5SDimitry Andric       //           (line_range * address advance) + opcode_base
8510b57cec5SDimitry Andric       //
8520b57cec5SDimitry Andric       // If the resulting opcode is greater than 255, a standard opcode
8530b57cec5SDimitry Andric       // must be used instead.
8540b57cec5SDimitry Andric       //
8550b57cec5SDimitry Andric       // To decode a special opcode, subtract the opcode_base from the
8560b57cec5SDimitry Andric       // opcode itself to give the adjusted opcode. The amount to
8570b57cec5SDimitry Andric       // increment the address register is the result of the adjusted
8580b57cec5SDimitry Andric       // opcode divided by the line_range multiplied by the
8590b57cec5SDimitry Andric       // minimum_instruction_length field from the header. That is:
8600b57cec5SDimitry Andric       //
8610b57cec5SDimitry Andric       //  address increment = (adjusted opcode / line_range) *
8620b57cec5SDimitry Andric       //                      minimum_instruction_length
8630b57cec5SDimitry Andric       //
8640b57cec5SDimitry Andric       // The amount to increment the line register is the line_base plus
8650b57cec5SDimitry Andric       // the result of the adjusted opcode modulo the line_range. That is:
8660b57cec5SDimitry Andric       //
8670b57cec5SDimitry Andric       // line increment = line_base + (adjusted opcode % line_range)
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric       uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
8700b57cec5SDimitry Andric       uint64_t AddrOffset =
8710b57cec5SDimitry Andric           (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
8720b57cec5SDimitry Andric       int32_t LineOffset =
8730b57cec5SDimitry Andric           Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
8740b57cec5SDimitry Andric       State.Row.Line += LineOffset;
8750b57cec5SDimitry Andric       State.Row.Address.Address += AddrOffset;
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric       if (OS) {
8780b57cec5SDimitry Andric         *OS << "address += " << AddrOffset << ",  line += " << LineOffset
8790b57cec5SDimitry Andric             << "\n";
8800b57cec5SDimitry Andric         OS->indent(12);
8810b57cec5SDimitry Andric         State.Row.dump(*OS);
8820b57cec5SDimitry Andric       }
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric       State.appendRowToMatrix();
8850b57cec5SDimitry Andric     }
8860b57cec5SDimitry Andric     if(OS)
8870b57cec5SDimitry Andric       *OS << "\n";
8880b57cec5SDimitry Andric   }
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   if (!State.Sequence.Empty)
8910b57cec5SDimitry Andric     RecoverableErrorCallback(
8920b57cec5SDimitry Andric         createStringError(errc::illegal_byte_sequence,
8930b57cec5SDimitry Andric                     "last sequence in debug line table is not terminated!"));
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   // Sort all sequences so that address lookup will work faster.
8960b57cec5SDimitry Andric   if (!Sequences.empty()) {
8970b57cec5SDimitry Andric     llvm::sort(Sequences, Sequence::orderByHighPC);
8980b57cec5SDimitry Andric     // Note: actually, instruction address ranges of sequences should not
8990b57cec5SDimitry Andric     // overlap (in shared objects and executables). If they do, the address
9000b57cec5SDimitry Andric     // lookup would still work, though, but result would be ambiguous.
9010b57cec5SDimitry Andric     // We don't report warning in this case. For example,
9020b57cec5SDimitry Andric     // sometimes .so compiled from multiple object files contains a few
9030b57cec5SDimitry Andric     // rudimentary sequences for address ranges [0x0, 0xsomething).
9040b57cec5SDimitry Andric   }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   return Error::success();
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric uint32_t DWARFDebugLine::LineTable::findRowInSeq(
9100b57cec5SDimitry Andric     const DWARFDebugLine::Sequence &Seq,
9110b57cec5SDimitry Andric     object::SectionedAddress Address) const {
9120b57cec5SDimitry Andric   if (!Seq.containsPC(Address))
9130b57cec5SDimitry Andric     return UnknownRowIndex;
9140b57cec5SDimitry Andric   assert(Seq.SectionIndex == Address.SectionIndex);
9150b57cec5SDimitry Andric   // In some cases, e.g. first instruction in a function, the compiler generates
9160b57cec5SDimitry Andric   // two entries, both with the same address. We want the last one.
9170b57cec5SDimitry Andric   //
9180b57cec5SDimitry Andric   // In general we want a non-empty range: the last row whose address is less
9190b57cec5SDimitry Andric   // than or equal to Address. This can be computed as upper_bound - 1.
9200b57cec5SDimitry Andric   DWARFDebugLine::Row Row;
9210b57cec5SDimitry Andric   Row.Address = Address;
9220b57cec5SDimitry Andric   RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
9230b57cec5SDimitry Andric   RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
9240b57cec5SDimitry Andric   assert(FirstRow->Address.Address <= Row.Address.Address &&
9250b57cec5SDimitry Andric          Row.Address.Address < LastRow[-1].Address.Address);
9260b57cec5SDimitry Andric   RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1, Row,
9270b57cec5SDimitry Andric                                     DWARFDebugLine::Row::orderByAddress) -
9280b57cec5SDimitry Andric                    1;
9290b57cec5SDimitry Andric   assert(Seq.SectionIndex == RowPos->Address.SectionIndex);
9300b57cec5SDimitry Andric   return RowPos - Rows.begin();
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric uint32_t DWARFDebugLine::LineTable::lookupAddress(
9340b57cec5SDimitry Andric     object::SectionedAddress Address) const {
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   // Search for relocatable addresses
9370b57cec5SDimitry Andric   uint32_t Result = lookupAddressImpl(Address);
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   if (Result != UnknownRowIndex ||
9400b57cec5SDimitry Andric       Address.SectionIndex == object::SectionedAddress::UndefSection)
9410b57cec5SDimitry Andric     return Result;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   // Search for absolute addresses
9440b57cec5SDimitry Andric   Address.SectionIndex = object::SectionedAddress::UndefSection;
9450b57cec5SDimitry Andric   return lookupAddressImpl(Address);
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric uint32_t DWARFDebugLine::LineTable::lookupAddressImpl(
9490b57cec5SDimitry Andric     object::SectionedAddress Address) const {
9500b57cec5SDimitry Andric   // First, find an instruction sequence containing the given address.
9510b57cec5SDimitry Andric   DWARFDebugLine::Sequence Sequence;
9520b57cec5SDimitry Andric   Sequence.SectionIndex = Address.SectionIndex;
9530b57cec5SDimitry Andric   Sequence.HighPC = Address.Address;
9540b57cec5SDimitry Andric   SequenceIter It = llvm::upper_bound(Sequences, Sequence,
9550b57cec5SDimitry Andric                                       DWARFDebugLine::Sequence::orderByHighPC);
9560b57cec5SDimitry Andric   if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex)
9570b57cec5SDimitry Andric     return UnknownRowIndex;
9580b57cec5SDimitry Andric   return findRowInSeq(*It, Address);
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric bool DWARFDebugLine::LineTable::lookupAddressRange(
9620b57cec5SDimitry Andric     object::SectionedAddress Address, uint64_t Size,
9630b57cec5SDimitry Andric     std::vector<uint32_t> &Result) const {
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric   // Search for relocatable addresses
9660b57cec5SDimitry Andric   if (lookupAddressRangeImpl(Address, Size, Result))
9670b57cec5SDimitry Andric     return true;
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   if (Address.SectionIndex == object::SectionedAddress::UndefSection)
9700b57cec5SDimitry Andric     return false;
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   // Search for absolute addresses
9730b57cec5SDimitry Andric   Address.SectionIndex = object::SectionedAddress::UndefSection;
9740b57cec5SDimitry Andric   return lookupAddressRangeImpl(Address, Size, Result);
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
9780b57cec5SDimitry Andric     object::SectionedAddress Address, uint64_t Size,
9790b57cec5SDimitry Andric     std::vector<uint32_t> &Result) const {
9800b57cec5SDimitry Andric   if (Sequences.empty())
9810b57cec5SDimitry Andric     return false;
9820b57cec5SDimitry Andric   uint64_t EndAddr = Address.Address + Size;
9830b57cec5SDimitry Andric   // First, find an instruction sequence containing the given address.
9840b57cec5SDimitry Andric   DWARFDebugLine::Sequence Sequence;
9850b57cec5SDimitry Andric   Sequence.SectionIndex = Address.SectionIndex;
9860b57cec5SDimitry Andric   Sequence.HighPC = Address.Address;
9870b57cec5SDimitry Andric   SequenceIter LastSeq = Sequences.end();
9880b57cec5SDimitry Andric   SequenceIter SeqPos = llvm::upper_bound(
9890b57cec5SDimitry Andric       Sequences, Sequence, DWARFDebugLine::Sequence::orderByHighPC);
9900b57cec5SDimitry Andric   if (SeqPos == LastSeq || !SeqPos->containsPC(Address))
9910b57cec5SDimitry Andric     return false;
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric   SequenceIter StartPos = SeqPos;
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   // Add the rows from the first sequence to the vector, starting with the
9960b57cec5SDimitry Andric   // index we just calculated
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
9990b57cec5SDimitry Andric     const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
10000b57cec5SDimitry Andric     // For the first sequence, we need to find which row in the sequence is the
10010b57cec5SDimitry Andric     // first in our range.
10020b57cec5SDimitry Andric     uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
10030b57cec5SDimitry Andric     if (SeqPos == StartPos)
10040b57cec5SDimitry Andric       FirstRowIndex = findRowInSeq(CurSeq, Address);
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric     // Figure out the last row in the range.
10070b57cec5SDimitry Andric     uint32_t LastRowIndex =
10080b57cec5SDimitry Andric         findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex});
10090b57cec5SDimitry Andric     if (LastRowIndex == UnknownRowIndex)
10100b57cec5SDimitry Andric       LastRowIndex = CurSeq.LastRowIndex - 1;
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric     assert(FirstRowIndex != UnknownRowIndex);
10130b57cec5SDimitry Andric     assert(LastRowIndex != UnknownRowIndex);
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric     for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
10160b57cec5SDimitry Andric       Result.push_back(I);
10170b57cec5SDimitry Andric     }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric     ++SeqPos;
10200b57cec5SDimitry Andric   }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   return true;
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
10260b57cec5SDimitry Andric                                                                 FileLineInfoKind Kind) const {
10270b57cec5SDimitry Andric   if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex))
10280b57cec5SDimitry Andric     return None;
10290b57cec5SDimitry Andric   const FileNameEntry &Entry = Prologue.getFileNameEntry(FileIndex);
10300b57cec5SDimitry Andric   if (Optional<const char *> source = Entry.Source.getAsCString())
10310b57cec5SDimitry Andric     return StringRef(*source);
10320b57cec5SDimitry Andric   return None;
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
10360b57cec5SDimitry Andric   // Debug info can contain paths from any OS, not necessarily
10370b57cec5SDimitry Andric   // an OS we're currently running on. Moreover different compilation units can
10380b57cec5SDimitry Andric   // be compiled on different operating systems and linked together later.
10390b57cec5SDimitry Andric   return sys::path::is_absolute(Path, sys::path::Style::posix) ||
10400b57cec5SDimitry Andric          sys::path::is_absolute(Path, sys::path::Style::windows);
10410b57cec5SDimitry Andric }
10420b57cec5SDimitry Andric 
1043*8bcb0991SDimitry Andric bool DWARFDebugLine::Prologue::getFileNameByIndex(
1044*8bcb0991SDimitry Andric     uint64_t FileIndex, StringRef CompDir, FileLineInfoKind Kind,
1045*8bcb0991SDimitry Andric     std::string &Result, sys::path::Style Style) const {
10460b57cec5SDimitry Andric   if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
10470b57cec5SDimitry Andric     return false;
10480b57cec5SDimitry Andric   const FileNameEntry &Entry = getFileNameEntry(FileIndex);
10490b57cec5SDimitry Andric   StringRef FileName = Entry.Name.getAsCString().getValue();
10500b57cec5SDimitry Andric   if (Kind != FileLineInfoKind::AbsoluteFilePath ||
10510b57cec5SDimitry Andric       isPathAbsoluteOnWindowsOrPosix(FileName)) {
10520b57cec5SDimitry Andric     Result = FileName;
10530b57cec5SDimitry Andric     return true;
10540b57cec5SDimitry Andric   }
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   SmallString<16> FilePath;
10570b57cec5SDimitry Andric   StringRef IncludeDir;
10580b57cec5SDimitry Andric   // Be defensive about the contents of Entry.
10590b57cec5SDimitry Andric   if (getVersion() >= 5) {
10600b57cec5SDimitry Andric     if (Entry.DirIdx < IncludeDirectories.size())
10610b57cec5SDimitry Andric       IncludeDir = IncludeDirectories[Entry.DirIdx].getAsCString().getValue();
10620b57cec5SDimitry Andric   } else {
10630b57cec5SDimitry Andric     if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size())
10640b57cec5SDimitry Andric       IncludeDir =
10650b57cec5SDimitry Andric           IncludeDirectories[Entry.DirIdx - 1].getAsCString().getValue();
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric     // We may still need to append compilation directory of compile unit.
10680b57cec5SDimitry Andric     // We know that FileName is not absolute, the only way to have an
10690b57cec5SDimitry Andric     // absolute path at this point would be if IncludeDir is absolute.
10700b57cec5SDimitry Andric     if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir))
1071*8bcb0991SDimitry Andric       sys::path::append(FilePath, Style, CompDir);
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // sys::path::append skips empty strings.
1075*8bcb0991SDimitry Andric   sys::path::append(FilePath, Style, IncludeDir, FileName);
10760b57cec5SDimitry Andric   Result = FilePath.str();
10770b57cec5SDimitry Andric   return true;
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
10810b57cec5SDimitry Andric     object::SectionedAddress Address, const char *CompDir,
10820b57cec5SDimitry Andric     FileLineInfoKind Kind, DILineInfo &Result) const {
10830b57cec5SDimitry Andric   // Get the index of row we're looking for in the line table.
10840b57cec5SDimitry Andric   uint32_t RowIndex = lookupAddress(Address);
10850b57cec5SDimitry Andric   if (RowIndex == -1U)
10860b57cec5SDimitry Andric     return false;
10870b57cec5SDimitry Andric   // Take file number and line/column from the row.
10880b57cec5SDimitry Andric   const auto &Row = Rows[RowIndex];
10890b57cec5SDimitry Andric   if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
10900b57cec5SDimitry Andric     return false;
10910b57cec5SDimitry Andric   Result.Line = Row.Line;
10920b57cec5SDimitry Andric   Result.Column = Row.Column;
10930b57cec5SDimitry Andric   Result.Discriminator = Row.Discriminator;
10940b57cec5SDimitry Andric   Result.Source = getSourceByIndex(Row.File, Kind);
10950b57cec5SDimitry Andric   return true;
10960b57cec5SDimitry Andric }
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric // We want to supply the Unit associated with a .debug_line[.dwo] table when
10990b57cec5SDimitry Andric // we dump it, if possible, but still dump the table even if there isn't a Unit.
11000b57cec5SDimitry Andric // Therefore, collect up handles on all the Units that point into the
11010b57cec5SDimitry Andric // line-table section.
11020b57cec5SDimitry Andric static DWARFDebugLine::SectionParser::LineToUnitMap
11030b57cec5SDimitry Andric buildLineToUnitMap(DWARFDebugLine::SectionParser::cu_range CUs,
11040b57cec5SDimitry Andric                    DWARFDebugLine::SectionParser::tu_range TUs) {
11050b57cec5SDimitry Andric   DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit;
11060b57cec5SDimitry Andric   for (const auto &CU : CUs)
11070b57cec5SDimitry Andric     if (auto CUDIE = CU->getUnitDIE())
11080b57cec5SDimitry Andric       if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))
11090b57cec5SDimitry Andric         LineToUnit.insert(std::make_pair(*StmtOffset, &*CU));
11100b57cec5SDimitry Andric   for (const auto &TU : TUs)
11110b57cec5SDimitry Andric     if (auto TUDIE = TU->getUnitDIE())
11120b57cec5SDimitry Andric       if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list)))
11130b57cec5SDimitry Andric         LineToUnit.insert(std::make_pair(*StmtOffset, &*TU));
11140b57cec5SDimitry Andric   return LineToUnit;
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data,
11180b57cec5SDimitry Andric                                              const DWARFContext &C,
11190b57cec5SDimitry Andric                                              cu_range CUs, tu_range TUs)
11200b57cec5SDimitry Andric     : DebugLineData(Data), Context(C) {
11210b57cec5SDimitry Andric   LineToUnit = buildLineToUnitMap(CUs, TUs);
11220b57cec5SDimitry Andric   if (!DebugLineData.isValidOffset(Offset))
11230b57cec5SDimitry Andric     Done = true;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric bool DWARFDebugLine::Prologue::totalLengthIsValid() const {
1127*8bcb0991SDimitry Andric   return TotalLength == dwarf::DW_LENGTH_DWARF64 ||
1128*8bcb0991SDimitry Andric          TotalLength < dwarf::DW_LENGTH_lo_reserved;
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
11320b57cec5SDimitry Andric     function_ref<void(Error)> RecoverableErrorCallback,
11330b57cec5SDimitry Andric     function_ref<void(Error)> UnrecoverableErrorCallback, raw_ostream *OS) {
11340b57cec5SDimitry Andric   assert(DebugLineData.isValidOffset(Offset) &&
11350b57cec5SDimitry Andric          "parsing should have terminated");
11360b57cec5SDimitry Andric   DWARFUnit *U = prepareToParse(Offset);
1137*8bcb0991SDimitry Andric   uint64_t OldOffset = Offset;
11380b57cec5SDimitry Andric   LineTable LT;
11390b57cec5SDimitry Andric   if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,
11400b57cec5SDimitry Andric                            RecoverableErrorCallback, OS))
11410b57cec5SDimitry Andric     UnrecoverableErrorCallback(std::move(Err));
11420b57cec5SDimitry Andric   moveToNextTable(OldOffset, LT.Prologue);
11430b57cec5SDimitry Andric   return LT;
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric void DWARFDebugLine::SectionParser::skip(
11470b57cec5SDimitry Andric     function_ref<void(Error)> ErrorCallback) {
11480b57cec5SDimitry Andric   assert(DebugLineData.isValidOffset(Offset) &&
11490b57cec5SDimitry Andric          "parsing should have terminated");
11500b57cec5SDimitry Andric   DWARFUnit *U = prepareToParse(Offset);
1151*8bcb0991SDimitry Andric   uint64_t OldOffset = Offset;
11520b57cec5SDimitry Andric   LineTable LT;
11530b57cec5SDimitry Andric   if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U))
11540b57cec5SDimitry Andric     ErrorCallback(std::move(Err));
11550b57cec5SDimitry Andric   moveToNextTable(OldOffset, LT.Prologue);
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric 
1158*8bcb0991SDimitry Andric DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint64_t Offset) {
11590b57cec5SDimitry Andric   DWARFUnit *U = nullptr;
11600b57cec5SDimitry Andric   auto It = LineToUnit.find(Offset);
11610b57cec5SDimitry Andric   if (It != LineToUnit.end())
11620b57cec5SDimitry Andric     U = It->second;
11630b57cec5SDimitry Andric   DebugLineData.setAddressSize(U ? U->getAddressByteSize() : 0);
11640b57cec5SDimitry Andric   return U;
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
1167*8bcb0991SDimitry Andric void DWARFDebugLine::SectionParser::moveToNextTable(uint64_t OldOffset,
11680b57cec5SDimitry Andric                                                     const Prologue &P) {
11690b57cec5SDimitry Andric   // If the length field is not valid, we don't know where the next table is, so
11700b57cec5SDimitry Andric   // cannot continue to parse. Mark the parser as done, and leave the Offset
11710b57cec5SDimitry Andric   // value as it currently is. This will be the end of the bad length field.
11720b57cec5SDimitry Andric   if (!P.totalLengthIsValid()) {
11730b57cec5SDimitry Andric     Done = true;
11740b57cec5SDimitry Andric     return;
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();
11780b57cec5SDimitry Andric   if (!DebugLineData.isValidOffset(Offset)) {
11790b57cec5SDimitry Andric     Done = true;
11800b57cec5SDimitry Andric   }
11810b57cec5SDimitry Andric }
1182