// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/dwarf.h"

#include "vm/code_comments.h"
#include "vm/code_descriptors.h"
#include "vm/elf.h"
#include "vm/image_snapshot.h"
#include "vm/object_store.h"

namespace dart {

#if defined(DART_PRECOMPILER)

DEFINE_FLAG(bool,
            resolve_dwarf_paths,
            false,
            "Resolve script URIs to absolute or relative file paths in DWARF");

DEFINE_FLAG(charp,
            write_code_comments_as_synthetic_source_to,
            nullptr,
            "Print comments associated with instructions into the given file");

class DwarfPosition {
 public:
  DwarfPosition(int32_t line, int32_t column) : line_(line), column_(column) {
    // Should only have no line information if also no column information.
    ASSERT(line_ > kNoLine || column_ <= kNoColumn);
  }
  // CodeSourceMaps start the line and column registers at -1, not at 0, and
  // the arguments passed to ChangePosition are retrieved from CodeSourceMaps.
  explicit DwarfPosition(int32_t line) : DwarfPosition(line, -1) {}
  constexpr DwarfPosition() : line_(-1), column_(-1) {}

  // The DWARF standard uses 0 to denote missing line or column
  // information.
  static constexpr int32_t kNoLine = 0;
  static constexpr int32_t kNoColumn = 0;

  int32_t line() const { return line_ > kNoLine ? line_ : kNoLine; }
  int32_t column() const { return column_ > kNoColumn ? column_ : kNoColumn; }

  // Adjusts the contents given the arguments to a ChangePosition instruction
  // from CodeSourceMaps.
  void ChangePosition(int32_t line_delta, int32_t new_column) {
    line_ = Utils::AddWithWrapAround(line_, line_delta);
    column_ = new_column;
  }

 private:
  int32_t line_;
  int32_t column_;
};

static constexpr auto kNoDwarfPositionInfo = DwarfPosition();

class InliningNode : public ZoneAllocated {
 public:
  InliningNode(const Function& function,
               const DwarfPosition& position,
               int32_t start_pc_offset)
      : function(function),
        position(position),
        start_pc_offset(start_pc_offset),
        end_pc_offset(-1),
        children_head(nullptr),
        children_tail(nullptr),
        children_next(nullptr) {
    ASSERT(!function.IsNull());
    DEBUG_ASSERT(function.IsNotTemporaryScopedHandle());
  }

  void AppendChild(InliningNode* child) {
    if (children_tail == nullptr) {
      children_head = children_tail = child;
    } else {
      children_tail->children_next = child;
      children_tail = child;
    }
  }

  const Function& function;
  DwarfPosition position;
  int32_t start_pc_offset;
  int32_t end_pc_offset;
  InliningNode* children_head;
  InliningNode* children_tail;
  InliningNode* children_next;
};

Dwarf::Dwarf(Zone* zone, const Trie<const char>* deobfuscation_trie)
    : zone_(zone),
      deobfuscation_trie_(deobfuscation_trie),
      codes_(zone, 1024),
      code_to_label_(zone),
      functions_(zone, 1024),
      function_to_index_(zone),
      scripts_(zone, 1024),
      script_to_index_(zone) {}

void Dwarf::AddCode(const Code& orig_code, intptr_t label) {
  ASSERT(!orig_code.IsNull());
  ASSERT(label > 0);

  if (auto const old_pair = code_to_label_.Lookup(&orig_code)) {
    // Dwarf objects can be shared, so we may get the same information for a
    // given code object in different calls. In DEBUG mode, make sure the
    // information is the same before returning.
    ASSERT_EQUAL(label, old_pair->value);
    return;
  }

  // Generate an appropriately zoned ZoneHandle for storing.
  const auto& code = Code::ZoneHandle(zone_, orig_code.ptr());
  codes_.Add(&code);
  // Currently assumes the name has the same lifetime as the Zone of the
  // Dwarf object (which is currently true).  Otherwise, need to copy.
  code_to_label_.Insert({&code, label});

  if (code.IsFunctionCode() && !code.IsUnknownDartCode()) {
    const Function& function = Function::Handle(zone_, code.function());
    AddFunction(function);
  }
  const Array& inline_functions =
      Array::Handle(zone_, code.inlined_id_to_function());
  if (!inline_functions.IsNull()) {
    Function& function = Function::Handle(zone_);
    for (intptr_t i = 0; i < inline_functions.Length(); i++) {
      function ^= inline_functions.At(i);
      AddFunction(function);
    }
  }
}

intptr_t Dwarf::AddFunction(const Function& function) {
  RELEASE_ASSERT(!function.IsNull());
  FunctionIndexPair* pair = function_to_index_.Lookup(&function);
  if (pair != nullptr) {
    return pair->index_;
  }
  intptr_t index = functions_.length();
  const Function& zone_func = Function::ZoneHandle(zone_, function.ptr());
  function_to_index_.Insert(FunctionIndexPair(&zone_func, index));
  functions_.Add(&zone_func);
  const Script& script = Script::Handle(zone_, function.script());
  AddScript(script);
  return index;
}

intptr_t Dwarf::AddScript(const Script& script) {
  RELEASE_ASSERT(!script.IsNull());
  ScriptIndexPair* pair = script_to_index_.Lookup(&script);
  if (pair != nullptr) {
    return pair->index_;
  }
  // DWARF file numbers start from 1.
  intptr_t index = scripts_.length() + 1;
  const Script& zone_script = Script::ZoneHandle(zone_, script.ptr());
  script_to_index_.Insert(ScriptIndexPair(&zone_script, index));
  scripts_.Add(&zone_script);
  return index;
}

intptr_t Dwarf::LookupFunction(const Function& function) {
  RELEASE_ASSERT(!function.IsNull());
  FunctionIndexPair* pair = function_to_index_.Lookup(&function);
  if (pair == nullptr) {
    FATAL("Function detected too late during DWARF generation: %s",
          function.ToCString());
  }
  return pair->index_;
}

intptr_t Dwarf::LookupScript(const Script& script) {
  RELEASE_ASSERT(!script.IsNull());
  ScriptIndexPair* pair = script_to_index_.Lookup(&script);
  if (pair == nullptr) {
    FATAL("Script detected too late during DWARF generation: %s",
          script.ToCString());
  }
  return pair->index_;
}

void Dwarf::WriteAbbreviations(DwarfWriteStream* stream) {
  // Dwarf data mostly takes the form of a tree, whose nodes are called
  // DIEs. Each DIE begins with an abbreviation code, and the abbreviation
  // describes the attributes of that DIE and their representation.

  stream->uleb128(kCompilationUnit);     // Abbrev code.
  stream->uleb128(DW_TAG_compile_unit);  // Type.
  stream->u1(DW_CHILDREN_yes);
  stream->uleb128(DW_AT_name);  // Start of attributes.
  stream->uleb128(DW_FORM_string);
  stream->uleb128(DW_AT_producer);
  stream->uleb128(DW_FORM_string);
  stream->uleb128(DW_AT_comp_dir);
  stream->uleb128(DW_FORM_string);
  stream->uleb128(DW_AT_low_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_high_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_stmt_list);
  stream->uleb128(DW_FORM_sec_offset);
  stream->uleb128(0);
  stream->uleb128(0);  // End of attributes.

  stream->uleb128(kAbstractFunction);  // Abbrev code.
  stream->uleb128(DW_TAG_subprogram);  // Type.
  stream->u1(DW_CHILDREN_yes);
  stream->uleb128(DW_AT_name);  // Start of attributes.
  stream->uleb128(DW_FORM_string);
  stream->uleb128(DW_AT_decl_file);
  stream->uleb128(DW_FORM_udata);
  stream->uleb128(DW_AT_inline);
  stream->uleb128(DW_FORM_udata);
  stream->uleb128(0);
  stream->uleb128(0);  // End of attributes.

  stream->uleb128(kConcreteFunction);  // Abbrev code.
  stream->uleb128(DW_TAG_subprogram);  // Type.
  stream->u1(DW_CHILDREN_yes);
  stream->uleb128(DW_AT_abstract_origin);  // Start of attributes.
  stream->uleb128(DW_FORM_ref4);
  stream->uleb128(DW_AT_low_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_high_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_artificial);
  stream->uleb128(DW_FORM_flag);
  stream->uleb128(0);
  stream->uleb128(0);  // End of attributes.

  stream->uleb128(kInlinedFunction);           // Abbrev code.
  stream->uleb128(DW_TAG_inlined_subroutine);  // Type.
  stream->u1(DW_CHILDREN_yes);
  stream->uleb128(DW_AT_abstract_origin);  // Start of attributes.
  stream->uleb128(DW_FORM_ref4);
  stream->uleb128(DW_AT_low_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_high_pc);
  stream->uleb128(DW_FORM_addr);
  stream->uleb128(DW_AT_call_file);
  stream->uleb128(DW_FORM_udata);
  stream->uleb128(DW_AT_call_line);
  stream->uleb128(DW_FORM_udata);
  stream->uleb128(DW_AT_call_column);
  stream->uleb128(DW_FORM_udata);
  stream->uleb128(DW_AT_artificial);
  stream->uleb128(DW_FORM_flag);
  stream->uleb128(0);
  stream->uleb128(0);  // End of attributes.

  stream->uleb128(0);  // End of abbreviations.
}

void Dwarf::WriteDebugInfo(DwarfWriteStream* stream) {
  // 7.5.1.1 Compilation Unit Header

  // Unit length.
  stream->WritePrefixedLength("cu", [&]() {
    stream->u2(2);                            // DWARF version 2
    stream->u4(0);                            // debug_abbrev_offset
    stream->u1(compiler::target::kWordSize);  // address_size

    // Compilation Unit DIE. We describe the entire Dart program as a single
    // compilation unit. Note we write attributes in the same order we declared
    // them in our abbreviation above in WriteAbbreviations.
    stream->uleb128(kCompilationUnit);
    const Library& root_library = Library::Handle(
        zone_, IsolateGroup::Current()->object_store()->root_library());
    const String& root_uri = String::Handle(zone_, root_library.url());
    stream->string(root_uri.ToCString());  // DW_AT_name
    stream->string("Dart VM");             // DW_AT_producer
    stream->string("");                    // DW_AT_comp_dir

    // DW_AT_low_pc
    // The lowest instruction address in this object file that is part of our
    // compilation unit. Dwarf consumers use this to quickly decide which
    // compilation unit DIE to consult for a given pc.
    auto const isolate_instructions_label = ImageWriter::SectionLabel(
        ImageWriter::ProgramSection::Text, /*vm=*/false);
    stream->OffsetFromSymbol(isolate_instructions_label, 0);

    // DW_AT_high_pc
    // The highest instruction address in this object file that is part of our
    // compilation unit. Dwarf consumers use this to quickly decide which
    // compilation unit DIE to consult for a given pc.
    if (codes_.is_empty()) {
      // No code objects in this program, so set high_pc to same as low_pc.
      stream->OffsetFromSymbol(isolate_instructions_label, 0);
    } else {
      const Code& last_code = *codes_.Last();
      auto const last_code_label = code_to_label_.LookupValue(&last_code);
      ASSERT(last_code_label > 0);
      stream->OffsetFromSymbol(last_code_label, last_code.Size());
    }

    // DW_AT_stmt_list (offset into .debug_line)
    // Indicates which line number program is associated with this compilation
    // unit. We only emit a single line number program.
    stream->u4(0);

    WriteAbstractFunctions(stream);
    WriteConcreteFunctions(stream);

    stream->uleb128(0);  // End of children.

    stream->uleb128(0);  // End of entries.
  });
}

void Dwarf::WriteAbstractFunctions(DwarfWriteStream* stream) {
  Script& script = Script::Handle(zone_);
  String& name = String::Handle(zone_);
  stream->InitializeAbstractOrigins(functions_.length());
  // By the point we're creating DWARF information, scripts have already lost
  // their token stream and we can't look up their line number or column
  // information, hence the lack of DW_AT_decl_line and DW_AT_decl_column.
  for (intptr_t i = 0; i < functions_.length(); i++) {
    const Function& function = *(functions_[i]);
    name = function.QualifiedUserVisibleName();
    script = function.script();
    const intptr_t file = LookupScript(script);
    auto const name_cstr =
        ImageWriter::Deobfuscate(zone_, deobfuscation_trie_, name.ToCString());

    stream->RegisterAbstractOrigin(i);
    stream->uleb128(kAbstractFunction);
    stream->string(name_cstr);        // DW_AT_name
    stream->uleb128(file);            // DW_AT_decl_file
    stream->uleb128(DW_INL_inlined);  // DW_AT_inline
    stream->uleb128(0);               // End of children.
  }
}

void Dwarf::WriteConcreteFunctions(DwarfWriteStream* stream) {
  Function& function = Function::Handle(zone_);
  Script& script = Script::Handle(zone_);
  for (intptr_t i = 0; i < codes_.length(); i++) {
    const Code& code = *(codes_[i]);
    RELEASE_ASSERT(!code.IsNull());
    if (!code.IsFunctionCode() || code.IsUnknownDartCode()) {
      continue;
    }

    function = code.function();
    intptr_t function_index = LookupFunction(function);
    script = function.script();
    intptr_t label = code_to_label_.LookupValue(&code);
    ASSERT(label > 0);

    stream->uleb128(kConcreteFunction);
    // DW_AT_abstract_origin
    // References a node written above in WriteAbstractFunctions.
    stream->AbstractOrigin(function_index);

    // DW_AT_low_pc
    stream->OffsetFromSymbol(label, 0);
    // DW_AT_high_pc
    stream->OffsetFromSymbol(label, code.Size());
    // DW_AT_artificial
    stream->u1(function.is_visible() ? 0 : 1);

    InliningNode* node = ExpandInliningTree(code);
    if (node != nullptr) {
      for (InliningNode* child = node->children_head; child != nullptr;
           child = child->children_next) {
        WriteInliningNode(stream, child, label, script);
      }
    }

    stream->uleb128(0);  // End of children.
  }
}

// Our state machine encodes position metadata such that we don't know the
// end pc for an inlined function until it is popped, but DWARF DIEs encode
// it where the function is pushed. We expand the state transitions into
// an in-memory tree to do the conversion.
InliningNode* Dwarf::ExpandInliningTree(const Code& code) {
  const CodeSourceMap& map =
      CodeSourceMap::Handle(zone_, code.code_source_map());
  if (map.IsNull()) {
    return nullptr;
  }
  const Array& functions = Array::Handle(zone_, code.inlined_id_to_function());
  const Function& root_function = Function::ZoneHandle(zone_, code.function());
  if (root_function.IsNull()) {
    FATAL("Wherefore art thou functionless code, %s?\n", code.ToCString());
  }

  GrowableArray<InliningNode*> node_stack(zone_, 4);
  GrowableArray<DwarfPosition> token_positions(zone_, 4);

  NoSafepointScope no_safepoint;
  ReadStream stream(map.Data(), map.Length());

  int32_t current_pc_offset = 0;
  token_positions.Add(kNoDwarfPositionInfo);
  InliningNode* root_node =
      new (zone_) InliningNode(root_function, token_positions.Last(), 0);
  root_node->end_pc_offset = code.Size();
  node_stack.Add(root_node);

  while (stream.PendingBytes() > 0) {
    int32_t arg1;
    int32_t arg2 = -1;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg1, &arg2);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        DwarfPosition& pos = token_positions[token_positions.length() - 1];
        pos.ChangePosition(arg1, arg2);
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        current_pc_offset += arg1;
        if (arg1 == 0) {
          // This happens at the start of the function where we emit a special
          // kAdvancePC 0 instruction to record information about the function
          // itself. We need to advance current_pc_offset a bit to prevent
          // starting inlining interval directy at the start of the function
          // itself.
          current_pc_offset += 1;
        }
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        const Function& child_func =
            Function::ZoneHandle(zone_, Function::RawCast(functions.At(arg1)));
        InliningNode* child_node = new (zone_)
            InliningNode(child_func, token_positions.Last(), current_pc_offset);
        node_stack.Last()->AppendChild(child_node);
        node_stack.Add(child_node);
        token_positions.Add(kNoDwarfPositionInfo);
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        // We never pop the root function.
        ASSERT(node_stack.length() > 1);
        ASSERT(token_positions.length() > 1);
        node_stack.Last()->end_pc_offset = current_pc_offset;
        node_stack.RemoveLast();
        token_positions.RemoveLast();
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        break;
      }
      default:
        UNREACHABLE();
    }
  }

  while (node_stack.length() > 1) {
    node_stack.Last()->end_pc_offset = current_pc_offset;
    node_stack.RemoveLast();
    token_positions.RemoveLast();
  }
  ASSERT(node_stack[0] == root_node);
  return root_node;
}

void Dwarf::WriteInliningNode(DwarfWriteStream* stream,
                              InliningNode* node,
                              intptr_t root_label,
                              const Script& parent_script) {
  ASSERT(root_label > 0);
  intptr_t file = LookupScript(parent_script);
  intptr_t function_index = LookupFunction(node->function);
  const Script& script = Script::Handle(zone_, node->function.script());

  stream->uleb128(kInlinedFunction);
  // DW_AT_abstract_origin
  // References a node written above in WriteAbstractFunctions.
  stream->AbstractOrigin(function_index);

  // DW_AT_low_pc
  stream->OffsetFromSymbol(root_label, node->start_pc_offset);
  // DW_AT_high_pc
  stream->OffsetFromSymbol(root_label, node->end_pc_offset);
  // DW_AT_call_file
  stream->uleb128(file);

  // DW_AT_call_line
  stream->uleb128(node->position.line());
  // DW_AT_call_column
  stream->uleb128(node->position.column());
  // DW_AT_artificial
  stream->u1(node->function.is_visible() ? 0 : 1);

  for (InliningNode* child = node->children_head; child != nullptr;
       child = child->children_next) {
    WriteInliningNode(stream, child, root_label, script);
  }

  stream->uleb128(0);  // End of children.
}

// Helper class for tracking state of DWARF registers and emitting
// line number program commands to set these registers to the right
// state.
class LineNumberProgramWriter {
 public:
  explicit LineNumberProgramWriter(DwarfWriteStream* stream)
      : stream_(stream) {}

  void EmitRow(intptr_t file,
               intptr_t line,
               intptr_t column,
               intptr_t label,
               intptr_t pc_offset) {
    if (AddRow(file, line, column, label, pc_offset)) {
      // Address register must be updated from 0 before emitting an LNP row
      // (dartbug.com/41756).
      stream_->u1(Dwarf::DW_LNS_copy);
    }
  }

  // Associates the given file, line, and column information for the instruction
  // at the pc_offset into the instructions payload of the Code object with the
  // symbol asm_name. Returns whether any changes were made to the stream.
  DART_WARN_UNUSED_RESULT bool AddRow(intptr_t file,
                                      intptr_t line,
                                      intptr_t column,
                                      intptr_t label,
                                      intptr_t pc_offset) {
    ASSERT_EQUAL(end_sequence_, false);
    bool source_info_changed = false;
    // Note that files are 1-indexed.
    ASSERT(file >= 1);
    if (file != file_) {
      stream_->u1(Dwarf::DW_LNS_set_file);
      stream_->uleb128(file);
      file_ = file;
      source_info_changed = true;
    }
    ASSERT(line >= DwarfPosition::kNoLine);
    if (line != line_) {
      stream_->u1(Dwarf::DW_LNS_advance_line);
      stream_->sleb128(line - line_);
      line_ = line;
      source_info_changed = true;
    }
    ASSERT(column >= DwarfPosition::kNoColumn);
    if (column != column_) {
      stream_->u1(Dwarf::DW_LNS_set_column);
      stream_->uleb128(column);
      column_ = column;
      source_info_changed = true;
    }
    // If the file, line, and column information match that for the previous
    // AddRow call, no change is made to the stream. This is because all
    // addresses between two line number program rows inherit the source
    // information from the first.
    if (source_info_changed) {
      SetCurrentPosition(label, pc_offset);
    }
    return source_info_changed;
  }

  void MarkEnd() {
    ASSERT_EQUAL(end_sequence_, false);
    // End of contiguous machine code.
    stream_->u1(0);  // This is an extended opcode
    stream_->u1(1);  // that is 1 byte long
    stream_->u1(Dwarf::DW_LNE_end_sequence);
    end_sequence_ = true;
  }

  void MarkEnd(intptr_t label, intptr_t pc_offset) {
    ASSERT_EQUAL(end_sequence_, false);
    SetCurrentPosition(label, pc_offset);
    MarkEnd();
  }

 private:
  void SetCurrentPosition(intptr_t label, intptr_t pc_offset) {
    // Each LNP row is either in a different function from the previous row
    // or is at an increasing PC offset into the same function.
    ASSERT(label > 0);
    ASSERT(pc_offset >= 0);
    ASSERT(label_ != label || pc_offset > pc_offset_);
    if (label_ != label) {
      // Set the address register to the given offset into the new code payload.
      auto const instr_size = 1 + compiler::target::kWordSize;
      stream_->u1(0);           // This is an extended opcode
      stream_->u1(instr_size);  // that is 5 or 9 bytes long
      stream_->u1(Dwarf::DW_LNE_set_address);
      stream_->OffsetFromSymbol(label, pc_offset);
    } else {
      // Change the address register by the difference in the two offsets.
      stream_->u1(Dwarf::DW_LNS_advance_pc);
      stream_->uleb128(pc_offset - pc_offset_);
    }
    label_ = label;
    pc_offset_ = pc_offset;
  }

  DwarfWriteStream* const stream_;
  // The initial values for the line number program state machine registers
  // according to the DWARF standard.
  intptr_t pc_offset_ = 0;
  intptr_t file_ = 1;
  intptr_t line_ = 1;
  intptr_t column_ = 0;
  bool end_sequence_ = false;

  // Other info not stored in the state machine registers.
  intptr_t label_ = 0;
};

void Dwarf::WriteSyntheticLineNumberProgram(LineNumberProgramWriter* writer) {
  // We emit it last after all other scripts.
  const intptr_t comments_file_index = scripts_.length() + 1;

  auto file_open = Dart::file_open_callback();
  auto file_write = Dart::file_write_callback();
  auto file_close = Dart::file_close_callback();
  if ((file_open == nullptr) || (file_write == nullptr) ||
      (file_close == nullptr)) {
    OS::PrintErr("warning: Could not access file callbacks.");
    return;
  }

  TextBuffer comments_buffer(128 * KB);

  const char* filename = FLAG_write_code_comments_as_synthetic_source_to;
  void* comments_file = file_open(filename, /*write=*/true);
  if (comments_file == nullptr) {
    OS::PrintErr("warning: Failed to write code comments source: %s\n",
                 filename);
    return;
  }

  // Lines in DWARF are 1-indexed.
  intptr_t current_line = 1;

  for (intptr_t i = 0; i < codes_.length(); i++) {
    const Code& code = *(codes_[i]);
    auto const label = code_to_label_.LookupValue(&code);
    ASSERT(label > 0);

    auto& comments = code.comments();
    for (intptr_t i = 0, len = comments.Length(); i < len;) {
      intptr_t current_pc_offset = comments.PCOffsetAt(i);
      while (i < len && current_pc_offset == comments.PCOffsetAt(i)) {
        comments_buffer.AddString(comments.CommentAt(i));
        comments_buffer.AddChar('\n');
        current_line++;
        i++;
      }
      writer->EmitRow(comments_file_index, current_line - 1,
                      DwarfPosition::kNoColumn, label, current_pc_offset);
    }
  }

  file_write(comments_buffer.buffer(), comments_buffer.length(), comments_file);
  file_close(comments_file);
}

void Dwarf::WriteLineNumberProgramFromCodeSourceMaps(
    LineNumberProgramWriter* writer) {
  Function& root_function = Function::Handle(zone_);
  Script& script = Script::Handle(zone_);
  CodeSourceMap& map = CodeSourceMap::Handle(zone_);
  Array& functions = Array::Handle(zone_);
  GrowableArray<const Function*> function_stack(zone_, 8);
  GrowableArray<DwarfPosition> token_positions(zone_, 8);

  for (intptr_t i = 0; i < codes_.length(); i++) {
    const Code& code = *(codes_[i]);
    auto const label = code_to_label_.LookupValue(&code);
    ASSERT(label > 0);

    map = code.code_source_map();
    if (map.IsNull()) {
      continue;
    }
    root_function = code.function();
    functions = code.inlined_id_to_function();

    NoSafepointScope no_safepoint;
    ReadStream code_map_stream(map.Data(), map.Length());

    function_stack.Clear();
    token_positions.Clear();

    // CodeSourceMap might start in the following way:
    //
    //   ChangePosition function.token_pos()
    //   AdvancePC 0
    //   ChangePosition x
    //   AdvancePC y
    //
    // This entry is emitted to ensure correct symbolization of
    // function listener frames produced by async unwinding.
    // (See EmitFunctionEntrySourcePositionDescriptorIfNeeded).
    // Directly interpreting this sequence would cause us to emit
    // multiple with the same pc into line number table and different
    // position information. To avoid this will make an adjustment for
    // the second record we emit: if position x is a synthetic one we will
    // simply drop the second record, if position x is real then we will
    // emit row with a slightly adjusted PC (by 1 byte). This would not
    // affect symbolization (you can't have a call that is 1 byte long)
    // but will avoid line number table entries with the same PC.
    bool function_entry_position_was_emitted = false;

    int32_t current_pc_offset = 0;
    function_stack.Add(&root_function);
    token_positions.Add(kNoDwarfPositionInfo);

    while (code_map_stream.PendingBytes() > 0) {
      int32_t arg1;
      int32_t arg2 = -1;
      const uint8_t opcode =
          CodeSourceMapOps::Read(&code_map_stream, &arg1, &arg2);
      switch (opcode) {
        case CodeSourceMapOps::kChangePosition: {
          DwarfPosition& pos = token_positions[token_positions.length() - 1];
          pos.ChangePosition(arg1, arg2);
          break;
        }
        case CodeSourceMapOps::kAdvancePC: {
          // Emit a row for the previous PC value if the source location
          // changed since the last row was emitted.
          const Function& function = *(function_stack.Last());
          script = function.script();
          const intptr_t file = LookupScript(script);
          const intptr_t line = token_positions.Last().line();
          const intptr_t column = token_positions.Last().column();
          intptr_t pc_offset_adjustment = 0;
          bool should_emit = true;

          // If we are at the function entry and have already emitted a row
          // then adjust current_pc_offset to avoid duplicated entries.
          // See the comment below which explains why this code is here.
          if (current_pc_offset == 0 && function_entry_position_was_emitted) {
            pc_offset_adjustment = 1;
            // Ignore synthetic positions. Function entry position gives
            // more information anyway.
            should_emit = !(line == 0 && column == 0);
          }

          if (should_emit) {
            writer->EmitRow(file, line, column, label,
                            current_pc_offset + pc_offset_adjustment);
          }

          current_pc_offset += arg1;
          if (arg1 == 0) {  // Special case of AdvancePC 0.
            ASSERT(current_pc_offset == 0);
            ASSERT(!function_entry_position_was_emitted);
            function_entry_position_was_emitted = true;
          }
          break;
        }
        case CodeSourceMapOps::kPushFunction: {
          auto child_func =
              &Function::Handle(zone_, Function::RawCast(functions.At(arg1)));
          function_stack.Add(child_func);
          token_positions.Add(kNoDwarfPositionInfo);
          break;
        }
        case CodeSourceMapOps::kPopFunction: {
          // We never pop the root function.
          ASSERT(function_stack.length() > 1);
          ASSERT(token_positions.length() > 1);
          function_stack.RemoveLast();
          token_positions.RemoveLast();
          break;
        }
        case CodeSourceMapOps::kNullCheck: {
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
}

static constexpr char kResolvedFileRoot[] = "file:///";
static constexpr intptr_t kResolvedFileRootLen = sizeof(kResolvedFileRoot) - 1;
static constexpr char kResolvedFlutterRoot[] = "org-dartlang-sdk:///flutter/";
static constexpr intptr_t kResolvedFlutterRootLen =
    sizeof(kResolvedFlutterRoot) - 1;
static constexpr char kResolvedSdkRoot[] = "org-dartlang-sdk:///";
static constexpr intptr_t kResolvedSdkRootLen = sizeof(kResolvedSdkRoot) - 1;
static constexpr char kResolvedGoogle3Root[] = "google3:///";
static constexpr intptr_t kResolvedGoogle3RootLen =
    sizeof(kResolvedGoogle3Root) - 1;

static const char* ConvertResolvedURI(const char* str) {
  const intptr_t len = strlen(str);
  if (len > kResolvedFileRootLen &&
      strncmp(str, kResolvedFileRoot, kResolvedFileRootLen) == 0) {
#if defined(DART_HOST_OS_WINDOWS)
    return str + kResolvedFileRootLen;  // Strip off the entire prefix.
#else
    return str + kResolvedFileRootLen - 1;  // Leave a '/' on the front.
#endif
  }
  // Must do kResolvedFlutterRoot before kResolvedSdkRoot, since the latter is
  // a prefix of the former.
  if (len > kResolvedFlutterRootLen &&
      strncmp(str, kResolvedFlutterRoot, kResolvedFlutterRootLen) == 0) {
    return str + kResolvedFlutterRootLen;  // Strip off the entire prefix.
  }
  if (len > kResolvedSdkRootLen &&
      strncmp(str, kResolvedSdkRoot, kResolvedSdkRootLen) == 0) {
    return str + kResolvedSdkRootLen;  // Strip off the entire prefix.
  }
  if (len > kResolvedGoogle3RootLen &&
      strncmp(str, kResolvedGoogle3Root, kResolvedGoogle3RootLen) == 0) {
    return str + kResolvedGoogle3RootLen;  // Strip off the entire prefix.
  }
  return nullptr;
}

void Dwarf::WriteLineNumberProgram(DwarfWriteStream* stream) {
  // 6.2.4 The Line Number Program Header

  // 1. unit_length. This encoding implies 32-bit DWARF.
  stream->WritePrefixedLength("line", [&]() {
    stream->u2(2);  // 2. DWARF version 2

    // 3. header_length
    stream->WritePrefixedLength("lineheader", [&]() {
      stream->u1(1);   // 4. minimum_instruction_length
      stream->u1(1);   // 5. default_is_stmt (true for dsymutil compatibility).
      stream->u1(0);   // 6. line_base
      stream->u1(1);   // 7. line_range
      stream->u1(13);  // 8. opcode_base (12 standard opcodes in Dwarf 2)

      // 9. standard_opcode_lengths
      stream->u1(0);  // DW_LNS_copy, 0 operands
      stream->u1(1);  // DW_LNS_advance_pc, 1 operands
      stream->u1(1);  // DW_LNS_advance_list, 1 operands
      stream->u1(1);  // DW_LNS_set_file, 1 operands
      stream->u1(1);  // DW_LNS_set_column, 1 operands
      stream->u1(0);  // DW_LNS_negate_stmt, 0 operands
      stream->u1(0);  // DW_LNS_set_basic_block, 0 operands
      stream->u1(0);  // DW_LNS_const_add_pc, 0 operands
      stream->u1(1);  // DW_LNS_fixed_advance_pc, 1 operands
      stream->u1(0);  // DW_LNS_set_prolog_end, 0 operands
      stream->u1(0);  // DW_LNS_set_epilogue_begin, 0 operands
      stream->u1(1);  // DW_LNS_set_isa, 1 operands

      // 10. include_directories (sequence of path names)
      // We don't emit any because we use full paths below.
      stream->u1(0);

      // 11. file_names (sequence of file entries)
      String& uri = String::Handle(zone_);
      for (intptr_t i = 0; i < scripts_.length(); i++) {
        const Script& script = *(scripts_[i]);
        const char* uri_cstr = nullptr;
        if (FLAG_resolve_dwarf_paths) {
          uri = script.resolved_url();
          // Strictly enforce this to catch unresolvable cases.
          if (uri.IsNull()) {
            FATAL("no resolved URI for Script %s available",
                  script.ToCString());
          }
          // resolved_url is never obfuscated, so just convert the prefix.
          auto const orig_cstr = uri.ToCString();
          auto const converted_cstr = ConvertResolvedURI(orig_cstr);
          // Strictly enforce this to catch inconvertible cases.
          if (converted_cstr == nullptr) {
            FATAL("cannot convert resolved URI %s", orig_cstr);
          }
          uri_cstr = converted_cstr;
        } else {
          uri = script.url();
          ASSERT(!uri.IsNull());
          uri_cstr = ImageWriter::Deobfuscate(zone_, deobfuscation_trie_,
                                              uri.ToCString());
        }
        RELEASE_ASSERT(strlen(uri_cstr) != 0);

        stream->string(uri_cstr);  // NOLINT
        stream->uleb128(0);        // Include directory index.
        stream->uleb128(0);        // File modification time.
        stream->uleb128(0);        // File length.
      }
      if (FLAG_write_code_comments_as_synthetic_source_to != nullptr) {
        stream->string(  // NOLINT
            FLAG_write_code_comments_as_synthetic_source_to);
        stream->uleb128(0);  // Include directory index.
        stream->uleb128(0);  // File modification time.
        stream->uleb128(0);  // File length.
      }
      stream->u1(0);  // End of file names.
    });

    // 6.2.5 The Line Number Program
    LineNumberProgramWriter lnp_writer(stream);
    if (FLAG_write_code_comments_as_synthetic_source_to != nullptr) {
      WriteSyntheticLineNumberProgram(&lnp_writer);
    } else {
      WriteLineNumberProgramFromCodeSourceMaps(&lnp_writer);
    }

    // Advance pc to end of the compilation unit if not already there.
    if (codes_.length() != 0) {
      const intptr_t last_code_index = codes_.length() - 1;
      const Code& last_code = *(codes_[last_code_index]);
      const intptr_t last_pc_offset = last_code.Size();
      auto const last_label = code_to_label_.LookupValue(&last_code);
      ASSERT(last_label > 0);
      lnp_writer.MarkEnd(last_label, last_pc_offset);
    } else {
      lnp_writer.MarkEnd();
    }
  });
}

#endif  // DART_PRECOMPILER

}  // namespace dart
