/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DEBUG_ELF_DEBUG_LINE_WRITER_H_
#define ART_COMPILER_DEBUG_ELF_DEBUG_LINE_WRITER_H_

#include <unordered_set>
#include <vector>

#include "compiled_method.h"
#include "debug/dwarf/debug_line_opcode_writer.h"
#include "debug/dwarf/headers.h"
#include "debug/elf_compilation_unit.h"
#include "dex_file-inl.h"
#include "elf_builder.h"
#include "stack_map.h"

namespace art {
namespace debug {

typedef std::vector<DexFile::PositionInfo> PositionInfos;

static bool PositionInfoCallback(void* ctx, const DexFile::PositionInfo& entry) {
  static_cast<PositionInfos*>(ctx)->push_back(entry);
  return false;
}

template<typename ElfTypes>
class ElfDebugLineWriter {
  using Elf_Addr = typename ElfTypes::Addr;

 public:
  explicit ElfDebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
  }

  void Start() {
    builder_->GetDebugLine()->Start();
  }

  // Write line table for given set of methods.
  // Returns the number of bytes written.
  size_t WriteCompilationUnit(ElfCompilationUnit& compilation_unit) {
    const bool is64bit = Is64BitInstructionSet(builder_->GetIsa());
    const Elf_Addr base_address = compilation_unit.is_code_address_text_relative
        ? builder_->GetText()->GetAddress()
        : 0;

    compilation_unit.debug_line_offset = builder_->GetDebugLine()->GetSize();

    std::vector<dwarf::FileEntry> files;
    std::unordered_map<std::string, size_t> files_map;
    std::vector<std::string> directories;
    std::unordered_map<std::string, size_t> directories_map;
    int code_factor_bits_ = 0;
    int dwarf_isa = -1;
    switch (builder_->GetIsa()) {
      case kArm:  // arm actually means thumb2.
      case kThumb2:
        code_factor_bits_ = 1;  // 16-bit instuctions
        dwarf_isa = 1;  // DW_ISA_ARM_thumb.
        break;
      case kArm64:
      case kMips:
      case kMips64:
        code_factor_bits_ = 2;  // 32-bit instructions
        break;
      case kNone:
      case kX86:
      case kX86_64:
        break;
    }
    std::unordered_set<uint64_t> seen_addresses(compilation_unit.methods.size());
    dwarf::DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_);
    for (const MethodDebugInfo* mi : compilation_unit.methods) {
      // Ignore function if we have already generated line table for the same address.
      // It would confuse the debugger and the DWARF specification forbids it.
      // We allow the line table for method to be replicated in different compilation unit.
      // This ensures that each compilation unit contains line table for all its methods.
      if (!seen_addresses.insert(mi->code_address).second) {
        continue;
      }

      uint32_t prologue_end = std::numeric_limits<uint32_t>::max();
      std::vector<SrcMapElem> pc2dex_map;
      if (mi->code_info != nullptr) {
        // Use stack maps to create mapping table from pc to dex.
        const CodeInfo code_info(mi->code_info);
        const CodeInfoEncoding encoding = code_info.ExtractEncoding();
        pc2dex_map.reserve(code_info.GetNumberOfStackMaps(encoding));
        for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(encoding); s++) {
          StackMap stack_map = code_info.GetStackMapAt(s, encoding);
          DCHECK(stack_map.IsValid());
          const uint32_t pc = stack_map.GetNativePcOffset(encoding.stack_map_encoding);
          const int32_t dex = stack_map.GetDexPc(encoding.stack_map_encoding);
          pc2dex_map.push_back({pc, dex});
          if (stack_map.HasDexRegisterMap(encoding.stack_map_encoding)) {
            // Guess that the first map with local variables is the end of prologue.
            prologue_end = std::min(prologue_end, pc);
          }
        }
        std::sort(pc2dex_map.begin(), pc2dex_map.end());
      }

      if (pc2dex_map.empty()) {
        continue;
      }

      // Compensate for compiler's off-by-one-instruction error.
      //
      // The compiler generates stackmap with PC *after* the branch instruction
      // (because this is the PC which is easier to obtain when unwinding).
      //
      // However, the debugger is more clever and it will ask us for line-number
      // mapping at the location of the branch instruction (since the following
      // instruction could belong to other line, this is the correct thing to do).
      //
      // So we really want to just decrement the PC by one instruction so that the
      // branch instruction is covered as well. However, we do not know the size
      // of the previous instruction, and we can not subtract just a fixed amount
      // (the debugger would trust us that the PC is valid; it might try to set
      // breakpoint there at some point, and setting breakpoint in mid-instruction
      // would make the process crash in spectacular way).
      //
      // Therefore, we say that the PC which the compiler gave us for the stackmap
      // is the end of its associated address range, and we use the PC from the
      // previous stack map as the start of the range. This ensures that the PC is
      // valid and that the branch instruction is covered.
      //
      // This ensures we have correct line number mapping at call sites (which is
      // important for backtraces), but there is nothing we can do for non-call
      // sites (so stepping through optimized code in debugger is not possible).
      //
      // We do not adjust the stackmaps if the code was compiled as debuggable.
      // In that case, the stackmaps should accurately cover all instructions.
      if (!mi->is_native_debuggable) {
        for (size_t i = pc2dex_map.size() - 1; i > 0; --i) {
          pc2dex_map[i].from_ = pc2dex_map[i - 1].from_;
        }
        pc2dex_map[0].from_ = 0;
      }

      Elf_Addr method_address = base_address + mi->code_address;

      PositionInfos dex2line_map;
      DCHECK(mi->dex_file != nullptr);
      const DexFile* dex = mi->dex_file;
      if (!dex->DecodeDebugPositionInfo(mi->code_item, PositionInfoCallback, &dex2line_map)) {
        continue;
      }

      if (dex2line_map.empty()) {
        continue;
      }

      opcodes.SetAddress(method_address);
      if (dwarf_isa != -1) {
        opcodes.SetISA(dwarf_isa);
      }

      // Get and deduplicate directory and filename.
      int file_index = 0;  // 0 - primary source file of the compilation.
      auto& dex_class_def = dex->GetClassDef(mi->class_def_index);
      const char* source_file = dex->GetSourceFile(dex_class_def);
      if (source_file != nullptr) {
        std::string file_name(source_file);
        size_t file_name_slash = file_name.find_last_of('/');
        std::string class_name(dex->GetClassDescriptor(dex_class_def));
        size_t class_name_slash = class_name.find_last_of('/');
        std::string full_path(file_name);

        // Guess directory from package name.
        int directory_index = 0;  // 0 - current directory of the compilation.
        if (file_name_slash == std::string::npos &&  // Just filename.
            class_name.front() == 'L' &&  // Type descriptor for a class.
            class_name_slash != std::string::npos) {  // Has package name.
          std::string package_name = class_name.substr(1, class_name_slash - 1);
          auto it = directories_map.find(package_name);
          if (it == directories_map.end()) {
            directory_index = 1 + directories.size();
            directories_map.emplace(package_name, directory_index);
            directories.push_back(package_name);
          } else {
            directory_index = it->second;
          }
          full_path = package_name + "/" + file_name;
        }

        // Add file entry.
        auto it2 = files_map.find(full_path);
        if (it2 == files_map.end()) {
          file_index = 1 + files.size();
          files_map.emplace(full_path, file_index);
          files.push_back(dwarf::FileEntry {
            file_name,
            directory_index,
            0,  // Modification time - NA.
            0,  // File size - NA.
          });
        } else {
          file_index = it2->second;
        }
      }
      opcodes.SetFile(file_index);

      // Generate mapping opcodes from PC to Java lines.
      if (file_index != 0) {
        // If the method was not compiled as native-debuggable, we still generate all available
        // lines, but we try to prevent the debugger from stepping and setting breakpoints since
        // the information is too inaccurate for that (breakpoints would be set after the calls).
        const bool default_is_stmt = mi->is_native_debuggable;
        bool first = true;
        for (SrcMapElem pc2dex : pc2dex_map) {
          uint32_t pc = pc2dex.from_;
          int dex_pc = pc2dex.to_;
          // Find mapping with address with is greater than our dex pc; then go back one step.
          auto dex2line = std::upper_bound(
              dex2line_map.begin(),
              dex2line_map.end(),
              dex_pc,
              [](uint32_t address, const DexFile::PositionInfo& entry) {
                  return address < entry.address_;
              });
          // Look for first valid mapping after the prologue.
          if (dex2line != dex2line_map.begin() && pc >= prologue_end) {
            int line = (--dex2line)->line_;
            if (first) {
              first = false;
              if (pc > 0) {
                // Assume that any preceding code is prologue.
                int first_line = dex2line_map.front().line_;
                // Prologue is not a sensible place for a breakpoint.
                opcodes.SetIsStmt(false);
                opcodes.AddRow(method_address, first_line);
                opcodes.SetPrologueEnd();
              }
              opcodes.SetIsStmt(default_is_stmt);
              opcodes.AddRow(method_address + pc, line);
            } else if (line != opcodes.CurrentLine()) {
              opcodes.SetIsStmt(default_is_stmt);
              opcodes.AddRow(method_address + pc, line);
            }
          }
        }
      } else {
        // line 0 - instruction cannot be attributed to any source line.
        opcodes.AddRow(method_address, 0);
      }

      opcodes.AdvancePC(method_address + mi->code_size);
      opcodes.EndSequence();
    }
    std::vector<uint8_t> buffer;
    buffer.reserve(opcodes.data()->size() + KB);
    size_t offset = builder_->GetDebugLine()->GetSize();
    WriteDebugLineTable(directories, files, opcodes, offset, &buffer, &debug_line_patches_);
    builder_->GetDebugLine()->WriteFully(buffer.data(), buffer.size());
    return buffer.size();
  }

  void End(bool write_oat_patches) {
    builder_->GetDebugLine()->End();
    if (write_oat_patches) {
      builder_->WritePatches(".debug_line.oat_patches",
                             ArrayRef<const uintptr_t>(debug_line_patches_));
    }
  }

 private:
  ElfBuilder<ElfTypes>* builder_;
  std::vector<uintptr_t> debug_line_patches_;
};

}  // namespace debug
}  // namespace art

#endif  // ART_COMPILER_DEBUG_ELF_DEBUG_LINE_WRITER_H_

