[Lldb-commits] [lldb] r368742 - [DWARF} Use LLVM's debug line parser in LLDB.

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 13 12:51:51 PDT 2019


Author: jdevlieghere
Date: Tue Aug 13 12:51:51 2019
New Revision: 368742

URL: http://llvm.org/viewvc/llvm-project?rev=368742&view=rev
Log:
[DWARF} Use LLVM's debug line parser in LLDB.

The line number table header was substantially revised in DWARF 5 and is
not fully supported by LLDB's current debug line implementation.

This patch replaces the LLDB debug line parser with its counterpart in
LLVM. This was possible because of the limited contact surface between
the code to parse the DWARF debug line section and the rest of LLDB.

We pay a small cost in terms of performance and memory usage. This is
something we plan to address in the near future.

Differential revision: https://reviews.llvm.org/D62570

Removed:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
Modified:
    lldb/trunk/include/lldb/Core/FileSpecList.h
    lldb/trunk/include/lldb/Symbol/CompileUnit.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Symbol/CompileUnit.cpp

Modified: lldb/trunk/include/lldb/Core/FileSpecList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FileSpecList.h?rev=368742&r1=368741&r2=368742&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FileSpecList.h (original)
+++ lldb/trunk/include/lldb/Core/FileSpecList.h Tue Aug 13 12:51:51 2019
@@ -25,6 +25,9 @@ class Stream;
 /// A class that contains a mutable list of FileSpec objects.
 class FileSpecList {
 public:
+  typedef std::vector<FileSpec> collection;
+  typedef collection::const_iterator const_iterator;
+
   /// Default constructor.
   ///
   /// Initialize this object with an empty file list.
@@ -191,9 +194,10 @@ public:
   static size_t GetFilesMatchingPartialPath(const char *path, bool dir_okay,
                                             FileSpecList &matches);
 
+  const_iterator begin() const { return m_files.begin(); }
+  const_iterator end() const { return m_files.end(); }
+
 protected:
-  typedef std::vector<FileSpec>
-      collection;     ///< The collection type for the file list.
   collection m_files; ///< A collection of FileSpec objects.
 };
 

Modified: lldb/trunk/include/lldb/Symbol/CompileUnit.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/CompileUnit.h?rev=368742&r1=368741&r2=368742&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/CompileUnit.h (original)
+++ lldb/trunk/include/lldb/Symbol/CompileUnit.h Tue Aug 13 12:51:51 2019
@@ -298,6 +298,8 @@ public:
   ///     A line table object pointer that this object now owns.
   void SetLineTable(LineTable *line_table);
 
+  void SetSupportFiles(const FileSpecList &support_files);
+
   void SetDebugMacros(const DebugMacrosSP &debug_macros);
 
   /// Set accessor for the variable list.

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt?rev=368742&r1=368741&r2=368742&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt Tue Aug 13 12:51:51 2019
@@ -22,7 +22,6 @@ add_lldb_library(lldbPluginSymbolFileDWA
   DWARFDebugArangeSet.cpp
   DWARFDebugInfo.cpp
   DWARFDebugInfoEntry.cpp
-  DWARFDebugLine.cpp
   DWARFDebugMacro.cpp
   DWARFDebugRanges.cpp
   DWARFDeclContext.cpp

Removed: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp?rev=368741&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp (removed)
@@ -1,837 +0,0 @@
-//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFDebugLine.h"
-
-//#define ENABLE_DEBUG_PRINTF   // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!!
-#include <assert.h>
-
-#include <memory>
-
-#include "lldb/Core/FileSpecList.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Timer.h"
-
-#include "DWARFUnit.h"
-#include "LogChannelDWARF.h"
-#include "SymbolFileDWARF.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace std;
-
-// Parse
-//
-// Parse all information in the debug_line_data into an internal
-// representation.
-void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) {
-  m_lineTableMap.clear();
-  lldb::offset_t offset = 0;
-  LineTable::shared_ptr line_table_sp(new LineTable);
-  while (debug_line_data.ValidOffset(offset)) {
-    const lldb::offset_t debug_line_offset = offset;
-
-    if (line_table_sp.get() == nullptr)
-      break;
-
-    if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) {
-      // Make sure we don't don't loop infinitely
-      if (offset <= debug_line_offset)
-        break;
-      // DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n",
-      // debug_line_offset);
-      m_lineTableMap[debug_line_offset] = line_table_sp;
-      line_table_sp = std::make_shared<LineTable>();
-    } else
-      ++offset; // Try next byte in line table
-  }
-}
-
-void DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor &debug_line_data) {
-  if (m_lineTableMap.empty())
-    Parse(debug_line_data);
-}
-
-// DWARFDebugLine::GetLineTable
-DWARFDebugLine::LineTable::shared_ptr
-DWARFDebugLine::GetLineTable(const dw_offset_t offset) const {
-  DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr;
-  LineTableConstIter pos = m_lineTableMap.find(offset);
-  if (pos != m_lineTableMap.end())
-    line_table_shared_ptr = pos->second;
-  return line_table_shared_ptr;
-}
-
-// Parse
-//
-// Parse the entire line table contents calling callback each time a new
-// prologue is parsed and every time a new row is to be added to the line
-// table.
-void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data,
-                           DWARFDebugLine::State::Callback callback,
-                           void *userData) {
-  lldb::offset_t offset = 0;
-  if (debug_line_data.ValidOffset(offset)) {
-    if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr))
-      ++offset; // Skip to next byte in .debug_line section
-  }
-}
-
-namespace {
-struct EntryDescriptor {
-  dw_sleb128_t code;
-  dw_sleb128_t form;
-};
-
-static std::vector<EntryDescriptor>
-ReadDescriptors(const DWARFDataExtractor &debug_line_data,
-                lldb::offset_t *offset_ptr) {
-  std::vector<EntryDescriptor> ret;
-  uint8_t n = debug_line_data.GetU8(offset_ptr);
-  for (uint8_t i = 0; i < n; ++i) {
-    EntryDescriptor ent;
-    ent.code = debug_line_data.GetULEB128(offset_ptr);
-    ent.form = debug_line_data.GetULEB128(offset_ptr);
-    ret.push_back(ent);
-  }
-  return ret;
-}
-} // namespace
-
-// DWARFDebugLine::ParsePrologue
-bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
-                                   lldb::offset_t *offset_ptr,
-                                   Prologue *prologue, DWARFUnit *dwarf_cu) {
-  const lldb::offset_t prologue_offset = *offset_ptr;
-
-  // DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
-
-  prologue->Clear();
-  uint32_t i;
-  const char *s;
-  prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr);
-  prologue->version = debug_line_data.GetU16(offset_ptr);
-  if (prologue->version < 2 || prologue->version > 5)
-    return false;
-
-  if (prologue->version >= 5) {
-    prologue->address_size = debug_line_data.GetU8(offset_ptr);
-    prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr);
-  }
-
-  prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
-  const lldb::offset_t end_prologue_offset =
-      prologue->prologue_length + *offset_ptr;
-  prologue->min_inst_length = debug_line_data.GetU8(offset_ptr);
-  if (prologue->version >= 4)
-    prologue->maximum_operations_per_instruction =
-        debug_line_data.GetU8(offset_ptr);
-  else
-    prologue->maximum_operations_per_instruction = 1;
-  prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr);
-  prologue->line_base = debug_line_data.GetU8(offset_ptr);
-  prologue->line_range = debug_line_data.GetU8(offset_ptr);
-  prologue->opcode_base = debug_line_data.GetU8(offset_ptr);
-
-  prologue->standard_opcode_lengths.reserve(prologue->opcode_base - 1);
-
-  for (i = 1; i < prologue->opcode_base; ++i) {
-    uint8_t op_len = debug_line_data.GetU8(offset_ptr);
-    prologue->standard_opcode_lengths.push_back(op_len);
-  }
-
-  if (prologue->version >= 5) {
-    std::vector<EntryDescriptor> dirEntryFormatV =
-        ReadDescriptors(debug_line_data, offset_ptr);
-    uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr);
-    for (int i = 0; i < dirCount; ++i) {
-      for (EntryDescriptor &ent : dirEntryFormatV) {
-        DWARFFormValue value(dwarf_cu, ent.form);
-        if (ent.code != DW_LNCT_path) {
-          if (!value.SkipValue(debug_line_data, offset_ptr))
-            return false;
-          continue;
-        }
-
-        if (!value.ExtractValue(debug_line_data, offset_ptr))
-          return false;
-        prologue->include_directories.push_back(value.AsCString());
-      }
-    }
-
-    std::vector<EntryDescriptor> filesEntryFormatV =
-        ReadDescriptors(debug_line_data, offset_ptr);
-    llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen;
-    uint8_t n = debug_line_data.GetULEB128(offset_ptr);
-    for (int i = 0; i < n; ++i) {
-      FileNameEntry entry;
-      for (EntryDescriptor &ent : filesEntryFormatV) {
-        DWARFFormValue value(dwarf_cu, ent.form);
-        if (!value.ExtractValue(debug_line_data, offset_ptr))
-          return false;
-
-        switch (ent.code) {
-        case DW_LNCT_path:
-          entry.name = value.AsCString();
-          break;
-        case DW_LNCT_directory_index:
-          entry.dir_idx = value.Unsigned();
-          break;
-        case DW_LNCT_timestamp:
-          entry.mod_time = value.Unsigned();
-          break;
-        case DW_LNCT_size:
-          entry.length = value.Unsigned();
-          break;
-        case DW_LNCT_MD5:
-          assert(value.Unsigned() == 16);
-          std::uninitialized_copy_n(value.BlockData(), 16,
-                                    entry.checksum.Bytes.begin());
-          break;
-        default:
-          break;
-        }
-      }
-
-      if (seen.insert(entry.checksum.words()).second)
-        prologue->file_names.push_back(entry);
-    }
-  } else {
-    while (*offset_ptr < end_prologue_offset) {
-      s = debug_line_data.GetCStr(offset_ptr);
-      if (s && s[0])
-        prologue->include_directories.push_back(s);
-      else
-        break;
-    }
-
-    while (*offset_ptr < end_prologue_offset) {
-      const char *name = debug_line_data.GetCStr(offset_ptr);
-      if (name && name[0]) {
-        FileNameEntry fileEntry;
-        fileEntry.name = name;
-        fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
-        fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
-        fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
-        prologue->file_names.push_back(fileEntry);
-      } else
-        break;
-    }
-  }
-
-  // XXX GNU as is broken for 64-Bit DWARF
-  if (*offset_ptr != end_prologue_offset) {
-    Host::SystemLog(Host::eSystemLogWarning,
-                    "warning: parsing line table prologue at 0x%8.8" PRIx64
-                    " should have ended at 0x%8.8" PRIx64
-                    " but it ended at 0x%8.8" PRIx64 "\n",
-                    prologue_offset, end_prologue_offset, *offset_ptr);
-  }
-  return end_prologue_offset;
-}
-
-bool DWARFDebugLine::ParseSupportFiles(
-    const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
-    dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) {
-  lldb::offset_t offset = stmt_list;
-
-  Prologue prologue;
-  if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) {
-    Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue "
-                                           "at 0x%8.8x (parsing ended around "
-                                           "0x%8.8" PRIx64 "\n",
-                    stmt_list, offset);
-    return false;
-  }
-
-  FileSpec file_spec;
-  std::string remapped_file;
-
-  for (uint32_t file_idx = 1;
-       prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(),
-                        dwarf_cu->GetPathStyle(), file_spec);
-       ++file_idx) {
-    if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
-      file_spec.SetFile(remapped_file, FileSpec::Style::native);
-    support_files.Append(file_spec);
-  }
-  return true;
-}
-
-// ParseStatementTable
-//
-// Parse a single line table (prologue and all rows) and call the callback
-// function once for the prologue (row in state will be zero) and each time a
-// row is to be added to the line table.
-bool DWARFDebugLine::ParseStatementTable(
-    const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
-    DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) {
-  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE));
-  Prologue::shared_ptr prologue(new Prologue());
-
-  const dw_offset_t debug_line_offset = *offset_ptr;
-
-  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
-  Timer scoped_timer(
-      func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
-      debug_line_offset);
-
-  if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) {
-    if (log)
-      log->Error("failed to parse DWARF line table prologue");
-    // Restore our offset and return false to indicate failure!
-    *offset_ptr = debug_line_offset;
-    return false;
-  }
-
-  if (log)
-    prologue->Dump(log);
-
-  const dw_offset_t end_offset =
-      debug_line_offset + prologue->total_length +
-      (debug_line_data.GetDWARFSizeofInitialLength());
-
-  State state(prologue, log, callback, userData);
-
-  while (*offset_ptr < end_offset) {
-    // DEBUG_PRINTF("0x%8.8x: ", *offset_ptr);
-    uint8_t opcode = debug_line_data.GetU8(offset_ptr);
-
-    if (opcode == 0) {
-      // Extended Opcodes always start with a zero opcode followed by a uleb128
-      // length so you can skip ones you don't know about
-      lldb::offset_t ext_offset = *offset_ptr;
-      dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
-      dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
-
-      // DEBUG_PRINTF("Extended: <%2u> ", len);
-      uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr);
-      switch (sub_opcode) {
-      case DW_LNE_end_sequence:
-        // Set the end_sequence register of the state machine to true and
-        // append a row to the matrix using the current values of the state-
-        // machine registers. Then reset the registers to the initial values
-        // specified above. Every statement program sequence must end with a
-        // DW_LNE_end_sequence instruction which creates a row whose address is
-        // that of the byte after the last target machine instruction of the
-        // sequence.
-        state.end_sequence = true;
-        state.AppendRowToMatrix(*offset_ptr);
-        state.Reset();
-        break;
-
-      case DW_LNE_set_address:
-        // Takes a single relocatable address as an operand. The size of the
-        // operand is the size appropriate to hold an address on the target
-        // machine. Set the address register to the value given by the
-        // relocatable address. All of the other statement program opcodes that
-        // affect the address register add a delta to it. This instruction
-        // stores a relocatable value into it instead.
-        if (arg_size == 4)
-          state.address = debug_line_data.GetU32(offset_ptr);
-        else // arg_size == 8
-          state.address = debug_line_data.GetU64(offset_ptr);
-        break;
-
-      case DW_LNE_define_file:
-        // Takes 4 arguments. The first is a null terminated string containing
-        // a source file name. The second is an unsigned LEB128 number
-        // representing the directory index of the directory in which the file
-        // was found. The third is an unsigned LEB128 number representing the
-        // time of last modification of the file. The fourth is an unsigned
-        // LEB128 number representing the length in bytes of the file. The time
-        // and length fields may contain LEB128(0) if the information is not
-        // available.
-        //
-        // The directory index represents an entry in the include_directories
-        // section of the statement program prologue. The index is LEB128(0) if
-        // the file was found in the current directory of the compilation,
-        // LEB128(1) if it was found in the first directory in the
-        // include_directories section, and so on. The directory index is
-        // ignored for file names that represent full path names.
-        //
-        // The files are numbered, starting at 1, in the order in which they
-        // appear; the names in the prologue come before names defined by the
-        // DW_LNE_define_file instruction. These numbers are used in the file
-        // register of the state machine.
-        {
-          FileNameEntry fileEntry;
-          fileEntry.name = debug_line_data.GetCStr(offset_ptr);
-          fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
-          fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
-          fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
-          state.prologue->file_names.push_back(fileEntry);
-        }
-        break;
-
-      default:
-        // Length doesn't include the zero opcode byte or the length itself,
-        // but it does include the sub_opcode, so we have to adjust for that
-        // below
-        (*offset_ptr) += arg_size;
-        break;
-      }
-    } else if (opcode < prologue->opcode_base) {
-      switch (opcode) {
-      // Standard Opcodes
-      case DW_LNS_copy:
-        // Takes no arguments. Append a row to the matrix using the current
-        // values of the state-machine registers. Then set the basic_block
-        // register to false.
-        state.AppendRowToMatrix(*offset_ptr);
-        break;
-
-      case DW_LNS_advance_pc:
-        // Takes a single unsigned LEB128 operand, multiplies it by the
-        // min_inst_length field of the prologue, and adds the result to the
-        // address register of the state machine.
-        state.address +=
-            debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
-        break;
-
-      case DW_LNS_advance_line:
-        // Takes a single signed LEB128 operand and adds that value to the line
-        // register of the state machine.
-        state.line += debug_line_data.GetSLEB128(offset_ptr);
-        break;
-
-      case DW_LNS_set_file:
-        // Takes a single unsigned LEB128 operand and stores it in the file
-        // register of the state machine.
-        state.file = debug_line_data.GetULEB128(offset_ptr);
-        break;
-
-      case DW_LNS_set_column:
-        // Takes a single unsigned LEB128 operand and stores it in the column
-        // register of the state machine.
-        state.column = debug_line_data.GetULEB128(offset_ptr);
-        break;
-
-      case DW_LNS_negate_stmt:
-        // Takes no arguments. Set the is_stmt register of the state machine to
-        // the logical negation of its current value.
-        state.is_stmt = !state.is_stmt;
-        break;
-
-      case DW_LNS_set_basic_block:
-        // Takes no arguments. Set the basic_block register of the state
-        // machine to true
-        state.basic_block = true;
-        break;
-
-      case DW_LNS_const_add_pc:
-        // Takes no arguments. Add to the address register of the state machine
-        // the address increment value corresponding to special opcode 255. The
-        // motivation for DW_LNS_const_add_pc is this: when the statement
-        // program needs to advance the address by a small amount, it can use a
-        // single special opcode, which occupies a single byte. When it needs
-        // to advance the address by up to twice the range of the last special
-        // opcode, it can use DW_LNS_const_add_pc followed by a special opcode,
-        // for a total of two bytes. Only if it needs to advance the address by
-        // more than twice that range will it need to use both
-        // DW_LNS_advance_pc and a special opcode, requiring three or more
-        // bytes.
-        {
-          uint8_t adjust_opcode = 255 - prologue->opcode_base;
-          dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) *
-                                  prologue->min_inst_length;
-          state.address += addr_offset;
-        }
-        break;
-
-      case DW_LNS_fixed_advance_pc:
-        // Takes a single uhalf operand. Add to the address register of the
-        // state machine the value of the (unencoded) operand. This is the only
-        // extended opcode that takes an argument that is not a variable length
-        // number. The motivation for DW_LNS_fixed_advance_pc is this: existing
-        // assemblers cannot emit DW_LNS_advance_pc or special opcodes because
-        // they cannot encode LEB128 numbers or judge when the computation of a
-        // special opcode overflows and requires the use of DW_LNS_advance_pc.
-        // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead,
-        // sacrificing compression.
-        state.address += debug_line_data.GetU16(offset_ptr);
-        break;
-
-      case DW_LNS_set_prologue_end:
-        // Takes no arguments. Set the prologue_end register of the state
-        // machine to true
-        state.prologue_end = true;
-        break;
-
-      case DW_LNS_set_epilogue_begin:
-        // Takes no arguments. Set the basic_block register of the state
-        // machine to true
-        state.epilogue_begin = true;
-        break;
-
-      case DW_LNS_set_isa:
-        // Takes a single unsigned LEB128 operand and stores it in the column
-        // register of the state machine.
-        state.isa = debug_line_data.GetULEB128(offset_ptr);
-        break;
-
-      default:
-        // Handle any unknown standard opcodes here. We know the lengths of
-        // such opcodes because they are specified in the prologue as a
-        // multiple of LEB128 operands for each opcode.
-        {
-          uint8_t i;
-          assert(static_cast<size_t>(opcode - 1) <
-                 prologue->standard_opcode_lengths.size());
-          const uint8_t opcode_length =
-              prologue->standard_opcode_lengths[opcode - 1];
-          for (i = 0; i < opcode_length; ++i)
-            debug_line_data.Skip_LEB128(offset_ptr);
-        }
-        break;
-      }
-    } else {
-      // Special Opcodes
-
-      // A special opcode value is chosen based on the amount that needs
-      // to be added to the line and address registers. The maximum line
-      // increment for a special opcode is the value of the line_base field in
-      // the header, plus the value of the line_range field, minus 1 (line base
-      // + line range - 1). If the desired line increment is greater than the
-      // maximum line increment, a standard opcode must be used instead of a
-      // special opcode. The "address advance" is calculated by dividing the
-      // desired address increment by the minimum_instruction_length field from
-      // the header. The special opcode is then calculated using the following
-      // formula:
-      //
-      //  opcode = (desired line increment - line_base) + (line_range * address
-      //  advance) + opcode_base
-      //
-      // If the resulting opcode is greater than 255, a standard opcode must be
-      // used instead.
-      //
-      // To decode a special opcode, subtract the opcode_base from the opcode
-      // itself to give the adjusted opcode. The amount to increment the
-      // address register is the result of the adjusted opcode divided by the
-      // line_range multiplied by the minimum_instruction_length field from the
-      // header. That is:
-      //
-      //  address increment = (adjusted opcode / line_range) *
-      //  minimum_instruction_length
-      //
-      // The amount to increment the line register is the line_base plus the
-      // result of the adjusted opcode modulo the line_range. That is:
-      //
-      // line increment = line_base + (adjusted opcode % line_range)
-
-      uint8_t adjust_opcode = opcode - prologue->opcode_base;
-      dw_addr_t addr_offset =
-          (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
-      int32_t line_offset =
-          prologue->line_base + (adjust_opcode % prologue->line_range);
-      state.line += line_offset;
-      state.address += addr_offset;
-      state.AppendRowToMatrix(*offset_ptr);
-    }
-  }
-
-  state.Finalize(*offset_ptr);
-
-  return end_offset;
-}
-
-// ParseStatementTableCallback
-static void ParseStatementTableCallback(dw_offset_t offset,
-                                        const DWARFDebugLine::State &state,
-                                        void *userData) {
-  DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData;
-  if (state.row == DWARFDebugLine::State::StartParsingLineTable) {
-    // Just started parsing the line table, so lets keep a reference to the
-    // prologue using the supplied shared pointer
-    line_table->prologue = state.prologue;
-  } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) {
-    // Done parsing line table, nothing to do for the cleanup
-  } else {
-    // We have a new row, lets append it
-    line_table->AppendRow(state);
-  }
-}
-
-// ParseStatementTable
-//
-// Parse a line table at offset and populate the LineTable class with the
-// prologue and all rows.
-bool DWARFDebugLine::ParseStatementTable(
-    const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
-    LineTable *line_table, DWARFUnit *dwarf_cu) {
-  return ParseStatementTable(debug_line_data, offset_ptr,
-                             ParseStatementTableCallback, line_table, dwarf_cu);
-}
-
-inline bool DWARFDebugLine::Prologue::IsValid() const {
-  return SymbolFileDWARF::SupportedVersion(version);
-}
-
-// DWARFDebugLine::Prologue::Dump
-void DWARFDebugLine::Prologue::Dump(Log *log) {
-  uint32_t i;
-
-  LLDB_LOGF(log, "Line table prologue:");
-  LLDB_LOGF(log, "   total_length: 0x%8.8x", total_length);
-  LLDB_LOGF(log, "        version: %u", version);
-  LLDB_LOGF(log, "prologue_length: 0x%8.8x", prologue_length);
-  LLDB_LOGF(log, "min_inst_length: %u", min_inst_length);
-  LLDB_LOGF(log, "default_is_stmt: %u", default_is_stmt);
-  LLDB_LOGF(log, "      line_base: %i", line_base);
-  LLDB_LOGF(log, "     line_range: %u", line_range);
-  LLDB_LOGF(log, "    opcode_base: %u", opcode_base);
-
-  for (i = 0; i < standard_opcode_lengths.size(); ++i) {
-    LLDB_LOGF(log, "standard_opcode_lengths[%s] = %u",
-              DW_LNS_value_to_name(i + 1), standard_opcode_lengths[i]);
-  }
-
-  if (!include_directories.empty()) {
-    for (i = 0; i < include_directories.size(); ++i) {
-      LLDB_LOGF(log, "include_directories[%3u] = '%s'", i + 1,
-                include_directories[i]);
-    }
-  }
-
-  if (!file_names.empty()) {
-    log->PutCString("                Dir  Mod Time   File Len   File Name");
-    log->PutCString("                ---- ---------- ---------- "
-                    "---------------------------");
-    for (i = 0; i < file_names.size(); ++i) {
-      const FileNameEntry &fileEntry = file_names[i];
-      LLDB_LOGF(log, "file_names[%3u] %4u 0x%8.8x 0x%8.8x %s", i + 1,
-                fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length,
-                fileEntry.name);
-    }
-  }
-}
-
-// DWARFDebugLine::ParsePrologue::Append
-//
-// Append the contents of the prologue to the binary stream buffer
-// void
-// DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const
-//{
-//  uint32_t i;
-//
-//  buff.Append32(total_length);
-//  buff.Append16(version);
-//  buff.Append32(prologue_length);
-//  buff.Append8(min_inst_length);
-//  buff.Append8(default_is_stmt);
-//  buff.Append8(line_base);
-//  buff.Append8(line_range);
-//  buff.Append8(opcode_base);
-//
-//  for (i=0; i<standard_opcode_lengths.size(); ++i)
-//      buff.Append8(standard_opcode_lengths[i]);
-//
-//  for (i=0; i<include_directories.size(); ++i)
-//      buff.AppendCStr(include_directories[i].c_str());
-//  buff.Append8(0);    // Terminate the include directory section with empty
-//  string
-//
-//  for (i=0; i<file_names.size(); ++i)
-//  {
-//      buff.AppendCStr(file_names[i].name.c_str());
-//      buff.Append32_as_ULEB128(file_names[i].dir_idx);
-//      buff.Append32_as_ULEB128(file_names[i].mod_time);
-//      buff.Append32_as_ULEB128(file_names[i].length);
-//  }
-//  buff.Append8(0);    // Terminate the file names section with empty string
-//}
-
-bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
-                                       const FileSpec &comp_dir,
-                                       FileSpec::Style style,
-                                       FileSpec &file) const {
-  uint32_t idx = file_idx - 1; // File indexes are 1 based...
-  if (idx < file_names.size()) {
-    file.SetFile(file_names[idx].name, style);
-    if (file.IsRelative()) {
-      if (file_names[idx].dir_idx > 0) {
-        const uint32_t dir_idx = file_names[idx].dir_idx - 1;
-        if (dir_idx < include_directories.size()) {
-          file.PrependPathComponent(include_directories[dir_idx]);
-          if (!file.IsRelative())
-            return true;
-        }
-      }
-
-      if (comp_dir)
-        file.PrependPathComponent(comp_dir);
-    }
-    return true;
-  }
-  return false;
-}
-
-void DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row &state) {
-  rows.push_back(state);
-}
-
-// Compare function for the binary search in
-// DWARFDebugLine::LineTable::LookupAddress()
-static bool FindMatchingAddress(const DWARFDebugLine::Row &row1,
-                                const DWARFDebugLine::Row &row2) {
-  return row1.address < row2.address;
-}
-
-// DWARFDebugLine::LineTable::LookupAddress
-uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address,
-                                                  dw_addr_t cu_high_pc) const {
-  uint32_t index = UINT32_MAX;
-  if (!rows.empty()) {
-    // Use the lower_bound algorithm to perform a binary search since we know
-    // that our line table data is ordered by address.
-    DWARFDebugLine::Row row;
-    row.address = address;
-    Row::const_iterator begin_pos = rows.begin();
-    Row::const_iterator end_pos = rows.end();
-    Row::const_iterator pos =
-        lower_bound(begin_pos, end_pos, row, FindMatchingAddress);
-    if (pos == end_pos) {
-      if (address < cu_high_pc)
-        return rows.size() - 1;
-    } else {
-      // Rely on fact that we are using a std::vector and we can do pointer
-      // arithmetic to find the row index (which will be one less that what we
-      // found since it will find the first position after the current address)
-      // since std::vector iterators are just pointers to the container type.
-      index = pos - begin_pos;
-      if (pos->address > address) {
-        if (index > 0)
-          --index;
-        else
-          index = UINT32_MAX;
-      }
-    }
-  }
-  return index; // Failed to find address
-}
-
-// DWARFDebugLine::Row::Row
-DWARFDebugLine::Row::Row(bool default_is_stmt)
-    : address(0), line(1), column(0), file(1), is_stmt(default_is_stmt),
-      basic_block(false), end_sequence(false), prologue_end(false),
-      epilogue_begin(false), isa(0) {}
-
-// Called after a row is appended to the matrix
-void DWARFDebugLine::Row::PostAppend() {
-  basic_block = false;
-  prologue_end = false;
-  epilogue_begin = false;
-}
-
-// DWARFDebugLine::Row::Reset
-void DWARFDebugLine::Row::Reset(bool default_is_stmt) {
-  address = 0;
-  line = 1;
-  column = 0;
-  file = 1;
-  is_stmt = default_is_stmt;
-  basic_block = false;
-  end_sequence = false;
-  prologue_end = false;
-  epilogue_begin = false;
-  isa = 0;
-}
-// DWARFDebugLine::Row::Dump
-void DWARFDebugLine::Row::Dump(Log *log) const {
-  LLDB_LOGF(log, "0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s", address, line,
-            column, file, isa, is_stmt ? " is_stmt" : "",
-            basic_block ? " basic_block" : "",
-            prologue_end ? " prologue_end" : "",
-            epilogue_begin ? " epilogue_begin" : "",
-            end_sequence ? " end_sequence" : "");
-}
-
-// Compare function LineTable structures
-static bool AddressLessThan(const DWARFDebugLine::Row &a,
-                            const DWARFDebugLine::Row &b) {
-  return a.address < b.address;
-}
-
-// Insert a row at the correct address if the addresses can be out of order
-// which can only happen when we are linking a line table that may have had
-// it's contents rearranged.
-void DWARFDebugLine::Row::Insert(Row::collection &state_coll,
-                                 const Row &state) {
-  // If we don't have anything yet, or if the address of the last state in our
-  // line table is less than the current one, just append the current state
-  if (state_coll.empty() || AddressLessThan(state_coll.back(), state)) {
-    state_coll.push_back(state);
-  } else {
-    // Do a binary search for the correct entry
-    pair<Row::iterator, Row::iterator> range(equal_range(
-        state_coll.begin(), state_coll.end(), state, AddressLessThan));
-
-    // If the addresses are equal, we can safely replace the previous entry
-    // with the current one if the one it is replacing is an end_sequence
-    // entry. We currently always place an extra end sequence when ever we exit
-    // a valid address range for a function in case the functions get
-    // rearranged by optimizations or by order specifications. These extra end
-    // sequences will disappear by getting replaced with valid consecutive
-    // entries within a compile unit if there are no gaps.
-    if (range.first == range.second) {
-      state_coll.insert(range.first, state);
-    } else {
-      if ((distance(range.first, range.second) == 1) &&
-          range.first->end_sequence == true) {
-        *range.first = state;
-      } else {
-        state_coll.insert(range.second, state);
-      }
-    }
-  }
-}
-
-// DWARFDebugLine::State::State
-DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l,
-                             DWARFDebugLine::State::Callback cb, void *userData)
-    : Row(p->default_is_stmt), prologue(p), log(l), callback(cb),
-      callbackUserData(userData), row(StartParsingLineTable) {
-  // Call the callback with the initial row state of zero for the prologue
-  if (callback)
-    callback(0, *this, callbackUserData);
-}
-
-// DWARFDebugLine::State::Reset
-void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); }
-
-// DWARFDebugLine::State::AppendRowToMatrix
-void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) {
-  // Each time we are to add an entry into the line table matrix call the
-  // callback function so that someone can do something with the current state
-  // of the state machine (like build a line table or dump the line table!)
-  if (log) {
-    if (row == 0) {
-      log->PutCString("Address            Line   Column File   ISA Flags");
-      log->PutCString(
-          "------------------ ------ ------ ------ --- -------------");
-    }
-    Dump(log);
-  }
-
-  ++row; // Increase the row number before we call our callback for a real row
-  if (callback)
-    callback(offset, *this, callbackUserData);
-  PostAppend();
-}
-
-// DWARFDebugLine::State::Finalize
-void DWARFDebugLine::State::Finalize(dw_offset_t offset) {
-  // Call the callback with a special row state when we are done parsing a line
-  // table
-  row = DoneParsingLineTable;
-  if (callback)
-    callback(offset, *this, callbackUserData);
-}
-

Removed: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h?rev=368741&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h (removed)
@@ -1,224 +0,0 @@
-//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFDebugLine_h_
-#define SymbolFileDWARF_DWARFDebugLine_h_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-private.h"
-
-#include "DWARFDataExtractor.h"
-#include "DWARFDefines.h"
-
-#include "llvm/Support/MD5.h"
-
-class DWARFUnit;
-class SymbolFileDWARF;
-
-// DWARFDebugLine
-class DWARFDebugLine {
-public:
-  // FileNameEntry
-  struct FileNameEntry {
-    FileNameEntry()
-        : name(nullptr), dir_idx(0), mod_time(0), length(0), checksum() {}
-
-    const char *name;
-    dw_sleb128_t dir_idx;
-    dw_sleb128_t mod_time;
-    dw_sleb128_t length;
-    llvm::MD5::MD5Result checksum;
-  };
-
-  // Prologue
-  struct Prologue {
-
-    Prologue()
-        : total_length(0), version(0), prologue_length(0), min_inst_length(0),
-          default_is_stmt(0), line_base(0), line_range(0), opcode_base(0),
-          standard_opcode_lengths(), include_directories(), file_names() {}
-
-    typedef std::shared_ptr<Prologue> shared_ptr;
-
-    uint32_t total_length; // The size in bytes of the statement information for
-                           // this compilation unit (not including the
-                           // total_length field itself).
-    uint16_t
-        version; // Version identifier for the statement information format.
-
-    uint8_t address_size;
-    uint8_t segment_selector_size;
-
-    uint32_t prologue_length; // The number of bytes following the
-                              // prologue_length field to the beginning of the
-                              // first byte of the statement program itself.
-    uint8_t min_inst_length; // The size in bytes of the smallest target machine
-                             // instruction. Statement program opcodes that
-                             // alter the address register first multiply their
-                             // operands by this value.
-    uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum
-                                                // number of individual
-                                                // operations that may be
-                                                // encoded in an instruction.
-    uint8_t default_is_stmt; // The initial value of theis_stmtregister.
-    int8_t line_base;    // This parameter affects the meaning of the special
-                         // opcodes. See below.
-    uint8_t line_range;  // This parameter affects the meaning of the special
-                         // opcodes. See below.
-    uint8_t opcode_base; // The number assigned to the first special opcode.
-    std::vector<uint8_t> standard_opcode_lengths;
-    std::vector<const char *> include_directories;
-    std::vector<FileNameEntry> file_names;
-
-    int32_t MaxLineIncrementForSpecialOpcode() const {
-      return line_base + (int8_t)line_range - 1;
-    }
-    bool IsValid() const;
-    //      void Append(BinaryStreamBuf& buff) const;
-    void Dump(lldb_private::Log *log);
-    void Clear() {
-      total_length = version = prologue_length = min_inst_length = line_base =
-          line_range = opcode_base = 0;
-      line_base = 0;
-      standard_opcode_lengths.clear();
-      include_directories.clear();
-      file_names.clear();
-    }
-    bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir,
-                 lldb_private::FileSpec::Style style,
-                 lldb_private::FileSpec &file) const;
-  };
-
-  // Standard .debug_line state machine structure
-  struct Row {
-    typedef std::vector<Row> collection;
-    typedef collection::iterator iterator;
-    typedef collection::const_iterator const_iterator;
-
-    Row(bool default_is_stmt = false);
-    virtual ~Row() {}
-    void PostAppend();
-    void Reset(bool default_is_stmt);
-    void Dump(lldb_private::Log *log) const;
-    static void Insert(Row::collection &state_coll, const Row &state);
-
-    dw_addr_t address; // The program-counter value corresponding to a machine
-                       // instruction generated by the compiler.
-    uint32_t line; // An unsigned integer indicating a source line number. Lines
-                   // are numbered beginning at 1. The compiler may emit the
-                   // value 0 in cases where an instruction cannot be attributed
-                   // to any source line.
-    uint16_t column; // An unsigned integer indicating a column number within a
-                     // source line. Columns are numbered beginning at 1. The
-                     // value 0 is reserved to indicate that a statement begins
-                     // at the 'left edge' of the line.
-    uint16_t file; // An unsigned integer indicating the identity of the source
-                   // file corresponding to a machine instruction.
-    uint8_t is_stmt : 1, // A boolean indicating that the current instruction is
-                         // the beginning of a statement.
-        basic_block : 1, // A boolean indicating that the current instruction is
-                         // the beginning of a basic block.
-        end_sequence : 1, // A boolean indicating that the current address is
-                          // that of the first byte after the end of a sequence
-                          // of target machine instructions.
-        prologue_end : 1, // A boolean indicating that the current address is
-                          // one (of possibly many) where execution should be
-                          // suspended for an entry breakpoint of a function.
-        epilogue_begin : 1; // A boolean indicating that the current address is
-                            // one (of possibly many) where execution should be
-                            // suspended for an exit breakpoint of a function.
-    uint32_t isa; // An unsigned integer whose value encodes the applicable
-                  // instruction set architecture for the current instruction.
-  };
-
-  // LineTable
-  struct LineTable {
-    typedef std::shared_ptr<LineTable> shared_ptr;
-
-    LineTable() : prologue(), rows() {}
-
-    void AppendRow(const DWARFDebugLine::Row &state);
-    void Clear() {
-      prologue.reset();
-      rows.clear();
-    }
-
-    uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const;
-
-    Prologue::shared_ptr prologue;
-    Row::collection rows;
-  };
-
-  // State
-  struct State : public Row {
-    typedef void (*Callback)(dw_offset_t offset, const State &state,
-                             void *userData);
-
-    // Special row codes used when calling the callback
-    enum { StartParsingLineTable = 0, DoneParsingLineTable = -1 };
-
-    State(Prologue::shared_ptr &prologue_sp, lldb_private::Log *log,
-          Callback callback, void *userData);
-
-    void AppendRowToMatrix(dw_offset_t offset);
-
-    void Finalize(dw_offset_t offset);
-
-    void Reset();
-
-    Prologue::shared_ptr prologue;
-    lldb_private::Log *log;
-    Callback callback; // Callback function that gets called each time an entry
-                       // is to be added to the matrix
-    void *callbackUserData;
-    int row; // The row number that starts at zero for the prologue, and
-             // increases for each row added to the matrix
-  private:
-    DISALLOW_COPY_AND_ASSIGN(State);
-  };
-
-  static bool
-  ParseSupportFiles(const lldb::ModuleSP &module_sp,
-                    const lldb_private::DWARFDataExtractor &debug_line_data,
-                    dw_offset_t stmt_list,
-                    lldb_private::FileSpecList &support_files,
-                    DWARFUnit *dwarf_cu);
-  static bool
-  ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
-                lldb::offset_t *offset_ptr, Prologue *prologue,
-                DWARFUnit *dwarf_cu = nullptr);
-  static bool
-  ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data,
-                      lldb::offset_t *offset_ptr, State::Callback callback,
-                      void *userData, DWARFUnit *dwarf_cu);
-  static bool
-  ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data,
-                      lldb::offset_t *offset_ptr, LineTable *line_table,
-                      DWARFUnit *dwarf_cu);
-  static void Parse(const lldb_private::DWARFDataExtractor &debug_line_data,
-                    DWARFDebugLine::State::Callback callback, void *userData);
-
-  DWARFDebugLine() : m_lineTableMap() {}
-
-  void Parse(const lldb_private::DWARFDataExtractor &debug_line_data);
-  void ParseIfNeeded(const lldb_private::DWARFDataExtractor &debug_line_data);
-  LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const;
-
-protected:
-  typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap;
-  typedef LineTableMap::iterator LineTableIter;
-  typedef LineTableMap::const_iterator LineTableConstIter;
-
-  LineTableMap m_lineTableMap;
-};
-
-#endif // SymbolFileDWARF_DWARFDebugLine_h_

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=368742&r1=368741&r2=368742&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Aug 13 12:51:51 2019
@@ -58,7 +58,6 @@
 #include "DWARFDebugAbbrev.h"
 #include "DWARFDebugAranges.h"
 #include "DWARFDebugInfo.h"
-#include "DWARFDebugLine.h"
 #include "DWARFDebugMacro.h"
 #include "DWARFDebugRanges.h"
 #include "DWARFDeclContext.h"
@@ -72,6 +71,7 @@
 #include "SymbolFileDWARFDwo.h"
 #include "SymbolFileDWARFDwp.h"
 
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Support/FileSystem.h"
 
 #include <algorithm>
@@ -153,7 +153,67 @@ static const SymbolFileDWARFPropertiesSP
   return g_settings_sp;
 }
 
-} // anonymous namespace end
+} // namespace
+
+static const llvm::DWARFDebugLine::LineTable *
+ParseLLVMLineTable(lldb_private::DWARFContext &context,
+                   llvm::DWARFDebugLine &line, dw_offset_t line_offset,
+                   dw_offset_t unit_offset) {
+  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+
+  llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM();
+  llvm::DWARFContext &ctx = context.GetAsLLVM();
+  llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table =
+      line.getOrParseLineTable(
+          data, line_offset, ctx, nullptr, [&](llvm::Error e) {
+            LLDB_LOG_ERROR(log, std::move(e),
+                           "SymbolFileDWARF::ParseLineTable failed to parse");
+          });
+
+  if (!line_table) {
+    LLDB_LOG_ERROR(log, line_table.takeError(),
+                   "SymbolFileDWARF::ParseLineTable failed to parse");
+    return nullptr;
+  }
+  return *line_table;
+}
+
+static FileSpecList
+ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
+                              const llvm::DWARFDebugLine::Prologue &prologue,
+                              llvm::StringRef compile_dir = {},
+                              FileSpec first_file = {}) {
+  FileSpecList support_files;
+  support_files.Append(first_file);
+
+  const size_t number_of_files = prologue.FileNames.size();
+  for (size_t idx = 1; idx <= number_of_files; ++idx) {
+    std::string original_file;
+    if (!prologue.getFileNameByIndex(
+            idx, compile_dir,
+            llvm::DILineInfoSpecifier::FileLineInfoKind::Default,
+            original_file)) {
+      // Always add an entry so the indexes remain correct.
+      support_files.EmplaceBack();
+      continue;
+    }
+
+    std::string remapped_file;
+    if (!prologue.getFileNameByIndex(
+            idx, compile_dir,
+            llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+            remapped_file)) {
+      // Always add an entry so the indexes remain correct.
+      support_files.EmplaceBack(original_file, FileSpec::Style::native);
+      continue;
+    }
+
+    module->RemapSourceFile(llvm::StringRef(original_file), remapped_file);
+    support_files.EmplaceBack(remapped_file, FileSpec::Style::native);
+  }
+
+  return support_files;
+}
 
 FileSpecList SymbolFileDWARF::GetSymlinkPaths() {
   return GetGlobalPluginProperties()->GetSymLinkPaths();
@@ -452,7 +512,8 @@ uint32_t SymbolFileDWARF::CalculateAbili
         abbrev->GetUnsupportedForms(invalid_forms);
         if (!invalid_forms.empty()) {
           StreamString error;
-          error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : "");
+          error.Printf("unsupported DW_FORM value%s:",
+                       invalid_forms.size() > 1 ? "s" : "");
           for (auto form : invalid_forms)
             error.Printf(" %#x", form);
           m_objfile_sp->GetModule()->ReportWarning(
@@ -786,19 +847,9 @@ size_t SymbolFileDWARF::ParseFunctions(C
 
 bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
                                         FileSpecList &support_files) {
-  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
-  if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) {
-    const dw_offset_t stmt_list = unit->GetLineTableOffset();
-    if (stmt_list != DW_INVALID_OFFSET) {
-      // All file indexes in DWARF are one based and a file of index zero is
-      // supposed to be the compile unit itself.
-      support_files.Append(comp_unit);
-      return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(),
-                                               m_context.getOrLoadLineData(),
-                                               stmt_list, support_files, unit);
-    }
-  }
-  return false;
+  if (!comp_unit.GetLineTable())
+    ParseLineTable(comp_unit);
+  return true;
 }
 
 FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) {
@@ -827,10 +878,20 @@ SymbolFileDWARF::GetTypeUnitSupportFiles
   auto iter_bool = m_type_unit_support_files.try_emplace(offset);
   FileSpecList &list = iter_bool.first->second;
   if (iter_bool.second) {
-    list.EmplaceBack();
-    DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(),
-                                      m_context.getOrLoadLineData(), offset,
-                                      list, &tu);
+    uint64_t line_table_offset = offset;
+    llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM();
+    llvm::DWARFContext &ctx = m_context.GetAsLLVM();
+    llvm::DWARFDebugLine::Prologue prologue;
+    llvm::Error error = prologue.parse(data, &line_table_offset, ctx);
+    if (error) {
+      Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+      LLDB_LOG_ERROR(log, std::move(error),
+                     "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
+                     "the line table prologue");
+    } else {
+      list =
+          ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), prologue);
+    }
   }
   return list;
 }
@@ -895,102 +956,63 @@ bool SymbolFileDWARF::ParseImportedModul
   return true;
 }
 
-struct ParseDWARFLineTableCallbackInfo {
-  LineTable *line_table;
-  std::unique_ptr<LineSequence> sequence_up;
-  lldb::addr_t addr_mask;
-};
-
-// ParseStatementTableCallback
-static void ParseDWARFLineTableCallback(dw_offset_t offset,
-                                        const DWARFDebugLine::State &state,
-                                        void *userData) {
-  if (state.row == DWARFDebugLine::State::StartParsingLineTable) {
-    // Just started parsing the line table
-  } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) {
-    // Done parsing line table, nothing to do for the cleanup
-  } else {
-    ParseDWARFLineTableCallbackInfo *info =
-        (ParseDWARFLineTableCallbackInfo *)userData;
-    LineTable *line_table = info->line_table;
-
-    // If this is our first time here, we need to create a sequence container.
-    if (!info->sequence_up) {
-      info->sequence_up.reset(line_table->CreateLineSequenceContainer());
-      assert(info->sequence_up.get());
-    }
-    line_table->AppendLineEntryToSequence(
-        info->sequence_up.get(), state.address & info->addr_mask, state.line,
-        state.column, state.file, state.is_stmt, state.basic_block,
-        state.prologue_end, state.epilogue_begin, state.end_sequence);
-    if (state.end_sequence) {
-      // First, put the current sequence into the line table.
-      line_table->InsertSequence(info->sequence_up.get());
-      // Then, empty it to prepare for the next sequence.
-      info->sequence_up->Clear();
-    }
-  }
-}
-
 bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   if (comp_unit.GetLineTable() != nullptr)
     return true;
 
   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
-  if (dwarf_cu) {
-    const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
-    if (dwarf_cu_die) {
-      const dw_offset_t cu_line_offset =
-          dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list,
-                                                   DW_INVALID_OFFSET);
-      if (cu_line_offset != DW_INVALID_OFFSET) {
-        std::unique_ptr<LineTable> line_table_up(new LineTable(&comp_unit));
-        if (line_table_up) {
-          ParseDWARFLineTableCallbackInfo info;
-          info.line_table = line_table_up.get();
-
-          /*
-           * MIPS:
-           * The SymbolContext may not have a valid target, thus we may not be
-           * able
-           * to call Address::GetOpcodeLoadAddress() which would clear the bit
-           * #0
-           * for MIPS. Use ArchSpec to clear the bit #0.
-          */
-          switch (GetObjectFile()->GetArchitecture().GetMachine()) {
-          case llvm::Triple::mips:
-          case llvm::Triple::mipsel:
-          case llvm::Triple::mips64:
-          case llvm::Triple::mips64el:
-            info.addr_mask = ~((lldb::addr_t)1);
-            break;
-          default:
-            info.addr_mask = ~((lldb::addr_t)0);
-            break;
-          }
+  if (!dwarf_cu)
+    return false;
 
-          lldb::offset_t offset = cu_line_offset;
-          DWARFDebugLine::ParseStatementTable(
-              m_context.getOrLoadLineData(), &offset,
-              ParseDWARFLineTableCallback, &info, dwarf_cu);
-          SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
-          if (debug_map_symfile) {
-            // We have an object file that has a line table with addresses that
-            // are not linked. We need to link the line table and convert the
-            // addresses that are relative to the .o file into addresses for
-            // the main executable.
-            comp_unit.SetLineTable(
-                debug_map_symfile->LinkOSOLineTable(this, line_table_up.get()));
-          } else {
-            comp_unit.SetLineTable(line_table_up.release());
-            return true;
-          }
-        }
-      }
+  const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
+  if (!dwarf_cu_die)
+    return false;
+
+  const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(
+      DW_AT_stmt_list, DW_INVALID_OFFSET);
+  if (cu_line_offset == DW_INVALID_OFFSET)
+    return false;
+
+  llvm::DWARFDebugLine line;
+  const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable(
+      m_context, line, cu_line_offset, dwarf_cu->GetOffset());
+
+  if (!line_table)
+    return false;
+
+  // FIXME: Rather than parsing the whole line table and then copying it over
+  // into LLDB, we should explore using a callback to populate the line table
+  // while we parse to reduce memory usage.
+  std::unique_ptr<LineTable> line_table_up =
+      llvm::make_unique<LineTable>(&comp_unit);
+  LineSequence *sequence = line_table_up->CreateLineSequenceContainer();
+  for (auto &row : line_table->Rows) {
+    line_table_up->AppendLineEntryToSequence(
+        sequence, row.Address.Address, row.Line, row.Column, row.File,
+        row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
+        row.EndSequence);
+    if (row.EndSequence) {
+      line_table_up->InsertSequence(sequence);
+      sequence = line_table_up->CreateLineSequenceContainer();
     }
   }
-  return false;
+
+  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) {
+    // We have an object file that has a line table with addresses that are not
+    // linked. We need to link the line table and convert the addresses that
+    // are relative to the .o file into addresses for the main executable.
+    comp_unit.SetLineTable(
+        debug_map_symfile->LinkOSOLineTable(this, line_table_up.get()));
+  } else {
+    comp_unit.SetLineTable(line_table_up.release());
+  }
+
+  comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
+      comp_unit.GetModule(), line_table->Prologue,
+      dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit)));
+
+  return true;
 }
 
 lldb_private::DebugMacrosSP
@@ -1108,7 +1130,7 @@ size_t SymbolFileDWARF::ParseBlocksRecur
                 "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64
                 ") which has a base that is less than the function's low PC "
                 "0x%" PRIx64 ". Please file a bug and attach the file at the "
-                             "start of this error message",
+                "start of this error message",
                 block->GetID(), range_base, range.GetRangeEnd(),
                 subprogram_low_pc);
           }
@@ -1333,8 +1355,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(co
           // Get the type, which could be a forward declaration
           if (log)
             GetObjectFile()->GetModule()->LogMessage(
-                log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' "
-                     "resolve parent forward type for 0x%8.8x",
+                log,
+                "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' "
+                "resolve parent forward type for 0x%8.8x",
                 die.GetOffset(), die.GetTagAsCString(), die.GetName(),
                 decl_ctx_die.GetOffset());
         } break;
@@ -1496,7 +1519,6 @@ SymbolFileDWARF::GetDIE(const DIERef &di
         ->GetDIE(die_ref);
   }
 
-
   DWARFDebugInfo *debug_info = DebugInfo();
   if (debug_info)
     return debug_info->GetDIE(die_ref);
@@ -2230,8 +2252,9 @@ uint32_t SymbolFileDWARF::FindFunctions(
 
   if (log) {
     GetObjectFile()->GetModule()->LogMessage(
-        log, "SymbolFileDWARF::FindFunctions (name=\"%s\", "
-             "name_type_mask=0x%x, append=%u, sc_list)",
+        log,
+        "SymbolFileDWARF::FindFunctions (name=\"%s\", "
+        "name_type_mask=0x%x, append=%u, sc_list)",
         name.GetCString(), name_type_mask, append);
   }
 
@@ -2259,7 +2282,7 @@ uint32_t SymbolFileDWARF::FindFunctions(
 
   std::vector<DWARFDIE> dies;
   m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies);
-  for (const DWARFDIE &die: dies) {
+  for (const DWARFDIE &die : dies) {
     if (resolved_dies.insert(die.GetDIE()).second)
       ResolveFunction(die, include_inlines, sc_list);
   }
@@ -2269,9 +2292,10 @@ uint32_t SymbolFileDWARF::FindFunctions(
 
   if (log && num_matches > 0) {
     GetObjectFile()->GetModule()->LogMessage(
-        log, "SymbolFileDWARF::FindFunctions (name=\"%s\", "
-             "name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => "
-             "%u",
+        log,
+        "SymbolFileDWARF::FindFunctions (name=\"%s\", "
+        "name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => "
+        "%u",
         name.GetCString(), name_type_mask, include_inlines, append,
         num_matches);
   }
@@ -2351,8 +2375,8 @@ void SymbolFileDWARF::GetMangledNamesFor
 }
 
 uint32_t SymbolFileDWARF::FindTypes(
-    ConstString name, const CompilerDeclContext *parent_decl_ctx,
-    bool append, uint32_t max_matches,
+    ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append,
+    uint32_t max_matches,
     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
     TypeMap &types) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
@@ -2375,14 +2399,16 @@ uint32_t SymbolFileDWARF::FindTypes(
   if (log) {
     if (parent_decl_ctx)
       GetObjectFile()->GetModule()->LogMessage(
-          log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
-               "%p (\"%s\"), append=%u, max_matches=%u, type_list)",
+          log,
+          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
+          "%p (\"%s\"), append=%u, max_matches=%u, type_list)",
           name.GetCString(), static_cast<const void *>(parent_decl_ctx),
           parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches);
     else
       GetObjectFile()->GetModule()->LogMessage(
-          log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
-               "NULL, append=%u, max_matches=%u, type_list)",
+          log,
+          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
+          "NULL, append=%u, max_matches=%u, type_list)",
           name.GetCString(), append, max_matches);
   }
 
@@ -2419,15 +2445,17 @@ uint32_t SymbolFileDWARF::FindTypes(
     if (log && num_matches) {
       if (parent_decl_ctx) {
         GetObjectFile()->GetModule()->LogMessage(
-            log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
-                 "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",
+            log,
+            "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
+            "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",
             name.GetCString(), static_cast<const void *>(parent_decl_ctx),
             parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches,
             num_matches);
       } else {
         GetObjectFile()->GetModule()->LogMessage(
-            log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
-                 "= NULL, append=%u, max_matches=%u, type_list) => %u",
+            log,
+            "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
+            "= NULL, append=%u, max_matches=%u, type_list) => %u",
             name.GetCString(), append, max_matches, num_matches);
       }
     }
@@ -2548,8 +2576,9 @@ SymbolFileDWARF::FindNamespace(ConstStri
   }
   if (log && namespace_decl_ctx) {
     GetObjectFile()->GetModule()->LogMessage(
-        log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => "
-             "CompilerDeclContext(%p/%p) \"%s\"",
+        log,
+        "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => "
+        "CompilerDeclContext(%p/%p) \"%s\"",
         name.GetCString(),
         static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()),
         static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()),
@@ -2644,8 +2673,7 @@ SymbolFileDWARF::GetDeclContextDIEContai
   return DWARFDIE();
 }
 
-Symbol *
-SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) {
+Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) {
   Symbol *objc_class_symbol = nullptr;
   if (m_objfile_sp) {
     Symtab *symtab = m_objfile_sp->GetSymtab();
@@ -2665,8 +2693,7 @@ SymbolFileDWARF::GetObjCClassSymbol(Cons
 // worry about the debug map
 // DWARF file
 // if we are doing darwin DWARF in .o file debugging.
-bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(
-    DWARFUnit *cu) {
+bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) {
   if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
     m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
     if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
@@ -2693,8 +2720,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APP
 // This function can be used when a DIE is found that is a forward declaration
 // DIE and we want to try and find a type that has the complete definition.
 TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
-    const DWARFDIE &die, ConstString type_name,
-    bool must_be_implementation) {
+    const DWARFDIE &die, ConstString type_name, bool must_be_implementation) {
 
   TypeSP type_sp;
 
@@ -2861,8 +2887,9 @@ TypeSP SymbolFileDWARF::FindDefinitionTy
                                             DWARF_LOG_LOOKUPS));
       if (log) {
         GetObjectFile()->GetModule()->LogMessage(
-            log, "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%"
-                 "s, qualified-name='%s')",
+            log,
+            "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%"
+            "s, qualified-name='%s')",
             DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
             dwarf_decl_ctx.GetQualifiedName());
       }
@@ -2936,9 +2963,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTy
 
               if (log) {
                 GetObjectFile()->GetModule()->LogMessage(
-                    log, "SymbolFileDWARF::"
-                         "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
-                         "qualified-name='%s') trying die=0x%8.8x (%s)",
+                    log,
+                    "SymbolFileDWARF::"
+                    "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
+                    "qualified-name='%s') trying die=0x%8.8x (%s)",
                     DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
                     dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(),
                     type_dwarf_decl_ctx.GetQualifiedName());
@@ -2957,9 +2985,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTy
                 std::string qualified_name;
                 type_die.GetQualifiedName(qualified_name);
                 GetObjectFile()->GetModule()->LogMessage(
-                    log, "SymbolFileDWARF::"
-                         "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
-                         "qualified-name='%s') ignoring die=0x%8.8x (%s)",
+                    log,
+                    "SymbolFileDWARF::"
+                    "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
+                    "qualified-name='%s') ignoring die=0x%8.8x (%s)",
                     DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
                     dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(),
                     qualified_name.c_str());
@@ -3598,8 +3627,7 @@ size_t SymbolFileDWARF::ParseVariables(c
             } else {
               GetObjectFile()->GetModule()->ReportError(
                   "parent 0x%8.8" PRIx64 " %s with no valid compile unit in "
-                                         "symbol context for 0x%8.8" PRIx64
-                  " %s.\n",
+                  "symbol context for 0x%8.8" PRIx64 " %s.\n",
                   sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(),
                   orig_die.GetID(), orig_die.GetTagAsCString());
             }
@@ -3743,7 +3771,8 @@ void SymbolFileDWARF::DumpClangAST(Strea
   auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
   if (!ts_or_err)
     return;
-  ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get());
+  ClangASTContext *clang =
+      llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get());
   if (!clang)
     return;
   clang->Dump(s);

Modified: lldb/trunk/source/Symbol/CompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CompileUnit.cpp?rev=368742&r1=368741&r2=368742&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CompileUnit.cpp (original)
+++ lldb/trunk/source/Symbol/CompileUnit.cpp Tue Aug 13 12:51:51 2019
@@ -156,6 +156,10 @@ void CompileUnit::SetLineTable(LineTable
   m_line_table_up.reset(line_table);
 }
 
+void CompileUnit::SetSupportFiles(const FileSpecList &support_files) {
+  m_support_files = support_files;
+}
+
 DebugMacros *CompileUnit::GetDebugMacros() {
   if (m_debug_macros_sp.get() == nullptr) {
     if (m_flags.IsClear(flagsParsedDebugMacros)) {




More information about the lldb-commits mailing list