// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/client/substatement.h"

#include <lib/syslog/cpp/macros.h>

#include <algorithm>

#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/client/arch_info.h"
#include "src/developer/debug/zxdb/client/disassembler.h"
#include "src/developer/debug/zxdb/client/memory_dump.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/symbols/line_details.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"

// Because of the way GDB works, Clang and GCC both emit separate "statements" for each line of
// a multiline conditional. We would prefer if DWARF line table "IsStmt" entries mapped to
// language statements.
//
// As a result, out substatement extraction only works on a single line. If you have a complex
// multiline statement, each line of that will be separate and to get to the substatement you want
// you'll have to first step to the right line.
//
// Typically (at least in debug mode), statements are executed "bottom up". For a 3-line statement,
// there will be line entries for line 1 (initial stuff), then 3, 2, and back to 1 again. We could
// try to be smarter and consider all statements in between two references of the same line, or
// going backwards, as part of the same toplevel statement. This would allow us to handle these
// unoptimized multiline C/C++ statements better. But optimized code would become much less
// predictable and we'll have to test carefully.

namespace zxdb {

namespace {

// Appends all inline functions which start in the given location. The Location should identify both
// the address and the block the address is contained in. The result will be sorted by call address.
std::vector<SubstatementCall> GetInlineCallsForLocation(const ProcessSymbols* symbols,
                                                        const Location& loc) {
  std::vector<SubstatementCall> result;

  const Function* func = loc.symbol().Get()->As<Function>();
  if (!func)
    return result;

  // Move to the deepest code block for the address in question. Don't go into inlines since we're
  // currently going to search for the inline calls in the range.
  const CodeBlock* block = func->GetMostSpecificChild(loc.symbol_context(), loc.address(), false);
  if (!block)
    return result;

  TargetPointer relative_address = loc.symbol_context().AbsoluteToRelative(loc.address());

  // Check for inlines that are children of the current block for ones that start at the current
  // line.
  for (const auto& child : block->inner_blocks()) {
    const Function* call = child.Get()->As<Function>();
    if (!call || !call->is_inline())
      continue;

    if (call->code_ranges().empty())
      continue;  // No code for this call, not sure why.

    // To count as a call from the current line, the call must start after the current address
    // (the user could have stepped half through a bunch of inlines and we don't want to show the
    // ones already passed), and the call line must match.
    TargetPointer relative_call_addr = call->code_ranges()[0].begin();

    if (relative_call_addr >= relative_address && call->call_line() == loc.file_line()) {
      // This inline starts in the address range, count it.
      SubstatementCall& added = result.emplace_back();
      added.call_addr = loc.symbol_context().RelativeToAbsolute(relative_call_addr);
      added.call_dest = added.call_addr;
      added.inline_call = RefPtrTo(call);
    }
  }

  std::sort(result.begin(), result.end());
  return result;
}

// Sanity threshold to avoid doing too many queries if the symbols are corrupt, very different
// than we expect, or exceptionally long. This is in bytes.
constexpr uint64_t kMaxRangeSize = 1024;

// Checks all addresses in the given address range and adds the ranges that map to the given
// file_line to the output. This will also check for ranges that begin in the range but end outside
// of it.
//
// The stop_on_no_match flag indicates that adding line entries should stop as soon as a line is
// found that doesn't match the guven line (excepting compiler-generated "line 0" entries). This
// is used to greedily add all matching ranges.
//
// This just does many individual queries. This could be done faster using the line table directly
// since then we can go through it linearly for the range we care about. But that approach makes the
// querying more complex and so far this has not shown to be too slow.
void AppendAddressRangesForLineInRange(Process* process, const FileLine& file_line,
                                       const AddressRange& range, bool stop_on_no_match,
                                       AddressRanges::RangeVector* out) {
  TargetPointer cur = range.begin();
  while (cur < range.end() && cur - range.begin() < kMaxRangeSize) {
    LineDetails line_details = process->GetSymbols()->LineDetailsForAddress(cur);
    if (!line_details.is_valid())
      return;

    AddressRange extent = line_details.GetExtent();
    if (extent.empty())
      return;

    if (line_details.file_line() == file_line) {
      out->push_back(extent);
    } else if (line_details.file_line().line() != 0 && stop_on_no_match) {
      return;  // Found a non-matching line, done.
    }

    cur = extent.end();
  }
}

}  // namespace

AddressRange GetAddressRangeForLineSubstatements(Process* process, const Location& loc);

void GetSubstatementCallsForLine(
    Process* process, const Location& loc,
    fit::function<void(const Err&, std::vector<SubstatementCall>)> cb) {
  std::vector<SubstatementCall> inlines = GetInlineCallsForLocation(process->GetSymbols(), loc);

  // Each inline can have multiple non-contiguous ranges, possibly interleaved with other inline
  // calls. We need to consider the code not covered by any inline, so extract all inline ranges
  // into one structure. The inline ranges should not overlap since each of these inlines is at the
  // same lexicial scope.
  AddressRanges::RangeVector inline_range_vector;
  for (const auto& inline_call : inlines) {
    // These code ranges will be module-relative addresses.
    const auto& cur_ranges = inline_call.inline_call->code_ranges();
    inline_range_vector.insert(inline_range_vector.end(), cur_ranges.begin(), cur_ranges.end());
  }
  // This representation of all the inline ranges is sorted absolute addresses.
  AddressRanges inline_ranges = loc.symbol_context().RelativeToAbsolute(
      AddressRanges(AddressRanges::kNonCanonical, std::move(inline_range_vector)));

  // The code ranges we care about are all the bits between the inline functions we just identified
  // that map the current file/line.
  AddressRanges::RangeVector line_code_ranges;

  // Check the range in between each inline. Count starting from the current address.
  TargetPointer prev_end = loc.address();
  for (size_t i = 0; i < inline_ranges.size(); i++) {
    AddressRange cur_range(prev_end, inline_ranges[i].begin());
    if (!cur_range.empty()) {
      AppendAddressRangesForLineInRange(process, loc.file_line(), cur_range, false,
                                        &line_code_ranges);
    }
    prev_end = inline_ranges[i].end();
  }

  // The address immediately following the last inline call also counts as a place to query since
  // the last inline could be followed by a function call on the same line. If there are no inlines,
  // this location will just be the code range we're querying. We query from there to the end of
  // the enclosing function, but tell the Append... function to stop as soon as it finds a
  // non-matching line entry.
  TargetPointer end_inline_address =
      inline_ranges.empty() ? loc.address() : inline_ranges.back().end();
  // Compute the end of the function to know where to stop searching.
  TargetPointer function_end = end_inline_address + 1;  // Default to querying one byte.
  if (const Function* func = loc.symbol().Get()->As<Function>()) {
    // There can be more than one discontiguous address range for the function, use the one
    // that contains the address we're starting the query from. It's theoretically possible the
    // range we want to query covers a discontiguous memory region, but ignore that case since it
    // makes everything much more complicated.
    AddressRanges function_ranges = func->GetAbsoluteCodeRanges(loc.symbol_context());
    if (std::optional<AddressRange> range = function_ranges.GetRangeContaining(end_inline_address))
      function_end = range->end();
  }
  AppendAddressRangesForLineInRange(process, loc.file_line(),
                                    AddressRange(end_inline_address, function_end), true,
                                    &line_code_ranges);

  // Make all of the matching ranges in a canonical form.
  AddressRanges line_code(AddressRanges::kNonCanonical, std::move(line_code_ranges));

  if (line_code.empty()) {
    // No code for this line to disassemble. All we have are the inlines (if any).
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb), inlines = std::move(inlines)]() mutable {
          cb(Err(), std::move(inlines));
        });
    return;
  }

  AddressRange extent = line_code.GetExtent();
  process->ReadMemory(
      extent.begin(), extent.size(),
      [arch_info = &process->session()->arch_info(),
       weak_symbols = process->GetSymbols()->GetWeakPtr(), loc, line_code = std::move(line_code),
       inlines = std::move(inlines), cb = std::move(cb)](const Err& in_err, MemoryDump dump) {
        if (in_err.has_error())
          return cb(in_err, {});
        if (!weak_symbols)
          return cb(Err("Process destroyed."), {});

        std::vector<SubstatementCall> result =
            GetSubstatementCallsForMemory(arch_info, weak_symbols.get(), loc, line_code, dump);

        // Merge in inline calls.
        result.insert(result.end(), inlines.begin(), inlines.end());
        std::sort(result.begin(), result.end());

        cb(Err(), std::move(result));
      });
}

std::vector<SubstatementCall> GetSubstatementCallsForMemory(const ArchInfo* arch_info,
                                                            const ProcessSymbols* symbols,
                                                            const Location& loc,
                                                            const AddressRanges& ranges,
                                                            const MemoryDump& mem) {
  Disassembler disassembler;
  if (disassembler.Init(arch_info).has_error())
    return {};

  Disassembler::Options options;

  std::vector<Disassembler::Row> rows;
  disassembler.DisassembleDump(mem, mem.address(), options, 0, &rows);

  std::vector<SubstatementCall> result;
  for (const auto& row : rows) {
    if ((row.type == Disassembler::InstructionType::kCallDirect ||
         row.type == Disassembler::InstructionType::kCallIndirect) &&
        ranges.InRange(row.address)) {
      auto& call = result.emplace_back();
      call.call_addr = row.address;
      call.call_dest = row.call_dest;  // Will be nullopt for indirect calls.
    }
  }

  return result;
}

}  // namespace zxdb
