// Copyright 2018 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/process_impl.h"

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

#include <algorithm>
#include <set>

#include "lib/fit/defer.h"
#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/client/memory_dump.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/process_symbol_data_provider.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/target_impl.h"
#include "src/developer/debug/zxdb/client/thread_impl.h"
#include "src/developer/debug/zxdb/common/join_callbacks.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/input_location.h"
#include "src/developer/debug/zxdb/symbols/loaded_module_symbols.h"
#include "src/developer/debug/zxdb/symbols/module_symbol_status.h"
#include "src/lib/fxl/memory/ref_ptr.h"

namespace zxdb {

ProcessImpl::ProcessImpl(TargetImpl* target, uint64_t koid, const std::string& name,
                         Process::StartType start_type,
                         const std::vector<debug_ipc::ComponentInfo>& component_info,
                         std::optional<debug_ipc::AddressRegion> shared_aspace)
    : Process(target->session(), start_type),
      target_(target),
      koid_(koid),
      name_(name),
      component_info_(std::move(component_info)),
      shared_aspace_(std::move(shared_aspace)),
      symbols_(this, target->symbols()),
      weak_factory_(this) {}

ProcessImpl::~ProcessImpl() {
  // Send notifications for all destroyed threads.
  for (const auto& thread : threads_) {
    for (auto& observer : session()->thread_observers())
      observer.WillDestroyThread(thread.second.get());
  }
}

// static.
std::unique_ptr<ProcessImpl> ProcessImpl::FromPreviousProcess(
    TargetImpl* target, const debug_ipc::ProcessRecord& record) {
  auto process = std::make_unique<ProcessImpl>(target, record.process_koid, record.process_name,
                                               StartType::kAttach, record.components,
                                               record.shared_address_space);

  process->UpdateThreads(record.threads);

  return process;
}

ThreadImpl* ProcessImpl::GetThreadImplFromKoid(uint64_t koid) {
  auto found = threads_.find(koid);
  if (found == threads_.end())
    return nullptr;
  return found->second.get();
}

bool ProcessImpl::HasLoadedSymbols() const { return !symbols_.GetStatus().empty(); }

Process::SymbolStatus ProcessImpl::GetSymbolStatus() {
  auto process_symbol_status = GetSymbols()->GetStatus();

  if (process_symbol_status.empty()) {
    return SymbolStatus::kNoModules;
  }

  // Callers don't care about how many symbols are being loaded, just that some are.
  if (std::any_of(process_symbol_status.begin(), process_symbol_status.end(),
                  [this](const auto& status) {
                    return session()->system().HasDownload(status.build_id);
                  })) {
    return SymbolStatus::kInProgress;
  }

  bool any_failed = std::any_of(process_symbol_status.begin(), process_symbol_status.end(),
                                [](const auto& status) { return !status.symbols_loaded; });

  return any_failed ? SymbolStatus::kNotLoaded : SymbolStatus::kLoaded;
}

void ProcessImpl::GetModules(
    bool force_reload_symbols,
    fit::callback<void(const Err&, std::vector<debug_ipc::Module>)> callback) {
  debug_ipc::ModulesRequest request;
  request.process_koid = koid_;
  session()->remote_api()->Modules(
      request,
      [process = weak_factory_.GetWeakPtr(), force_reload_symbols, callback = std::move(callback)](
          const Err& err, debug_ipc::ModulesReply reply) mutable {
        if (process) {
          process->FixupEmptyModuleNames(reply.modules);
          process->symbols_.SetModules(reply.modules, force_reload_symbols);
          process->SyncThreads({});
        }
        if (callback)
          callback(err, std::move(reply.modules));
      });
}

void ProcessImpl::GetAspace(
    uint64_t address,
    fit::callback<void(const Err&, std::vector<debug_ipc::AddressRegion>)> callback) const {
  debug_ipc::AddressSpaceRequest request;
  request.process_koid = koid_;
  request.address = address;
  session()->remote_api()->AddressSpace(
      request,
      [callback = std::move(callback)](const Err& err, debug_ipc::AddressSpaceReply reply) mutable {
        if (callback)
          callback(err, std::move(reply.map));
      });
}

std::vector<Thread*> ProcessImpl::GetThreads() const {
  std::vector<Thread*> result;
  result.reserve(threads_.size());
  for (const auto& pair : threads_)
    result.push_back(pair.second.get());
  return result;
}

Thread* ProcessImpl::GetThreadFromKoid(uint64_t koid) { return GetThreadImplFromKoid(koid); }

void ProcessImpl::SyncThreads(fit::callback<void()> callback) {
  debug_ipc::ThreadsRequest request;
  request.process_koid = koid_;
  session()->remote_api()->Threads(
      request, [callback = std::move(callback), process = weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::ThreadsReply reply) mutable {
        if (process) {
          process->UpdateThreads(reply.threads);
          if (callback)
            callback();
        }
      });
}

void ProcessImpl::Pause(fit::callback<void()> on_paused) {
  debug_ipc::PauseRequest request;
  request.ids.push_back({.process = koid_, .thread = 0});
  session()->remote_api()->Pause(
      request, [weak_process = weak_factory_.GetWeakPtr(), on_paused = std::move(on_paused)](
                   const Err& err, debug_ipc::PauseReply reply) mutable {
        if (weak_process) {
          // Save any new thread metadata (will be empty for errors so don't need to check
          // explicitly for errors).
          for (const auto& record : reply.threads) {
            FX_DCHECK(record.id.process == weak_process->koid_);
            if (ThreadImpl* thread = weak_process->GetThreadImplFromKoid(record.id.thread))
              thread->SetMetadata(record);
          }
        }
        on_paused();
      });
}

void ProcessImpl::Continue(bool forward_exceptions) {
  // Tell each thread to continue as it desires.
  //
  // It would be more efficient to tell the backend to resume all threads in the process but the
  // Thread client objects have state which needs to be updated (like the current stack) and the
  // thread could have a controller that wants to continue in a specific way (like single-step or
  // step in a range).
  for (const auto& [koid, thread] : threads_)
    thread->Continue(forward_exceptions);
}

void ProcessImpl::ContinueUntil(std::vector<InputLocation> locations,
                                fit::callback<void(const Err&)> cb) {
  cb(Err("Process-wide 'until' is not implemented."));
}

void ProcessImpl::CancelAllThreadControllers() {
  for (const auto& [koid, thread] : threads_)
    thread->CancelAllThreadControllers();
}

fxl::RefPtr<SymbolDataProvider> ProcessImpl::GetSymbolDataProvider() const {
  if (!symbol_data_provider_) {
    symbol_data_provider_ = fxl::MakeRefCounted<ProcessSymbolDataProvider>(
        const_cast<ProcessImpl*>(this)->GetWeakPtr());
  }
  return symbol_data_provider_;
}

void ProcessImpl::GetTLSHelpers(GetTLSHelpersCallback cb) {
  DoWithHelpers([cb = std::move(cb), this, weak_this = GetWeakPtr()](bool have_helpers) mutable {
    if (!weak_this) {
      cb(Err("Process died while getting TLS helper."));
    } else if (have_helpers) {
      cb(&tls_helpers_);
    } else {
      cb(Err("This binary is missing debugger integration hooks for reading TLS."));
    }
  });
}

void ProcessImpl::ReadMemory(uint64_t address, uint32_t size,
                             fit::callback<void(const Err&, MemoryDump)> callback) {
  // If the memory was read automatically been read and was cached, then this branch will get the
  // memory locally as opposed to sending a remote message.
  if (memory_blocks_.size() > 0) {
    for (auto thread_blocks : memory_blocks_) {
      for (auto block : thread_blocks.second) {
        if (block.address <= address && block.address + block.size >= address + size) {
          auto vec = std::vector<debug_ipc::MemoryBlock>();
          if (block.address == address && block.size == size) {
            vec.push_back(block);
          } else if (!block.valid) {
            vec.push_back({.address = address, .valid = false, .size = size});
          } else {
            debug_ipc::MemoryBlock subset_block = {.address = address, .valid = true, .size = size};
            subset_block.data =
                std::vector<uint8_t>(block.data.begin() + (address - block.address),
                                     block.data.begin() + (address - block.address) + size);
            vec.push_back(subset_block);
          }
          // The callers expect the callback to be called after this method returns. That means that
          // we can't call it directly. Instead we post a task so that the callback will be called
          // when the caller will be idle.
          debug::MessageLoop::Current()->PostTask(
              FROM_HERE, [callback = std::move(callback), vec = std::move(vec)]() mutable {
                callback(Err(), MemoryDump(std::move(vec)));
              });
          return;
        }
      }
    }
  }
  debug_ipc::ReadMemoryRequest request;
  request.process_koid = koid_;
  request.address = address;
  request.size = size;
  session()->remote_api()->ReadMemory(
      request,
      [callback = std::move(callback)](const Err& err, debug_ipc::ReadMemoryReply reply) mutable {
        callback(err, MemoryDump(std::move(reply.blocks)));
      });
}

void ProcessImpl::WriteMemory(uint64_t address, std::vector<uint8_t> data,
                              fit::callback<void(const Err&)> callback) {
  debug_ipc::WriteMemoryRequest request;
  request.process_koid = koid_;
  request.address = address;
  request.data = std::move(data);
  session()->remote_api()->WriteMemory(
      request, [address, callback = std::move(callback)](
                   const Err& err, debug_ipc::WriteMemoryReply reply) mutable {
        if (err.has_error()) {
          callback(err);
        } else if (reply.status.has_error()) {
          // Convert bad reply to error.
          callback(Err("Unable to write memory to 0x%" PRIx64 ": %s", address,
                       reply.status.message().c_str()));
        } else {
          // Success.
          callback(Err());
        }
      });
}

void ProcessImpl::LoadInfoHandleTable(
    fit::callback<void(ErrOr<std::vector<debug_ipc::InfoHandle>> handles)> callback) {
  debug_ipc::LoadInfoHandleTableRequest request;
  request.process_koid = koid_;
  session()->remote_api()->LoadInfoHandleTable(
      request, [callback = std::move(callback)](const Err& err,
                                                debug_ipc::LoadInfoHandleTableReply reply) mutable {
        if (reply.status.has_error()) {
          callback(Err("Can't load handles: " + reply.status.message()));
        } else if (err.ok()) {
          callback(std::move(reply.handles));
        } else {
          callback(err);
        }
      });
}

std::optional<debug_ipc::AddressRegion> ProcessImpl::GetSharedAddressSpace() const {
  return shared_aspace_;
}

void ProcessImpl::OnThreadStarting(const debug_ipc::ThreadRecord& record) {
  if (threads_.find(record.id.thread) != threads_.end()) {
    // Duplicate new thread notification. Some legitimate cases could cause
    // this, like the client requesting a thread list (which will add missing
    // ones and get here) racing with the notification for just-created thread.
    return;
  }

  auto thread = std::make_unique<ThreadImpl>(this, record);
  Thread* thread_ptr = thread.get();
  threads_[record.id.thread] = std::move(thread);

  for (auto& observer : session()->thread_observers())
    observer.DidCreateThread(thread_ptr);
}

void ProcessImpl::OnThreadExiting(const debug_ipc::ThreadRecord& record) {
  auto found = threads_.find(record.id.thread);
  if (found == threads_.end()) {
    // Duplicate exit thread notification. Some legitimate cases could cause this as in
    // OnThreadStarting().
    return;
  }

  for (auto& observer : session()->thread_observers())
    observer.WillDestroyThread(found->second.get());

  threads_.erase(found);
}

debug_ipc::ResumeRequest::How ProcessImpl::OnException(const StopInfo& info) {
  debug_ipc::ResumeRequest::How how = debug_ipc::ResumeRequest::How::kLast;

  bool auto_continue_through_step =
      target()->settings().GetBool(ClientSettings::Target::kAutoContinueWhenStepping);

  switch (kind()) {
    case Process::Kind::kTest: {
      if (info.exception_record.strategy == debug_ipc::ExceptionStrategy::kSecondChance) {
        // Automatically forward and continue second chance exceptions for tests.
        how = debug_ipc::ResumeRequest::How::kForwardAndContinue;
      }

      if (debug_ipc::IsDebug(info.exception_type) && info.hit_breakpoints.empty()) {
        if (auto_continue_through_step) {
          // Automatically resolve and continue when we get a debug exception not associated with
          // any of our breakpoints for tests.
          how = debug_ipc::ResumeRequest::How::kResolveAndContinue;
        } else {
          // When |auto_continue_through_step| is false, then we should only apply the automatic
          // continue if the exception is not a single step.
          if (info.exception_type != debug_ipc::ExceptionType::kSingleStep) {
            how = debug_ipc::ResumeRequest::How::kResolveAndContinue;
          }
        }
      }
      break;
    }
    default: {
      break;
    }
  }

  // Only send the notification if we decided to tell the thread that it should continue.
  if (how != debug_ipc::ResumeRequest::How::kLast) {
    for (auto& observer : session()->process_observers())
      observer.WillAutomaticallyContinue(how, info);
  }

  return how;
}

void ProcessImpl::OnModules(std::vector<debug_ipc::Module> modules) {
  FixupEmptyModuleNames(modules);
  symbols_.SetModules(modules, false);

  // The process is stopped so we have time to load symbols and enable any pending breakpoints.
  // Now that the notification is complete, resume the process.
  //
  // Note that this is a "blind" resume, as the |this| does not yet know about any threads that are
  // currently running. It will issue a sync call shortly.
  debug_ipc::ResumeRequest request;
  request.how = debug_ipc::ResumeRequest::How::kResolveAndContinue;
  request.ids.push_back({.process = koid_});
  session()->remote_api()->Resume(request, [](const Err& err, debug_ipc::ResumeReply) {});

  // We get the list of threads for the process we are attaching.
  SyncThreads({});
}

bool ProcessImpl::HandleIO(const debug_ipc::NotifyIO& io) {
  auto& buffer = io.type == debug_ipc::NotifyIO::Type::kStdout ? stdout_ : stderr_;

  buffer.insert(buffer.end(), io.data.data(), io.data.data() + io.data.size());
  if (buffer.size() >= kMaxIOBufferSize)
    buffer.resize(kMaxIOBufferSize);

  return target()->settings().GetBool(ClientSettings::System::kShowStdout);
}

void ProcessImpl::UpdateThreads(const std::vector<debug_ipc::ThreadRecord>& new_threads) {
  // Go through all new threads, checking to added ones and updating existing.
  std::set<uint64_t> new_threads_koids;
  for (const auto& record : new_threads) {
    new_threads_koids.insert(record.id.thread);
    auto found_existing = threads_.find(record.id.thread);
    if (found_existing == threads_.end()) {
      // New thread added.
      OnThreadStarting(record);
    } else {
      // Existing one, update everything. Thread list updates don't include full stack frames for
      // performance reasons.
      found_existing->second->SetMetadata(record);
    }
  }

  // Do the reverse lookup to check for threads not in the new list. Be careful not to mutate the
  // threads_ list while iterating over it.
  std::vector<uint64_t> existing_koids;
  for (const auto& pair : threads_)
    existing_koids.push_back(pair.first);
  for (uint64_t existing_koid : existing_koids) {
    if (new_threads_koids.find(existing_koid) == new_threads_koids.end()) {
      debug_ipc::ThreadRecord record;
      record.id = {.process = koid_, .thread = existing_koid};
      OnThreadExiting(record);
    }
  }
}

void ProcessImpl::DidLoadModuleSymbols(LoadedModuleSymbols* module) {
  for (auto& observer : session()->process_observers())
    observer.DidLoadModuleSymbols(this, module);
}

void ProcessImpl::DidLoadAllModuleSymbols() {
  for (auto& observer : session()->process_observers())
    observer.DidLoadAllModuleSymbols(this);
}

void ProcessImpl::WillLoadModuleSymbols(int num_modules) {
  for (auto& observer : session()->process_observers())
    observer.WillLoadModuleSymbols(this, num_modules);
}

void ProcessImpl::WillUnloadModuleSymbols(LoadedModuleSymbols* module) {
  for (auto& observer : session()->process_observers())
    observer.WillUnloadModuleSymbols(this, module);
}

uint64_t ProcessImpl::GetElfSymbolAddress(const std::string& symbol, uint64_t* size) {
  Identifier elf_ident(IdentifierComponent(SpecialIdentifier::kElf, symbol));
  InputLocation location(elf_ident);
  auto locs = symbols_.ResolveInputLocation(location);

  for (const auto& loc : locs) {
    if (auto sym = loc.symbol().Get()) {
      if (auto elf_sym = sym->As<ElfSymbol>()) {
        *size = elf_sym->size();
        return loc.address();
      }
    }
  }

  return 0;
}

void ProcessImpl::DoWithHelpers(fit::callback<void(bool)> cb) {
  if (tls_helper_state_ == kFailed) {
    cb(false);
  } else if (tls_helper_state_ == kLoaded) {
    cb(true);
  } else {
    helper_waiters_.push_back(std::move(cb));
    LoadTLSHelpers();
  }
}

void ProcessImpl::LoadTLSHelpers() {
  if (tls_helper_state_ != kUnloaded) {
    return;
  }

  tls_helper_state_ = kLoading;

  struct HelperToLoad {
    uint64_t addr;
    uint64_t size;
    std::vector<uint8_t>* target;
  };

  std::vector<HelperToLoad> regions;
  regions.resize(3);

  regions[0].addr = GetElfSymbolAddress("zxdb.thrd_t", &regions[0].size);
  regions[0].target = &tls_helpers_.thrd_t;
  regions[1].addr = GetElfSymbolAddress("zxdb.link_map_tls_modid", &regions[1].size);
  regions[1].target = &tls_helpers_.link_map_tls_modid;
  regions[2].addr = GetElfSymbolAddress("zxdb.tlsbase", &regions[2].size);
  regions[2].target = &tls_helpers_.tlsbase;

  for (const auto& region : regions) {
    if (region.addr && region.size) {
      continue;
    }

    tls_helper_state_ = kFailed;

    for (auto& cb : helper_waiters_) {
      cb(false);
    }

    helper_waiters_.clear();

    return;
  }

  std::shared_ptr<fit::deferred_callback> finish = std::make_shared<fit::deferred_callback>(
      fit::defer_callback([this, weak_this = GetWeakPtr()]() {
        if (!weak_this) {
          return;
        }

        bool failed = tls_helpers_.thrd_t.empty() || tls_helpers_.link_map_tls_modid.empty() ||
                      tls_helpers_.tlsbase.empty();

        if (failed) {
          tls_helper_state_ = kFailed;
        } else {
          tls_helper_state_ = kLoaded;
        }

        for (auto& cb : helper_waiters_) {
          cb(!failed);
        }

        helper_waiters_.clear();
      }));

  for (const auto& region : regions) {
    ReadMemory(region.addr, region.size,
               [target = region.target, weak_this = GetWeakPtr(), finish](const Err& err,
                                                                          MemoryDump dump) {
                 if (weak_this && !err.has_error() && dump.AllValid()) {
                   for (const auto& block : dump.blocks()) {
                     std::copy(block.data.begin(), block.data.end(), std::back_inserter(*target));
                   }
                 }
               });
  }
}

void ProcessImpl::FixupEmptyModuleNames(std::vector<debug_ipc::Module>& modules) const {
  for (auto& m : modules) {
    if (m.name.empty())
      m.name = GetName();
  }
}

void ProcessImpl::OnSymbolLoadFailure(const Err& err) {
  for (auto& observer : session()->process_observers())
    observer.OnSymbolLoadFailure(this, err);
}

void ProcessImpl::FetchMemoryRanges(std::vector<std::pair<uint64_t, uint32_t>> ranges,
                                    fit::callback<void()> done) {
  struct Pack {
    Pack(const Err& err, std::vector<debug_ipc::MemoryBlock> blocks)
        : err(err), blocks(std::move(blocks)) {}
    Err err;
    std::vector<debug_ipc::MemoryBlock> blocks;
  };

  auto joiner = fxl::MakeRefCounted<JoinCallbacks<Pack>>();

  for (const auto& [addr, size] : ranges) {
    debug_ipc::ReadMemoryRequest request;
    request.address = addr;
    request.size = size;
    request.process_koid = GetKoid();

    session()->remote_api()->ReadMemory(
        request,
        [cb = joiner->AddCallback()](const Err& err, debug_ipc::ReadMemoryReply reply) mutable {
          return cb({err, std::move(reply.blocks)});
        });
  }

  joiner->Ready([weak_this = weak_factory_.GetWeakPtr(), joiner,
                 done = std::move(done)](std::vector<Pack> results) mutable {
    if (!weak_this) {
      joiner->Abandon();
      return;
    }

    std::vector<debug_ipc::MemoryBlock> all_blocks;

    for (const auto& result : results) {
      all_blocks.insert(all_blocks.end(), result.blocks.begin(), result.blocks.end());
    }

    std::sort(all_blocks.begin(), all_blocks.end(),
              [](const auto& lhs, const auto& rhs) { return lhs.address < rhs.address; });

    weak_this->cached_memory_.emplace_back(std::move(all_blocks));

    debug::MessageLoop::Current()->PostTask(FROM_HERE, [done = std::move(done)]() mutable {
      FX_DCHECK(done);
      done();
    });
  });
}

unwinder::Error ProcessImpl::ReadBytes(uint64_t addr, uint64_t size, void* dst) {
  unwinder::Error err = unwinder::Success();

  for (auto& memory : cached_memory_) {
    if (err = memory.ReadBytes(addr, size, dst); err.ok()) {
      return unwinder::Success();
    }
  }

  return err;
}

}  // namespace zxdb
