// 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.

#ifndef GARNET_BIN_DEBUG_AGENT_DEBUGGED_PROCESS_H_
#define GARNET_BIN_DEBUG_AGENT_DEBUGGED_PROCESS_H_

#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <map>
#include <memory>
#include <vector>

#include "garnet/bin/debug_agent/process_memory_accessor.h"
#include "garnet/lib/debug_ipc/helper/message_loop.h"
#include "garnet/lib/debug_ipc/helper/zircon_exception_watcher.h"
#include "garnet/lib/debug_ipc/protocol.h"
#include "garnet/lib/debug_ipc/records_utils.h"

#include "lib/fxl/macros.h"

namespace debug_agent {

class Breakpoint;
class DebugAgent;
class DebuggedThread;
class ProcessBreakpoint;
class ProcessWatchpoint;
class Watchpoint;

class DebuggedProcess : public debug_ipc::ZirconExceptionWatcher,
                        public ProcessMemoryAccessor {
 public:
  // Caller must call Init immediately after construction and delete the
  // object if that fails.
  DebuggedProcess(DebugAgent* debug_agent, zx_koid_t process_koid,
                  zx::process proc, bool resume_initial_thread);
  virtual ~DebuggedProcess();

  zx_koid_t koid() const { return koid_; }
  DebugAgent* debug_agent() const { return debug_agent_; }
  zx::process& process() { return process_; }
  uint64_t dl_debug_addr() const { return dl_debug_addr_; }

  // Returns true on success. On failure, the object may not be used further.
  bool Init();

  // IPC handlers.
  void OnPause(const debug_ipc::PauseRequest& request);
  void OnResume(const debug_ipc::ResumeRequest& request);
  void OnReadMemory(const debug_ipc::ReadMemoryRequest& request,
                    debug_ipc::ReadMemoryReply* reply);
  void OnKill(const debug_ipc::KillRequest& request,
              debug_ipc::KillReply* reply);
  void OnAddressSpace(const debug_ipc::AddressSpaceRequest& request,
                      debug_ipc::AddressSpaceReply* reply);
  void OnModules(debug_ipc::ModulesReply* reply);
  void OnSymbolTables(const debug_ipc::SymbolTablesRequest& request,
                      debug_ipc::SymbolTablesReply* reply);
  void OnWriteMemory(const debug_ipc::WriteMemoryRequest& request,
                     debug_ipc::WriteMemoryReply* reply);

  // Pauses all threads in the process. If non-null, the paused_koids vector
  // will be populated with the koids of all threads paused by this operation.
  void PauseAll(std::vector<uint64_t>* paused_koids = nullptr);

  // Returns the thread or null if there is no known thread for this koid.
  virtual DebuggedThread* GetThread(zx_koid_t thread_koid) const;
  virtual std::vector<DebuggedThread*> GetThreads() const;

  // Populates the thread map with the current threads for this process, and
  // sends the list to the client. Used after an attach where we will not get
  // new thread notifications.
  void PopulateCurrentThreads();

  // Attempts to load the debug_state_ value from the
  // ZX_PROP_PROCESS_DEBUG_ADDR of the debugged process. Returns true if it
  // is now set. False means it remains unset. Normally the first time this
  // returns true would need to be followed up with a SendModuleNotification.
  bool RegisterDebugState();

  // Sends the currently loaded modules to the client with the given list
  // of paused threads.
  void SendModuleNotification(std::vector<uint64_t> paused_thread_koids);

  // Looks for breakpoints at the given address. Null if no breakpoints are
  // at that address.
  ProcessBreakpoint* FindProcessBreakpointForAddr(uint64_t address);

  // Notifications when breakpoints are added or removed that affect this
  // process.
  zx_status_t RegisterBreakpoint(Breakpoint* bp, uint64_t address);
  void UnregisterBreakpoint(Breakpoint* bp, uint64_t address);

  zx_status_t RegisterWatchpoint(Watchpoint*, const debug_ipc::AddressRange&);
  void UnregisterWatchpoint(Watchpoint*, const debug_ipc::AddressRange&);

 private:
  // ZirconExceptionWatcher implementation.
  void OnProcessTerminated(zx_koid_t process_koid) override;
  void OnThreadStarting(zx_koid_t process_koid, zx_koid_t thread_koid) override;
  void OnThreadExiting(zx_koid_t process_koid, zx_koid_t thread_koid) override;
  void OnException(zx_koid_t process_koid, zx_koid_t thread_koid,
                   uint32_t type) override;

  // This function will gracefully detach from the underlying zircon process.
  // Detaching correctly requires several steps:
  //
  // 1. Remove the installed breakpoints.
  //
  // 2. Resume threads from the exception. Only threads that are stopped on an
  // exception should be resumed. This is because otherwise zircon will treat
  // this exception as unhandled and will bubble up the exception upwards,
  // probably resulting in a crash.
  //
  // 3. Unbind the exception port.
  void DetachFromProcess();

  // ProcessMemoryAccessor implementation.
  zx_status_t ReadProcessMemory(uintptr_t address, void* buffer, size_t len,
                                size_t* actual) override;
  zx_status_t WriteProcessMemory(uintptr_t address, const void* buffer,
                                 size_t len, size_t* actual) override;

  DebugAgent* debug_agent_;  // Non-owning.
  zx_koid_t koid_;
  zx::process process_;

  // Address in the debugged program of the dl_debug_state in ld.so.
  uint64_t dl_debug_addr_ = 0;

  // Handle for watching the process exceptions.
  debug_ipc::MessageLoop::WatchHandle process_watch_handle_;

  std::map<zx_koid_t, std::unique_ptr<DebuggedThread>> threads_;

  // Maps addresses to the ProcessBreakpoint at a location. The
  // ProcessBreakpoint can hold multiple Breakpoint objects.
  std::map<uint64_t, std::unique_ptr<ProcessBreakpoint>> breakpoints_;

  // Each watchpoint holds the information about what range of addresses
  // it spans.
  std::map<debug_ipc::AddressRange, std::unique_ptr<ProcessWatchpoint>,
           debug_ipc::AddressRangeCompare>
      watchpoints_;

  // TODO(donosoc): Allow options to stop none, initial or all threads.
  bool resume_initial_thread_;
  bool waiting_for_initial_thread_;

  FXL_DISALLOW_COPY_AND_ASSIGN(DebuggedProcess);
};

}  // namespace debug_agent

#endif  // GARNET_BIN_DEBUG_AGENT_DEBUGGED_PROCESS_H_
