// 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(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_ > 0 || column_ <= 0);
  }
  explicit DwarfPosition(int32_t line) : DwarfPosition(line, -1) {}
  constexpr DwarfPosition() : line_(-1), column_(-1) {}

  int32_t line() const { return line_; }
  int32_t column() const { return 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(NULL),
        children_tail(NULL),
        children_next(NULL) {
    RELEASE_ASSERT(!function.IsNull());
    RELEASE_ASSERT(function.IsNotTemporaryScopedHandle());
  }

  void AppendChild(InliningNode* child) {
    if (children_tail == NULL) {
      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;
};

template <typename T>
Trie<T>* Trie<T>::AddString(Zone* zone,
                            Trie<T>* trie,
                            const char* key,
                            const T* value) {
  ASSERT(key != nullptr);
  if (trie == nullptr) {
    trie = new (zone) Trie<T>();
  }
  if (*key == '\0') {
    ASSERT(trie->value_ == nullptr);
    trie->value_ = value;
  } else {
    auto const index = ChildIndex(*key);
    ASSERT(index >= 0 && index < kNumValidChars);
    trie->children_[index] =
        AddString(zone, trie->children_[index], key + 1, value);
  }

  return trie;
}

template <typename T>
const T* Trie<T>::Lookup(const Trie<T>* trie, const char* key, intptr_t* end) {
  intptr_t i = 0;
  for (; key[i] != '\0'; i++) {
    auto const index = ChildIndex(key[i]);
    ASSERT(index < kNumValidChars);
    if (index < 0) {
      if (end == nullptr) return nullptr;
      break;
    }
    // Still find the longest valid trie prefix when no stored value.
    if (trie == nullptr) continue;
    trie = trie->children_[index];
  }
  if (end != nullptr) {
    *end = i;
  }
  if (trie == nullptr) return nullptr;
  return trie->value_;
}

Dwarf::Dwarf(Zone* zone)
    : zone_(zone),
      reverse_obfuscation_trie_(CreateReverseObfuscationTrie(zone)),
      codes_(zone, 1024),
      code_to_name_(zone),
      functions_(zone, 1024),
      function_to_index_(zone),
      scripts_(zone, 1024),
      script_to_index_(zone),
      temp_(0) {}

void Dwarf::AddCode(const Code& orig_code, const char* name) {
  ASSERT(!orig_code.IsNull());
  ASSERT(name != nullptr);

  if (auto const old_pair = code_to_name_.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(old_pair->value != nullptr);
    ASSERT_EQUAL(strcmp(old_pair->value, name), 0);
    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_name_.Insert({&code, name});

  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 != NULL) {
    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 != NULL) {
    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 == NULL) {
    FATAL1("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 == NULL) {
    FATAL1("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(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(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.
  auto const cu_prefix = "cu";
  intptr_t cu_start;
  intptr_t cu_size_fixup = stream->ReserveSize(cu_prefix, &cu_start);

  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.
  stream->OffsetFromSymbol(kIsolateSnapshotInstructionsAsmSymbol, 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(kIsolateSnapshotInstructionsAsmSymbol, 0);
  } else {
    const Code& last_code = *codes_.Last();
    auto const last_code_name = code_to_name_.LookupValue(&last_code);
    ASSERT(last_code_name != nullptr);
    stream->OffsetFromSymbol(last_code_name, 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.
  stream->SetSize(cu_size_fixup, cu_prefix, cu_start);
}

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 = Deobfuscate(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();
    const char* asm_name = code_to_name_.LookupValue(&code);
    ASSERT(asm_name != nullptr);

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

    // DW_AT_low_pc
    stream->OffsetFromSymbol(asm_name, 0);
    // DW_AT_high_pc
    stream->OffsetFromSymbol(asm_name, code.Size());

    InliningNode* node = ExpandInliningTree(code);
    if (node != NULL) {
      for (InliningNode* child = node->children_head; child != NULL;
           child = child->children_next) {
        WriteInliningNode(stream, child, asm_name, 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 NULL;
  }
  const Array& functions = Array::Handle(zone_, code.inlined_id_to_function());
  const Function& root_function = Function::ZoneHandle(zone_, code.function());
  if (root_function.IsNull()) {
    FATAL1("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: {
        const DwarfPosition& old_pos =
            token_positions[token_positions.length() - 1];
        token_positions[token_positions.length() - 1] =
            DwarfPosition(Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        current_pc_offset += arg1;
        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,
                              const char* root_asm_name,
                              const Script& parent_script) {
  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_asm_name, node->start_pc_offset);
  // DW_AT_high_pc
  stream->OffsetFromSymbol(root_asm_name, node->end_pc_offset);
  // DW_AT_call_file
  stream->uleb128(file);

  // The DWARF standard uses 0 to denote missing line or column information.

  // DW_AT_call_line
  stream->uleb128(node->position.line() < 0 ? 0 : node->position.line());
  // DW_at_call_column
  stream->uleb128(node->position.column() < 0 ? 0 : node->position.column());

  for (InliningNode* child = node->children_head; child != NULL;
       child = child->children_next) {
    WriteInliningNode(stream, child, root_asm_name, 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 SetFile(intptr_t file) {
    if (file != file_) {
      stream_->u1(Dwarf::DW_LNS_set_file);
      stream_->uleb128(file);
      file_ = file;
    }
  }

  void SetLine(intptr_t line) {
    if (line != line_) {
      stream_->u1(Dwarf::DW_LNS_advance_line);
      stream_->sleb128(line - line_);
      line_ = line;
    }
  }

  void SetColumn(intptr_t column) {
    if (column != column_) {
      stream_->u1(Dwarf::DW_LNS_set_column);
      stream_->uleb128(column);
      column_ = column;
    }
  }

  void SetPCOffset(const char* asm_name, intptr_t pc_offset) {
    if (asm_name_ == nullptr) {
      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(asm_name, pc_offset);
    } else {
      // Emit LNP row if the address register has been updated to a
      // non-zero value (dartbug.com/41756).
      stream_->u1(Dwarf::DW_LNS_copy);
      stream_->u1(Dwarf::DW_LNS_advance_pc);
      stream_->DistanceBetweenSymbolOffsets(asm_name, pc_offset, asm_name_,
                                            pc_offset_);
    }
    asm_name_ = asm_name;
    pc_offset_ = pc_offset;
  }

 private:
  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;

  // Other info not stored in the state machine registers.
  const char* asm_name_ = nullptr;
};

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)) {
    return;
  }

  TextBuffer comments_buffer(128 * KB);

  auto comments_file = file_open(
      FLAG_write_code_comments_as_synthetic_source_to, /*write=*/true);
  if (comments_file == nullptr) {
    OS::PrintErr("Failed to open file %s\n",
                 FLAG_write_code_comments_as_synthetic_source_to);
    return;
  }

  intptr_t current_line = 0;

  writer->SetFile(comments_file_index);

  for (intptr_t i = 0; i < codes_.length(); i++) {
    const Code& code = *(codes_[i]);
    auto const asm_name = code_to_name_.LookupValue(&code);
    ASSERT(asm_name != nullptr);

    auto& comments = code.comments();
    for (intptr_t i = 0, len = comments.Length(); i < len;) {
      intptr_t current_pc_offset = comments.PCOffsetAt(i);
      writer->SetPCOffset(asm_name, current_pc_offset);
      while (i < len && current_pc_offset == comments.PCOffsetAt(i)) {
        comments_buffer.AddString(comments.CommentAt(i));
        comments_buffer.AddChar('\n');
        current_line++;
        i++;
      }

      writer->SetLine(current_line);
    }
  }

  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 asm_name = code_to_name_.LookupValue(&code);
    ASSERT(asm_name != nullptr);

    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();

    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: {
          const DwarfPosition& old_pos =
              token_positions[token_positions.length() - 1];
          token_positions[token_positions.length() - 1] = DwarfPosition(
              Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
          break;
        }
        case CodeSourceMapOps::kAdvancePC: {
          current_pc_offset += arg1;

          const Function& function = *(function_stack.Last());
          script = function.script();
          intptr_t file = LookupScript(script);

          // 1. Update LNP file.
          writer->SetFile(file);

          // 2. Update LNP line.
          // The DWARF standard uses 0 to denote missing line or column
          // information.
          writer->SetLine(token_positions.Last().line() < 0
                              ? 0
                              : token_positions.Last().line());
          writer->SetColumn(token_positions.Last().column() < 0
                                ? 0
                                : token_positions.Last().column());

          writer->SetPCOffset(asm_name, current_pc_offset);
          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();
      }
    }
  }
}

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

  // 1. unit_length. This encoding implies 32-bit DWARF.
  auto const line_prefix = "line";
  intptr_t line_start;
  intptr_t line_size_fixup = stream->ReserveSize(line_prefix, &line_start);

  stream->u2(2);  // 2. DWARF version 2

  // 3. header_length
  auto const lineheader_prefix = "lineheader";
  intptr_t lineheader_start;
  intptr_t lineheader_size_fixup =
      stream->ReserveSize(lineheader_prefix, &lineheader_start);

  stream->u1(1);   // 4. minimum_instruction_length
  stream->u1(1);   // 5. default_is_stmt (true for compatibility with dsymutil).
  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_epligoue_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]);
    uri = script.url();
    auto const uri_cstr = Deobfuscate(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(FLAG_write_code_comments_as_synthetic_source_to);  // NOLINT
    stream->uleb128(0);  // Include directory index.
    stream->uleb128(0);  // File modification time.
    stream->uleb128(0);  // File length.
  }
  stream->u1(0);  // End of file names.
  stream->SetSize(lineheader_size_fixup, lineheader_prefix, lineheader_start);

  // 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();
    const char* last_asm_name = code_to_name_.LookupValue(&last_code);
    ASSERT(last_asm_name != nullptr);
    lnp_writer.SetPCOffset(last_asm_name, last_pc_offset);
  }

  // End of contiguous machine code.
  stream->u1(0);  // This is an extended opcode
  stream->u1(1);  // that is 1 byte long
  stream->u1(DW_LNE_end_sequence);
  stream->SetSize(line_size_fixup, line_prefix, line_start);
}

const char* Dwarf::Deobfuscate(const char* cstr) {
  if (reverse_obfuscation_trie_ == nullptr) return cstr;
  TextBuffer buffer(256);
  // Used to avoid Zone-allocating strings if no deobfuscation was performed.
  bool changed = false;
  intptr_t i = 0;
  while (cstr[i] != '\0') {
    intptr_t offset;
    auto const value = reverse_obfuscation_trie_->Lookup(cstr + i, &offset);
    if (offset == 0) {
      // The first character was an invalid key element (that isn't the null
      // terminator due to the while condition), copy it and skip to the next.
      buffer.AddChar(cstr[i++]);
    } else if (value != nullptr) {
      changed = true;
      buffer.AddString(value);
    } else {
      buffer.AddRaw(reinterpret_cast<const uint8_t*>(cstr + i), offset);
    }
    i += offset;
  }
  if (!changed) return cstr;
  return OS::SCreate(zone_, "%s", buffer.buffer());
}

Trie<const char>* Dwarf::CreateReverseObfuscationTrie(Zone* zone) {
  auto const map_array = IsolateGroup::Current()->obfuscation_map();
  if (map_array == nullptr) return nullptr;

  Trie<const char>* trie = nullptr;
  for (intptr_t i = 0; map_array[i] != nullptr; i += 2) {
    auto const key = map_array[i];
    auto const value = map_array[i + 1];
    ASSERT(value != nullptr);
    // Don't include identity mappings.
    if (strcmp(key, value) == 0) continue;
    // Otherwise, any value in the obfuscation map should be a valid key.
    ASSERT(Trie<const char>::IsValidKey(value));
    trie = Trie<const char>::AddString(zone, trie, value, key);
  }
  return trie;
}

#endif  // DART_PRECOMPILER

}  // namespace dart
