// 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 "interception_workflow.h"

#include <string>
#include <thread>

#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/thread.h"

namespace fidlcat {

const char InterceptionWorkflow::kZxChannelWriteName[] = "zx_channel_write@plt";
const char InterceptionWorkflow::kZxChannelReadName[] = "zx_channel_read@plt";

namespace internal {

void InterceptingThreadObserver::OnThreadStopped(
    zxdb::Thread* thread, debug_ipc::NotifyException::Type type,
    const std::vector<fxl::WeakPtr<zxdb::Breakpoint>>& hit_breakpoints) {
  FXL_CHECK(thread)
      << "Internal error: Stopped in a breakpoint without a thread?";

  // There a two possible breakpoints we can hit:
  //  - A breakpoint right before a system call (zx_channel_read,
  //    zx_channel_write, etc)
  //  - A breakpoint that we hit because we ran the system call to see what the
  //    result will be.

  // This is the breakpoint that we hit after running the system call.  The
  // initial breakpoint - the one on the system call - registered a callback in
  // this per-thread map, so that the next breakpoint on this thread would be
  // handled here.
  auto entry = breakpoint_map_.find(thread->GetKoid());
  if (entry != breakpoint_map_.end()) {
    entry->second(thread);
    // Erasing under the assumption that the next step will put it back, if
    // necessary.
    breakpoint_map_.erase(thread->GetKoid());
    return;
  }

  // If there was no registered breakpoint on this thread, we hit it because we
  // encountered a system call.  Run the callbacks associated with this system
  // call.
  for (auto& bp_ptr : hit_breakpoints) {
    zxdb::BreakpointSettings settings = bp_ptr->GetSettings();
    if (settings.location.type == zxdb::InputLocation::Type::kSymbol &&
        settings.location.symbol.components().size() == 1u) {
      if (settings.location.symbol.components()[0].name() ==
          InterceptionWorkflow::kZxChannelWriteName) {
        workflow_->OnZxChannelAction<ZxChannelWriteParamsBuilder>(thread);
        return;
      } else if (settings.location.symbol.components()[0].name() ==
                 InterceptionWorkflow::kZxChannelReadName) {
        workflow_->OnZxChannelAction<ZxChannelReadParamsBuilder>(thread);
        return;
      } else {
        thread->Continue();
        return;
      }
    }
  }
  FXL_LOG(INFO)
      << "Internal error: Thread stopped on exception with no breakpoint set";
  thread->Continue();
}

void InterceptingThreadObserver::Register(
    int64_t koid, std::function<void(zxdb::Thread*)>&& cb) {
  breakpoint_map_[koid] = std::move(cb);
}

void InterceptingTargetObserver::DidCreateProcess(
    zxdb::Target* target, zxdb::Process* process,
    bool autoattached_to_new_process) {
  process->AddObserver(&dispatcher_);
  workflow_->SetBreakpoints(target);
}

}  // namespace internal

InterceptionWorkflow::InterceptionWorkflow()
    : session_(new zxdb::Session()),
      delete_session_(true),
      loop_(new debug_ipc::PlatformMessageLoop()),
      delete_loop_(true),
      observer_(this),
      zx_channel_write_callback_([](const zxdb::Err&, const ZxChannelParams&) {
        FXL_DCHECK(false) << "Did not specify zx_channel_write callback";
      }),
      zx_channel_read_callback_([](const zxdb::Err&, const ZxChannelParams&) {
        FXL_DCHECK(false) << "Did not specify zx_channel_read callback";
      }) {}

InterceptionWorkflow::InterceptionWorkflow(zxdb::Session* session,
                                           debug_ipc::PlatformMessageLoop* loop)
    : session_(session),
      delete_session_(false),
      loop_(loop),
      delete_loop_(false),
      observer_(this) {}

InterceptionWorkflow::~InterceptionWorkflow() {
  if (delete_session_) {
    delete session_;
  }
  if (delete_loop_) {
    delete loop_;
  }
}

void InterceptionWorkflow::Initialize(
    const std::vector<std::string>& symbol_paths) {
  // 1) Set up symbol index.

  // Stolen from console/console_main.cc
  std::vector<std::string> paths;

  // At this moment, the build index has all the "default" paths.
  zxdb::BuildIDIndex& build_id_index =
      session_->system().GetSymbols()->build_id_index();

  for (const auto& build_id_file : build_id_index.build_id_files()) {
    paths.push_back(build_id_file);
  }
  for (const auto& source : build_id_index.sources()) {
    paths.push_back(source);
  }

  // We add the options paths given paths.
  paths.insert(paths.end(), symbol_paths.begin(), symbol_paths.end());

  // Adding it to the settings will trigger the loading of the symbols.
  // Redundant adds are ignored.
  session_->system().settings().SetList(
      zxdb::ClientSettings::System::kSymbolPaths, std::move(paths));

  // 2) Ensure that the session correctly reads data off of the loop.
  buffer_.set_data_available_callback(
      [this]() { session_->OnStreamReadable(); });

  // 3) Provide a loop, if none exists.
  if (debug_ipc::MessageLoop::Current() == nullptr) {
    loop_->Init();
  }
}

void InterceptionWorkflow::Connect(const std::string& host, uint16_t port,
                                   SimpleErrorFunction and_then) {
  session_->Connect(host, port,
                    [and_then](const zxdb::Err& err) { and_then(err); });
}

// Helper function that finds a target for fidlcat to attach itself to. The
// target may already be running. |process_koid| should be set if you want to
// attach to a particular given process.
zxdb::Target* InterceptionWorkflow::GetTarget(uint64_t process_koid) {
  if (process_koid != ULLONG_MAX) {
    for (zxdb::Target* target : session_->system().GetTargets()) {
      if (target->GetProcess() &&
          target->GetProcess()->GetKoid() == process_koid) {
        return target;
      }
    }
  }

  for (zxdb::Target* target : session_->system().GetTargets()) {
    if (target->GetState() == zxdb::Target::State::kNone) {
      return target;
    }
  }
  return session_->system().CreateNewTarget(nullptr);
}

void InterceptionWorkflow::Attach(uint64_t process_koid,
                                  SimpleErrorFunction and_then) {
  zxdb::Target* target = GetTarget(process_koid);
  if (target->GetProcess() && target->GetProcess()->GetKoid() == process_koid) {
    return;
  }

  // TODO: Remove observer when appropriate.
  target->AddObserver(&observer_);
  target->Attach(
      process_koid, [process_koid, and_then = std::move(and_then)](
                        fxl::WeakPtr<zxdb::Target>, const zxdb::Err& err) {
        if (!err.ok()) {
          FXL_LOG(INFO) << "Unable to attach to koid " << process_koid << ": "
                        << err.msg();
          return;
        } else {
          FXL_LOG(INFO) << "Attached to process with koid " << process_koid;
        }
        and_then(err);
      });
}

void InterceptionWorkflow::Launch(const std::vector<std::string>& command,
                                  SimpleErrorFunction and_then) {
  zxdb::Target* target = GetTarget();
  target->AddObserver(&observer_);

  auto on_err = [command](const zxdb::Err& err) {
    std::string cmd;
    for (auto& param : command) {
      cmd.append(param);
      cmd.append(" ");
    }
    if (!err.ok()) {
      FXL_LOG(INFO) << "Unable to launch " << cmd << ": " << err.msg();
    } else {
      FXL_LOG(INFO) << "Launched " << cmd;
    }
    return err.ok();
  };

  if (command[0] == "run") {
    // The component workflow.
    debug_ipc::LaunchRequest request;
    request.inferior_type = debug_ipc::InferiorType::kComponent;
    request.argv = std::vector<std::string>(command.begin() + 1, command.end());
    session_->remote_api()->Launch(
        std::move(request),
        [target = target->GetWeakPtr(), on_err = std::move(on_err),
         and_then = std::move(and_then)](const zxdb::Err& err,
                                         debug_ipc::LaunchReply reply) {
          if (!on_err(err)) {
            return;
          }
          if (reply.status != debug_ipc::kZxOk) {
            FXL_LOG(INFO) << "Could not start component " << reply.process_name
                          << ": error " << reply.status;
          }
          target->session()->ExpectComponent(reply.component_id);
          and_then(err);
        });
    return;
  }

  target->SetArgs(command);
  target->Launch([on_err = std::move(on_err), and_then = std::move(and_then)](
                     fxl::WeakPtr<zxdb::Target> target, const zxdb::Err& err) {
    if (!on_err(err)) {
      return;
    }
    and_then(err);
  });
}

void InterceptionWorkflow::SetBreakpoints(zxdb::Target* target) {
  // Set the breakpoint
  zxdb::BreakpointSettings settings;
  settings.enabled = true;
  settings.stop_mode = zxdb::BreakpointSettings::StopMode::kThread;
  settings.type = debug_ipc::BreakpointType::kSoftware;
  settings.location.symbol = zxdb::Identifier(kZxChannelWriteName);
  settings.location.type = zxdb::InputLocation::Type::kSymbol;
  settings.scope = zxdb::BreakpointSettings::Scope::kTarget;
  settings.scope_target = target;

  zxdb::Breakpoint* breakpoint = session_->system().CreateNewBreakpoint();

  breakpoint->SetSettings(settings, [](const zxdb::Err& err) {
    if (!err.ok()) {
      FXL_LOG(INFO) << "Error in setting breakpoints: " << err.msg();
    }
  });

  settings.location.symbol = zxdb::Identifier(kZxChannelReadName);

  breakpoint = session_->system().CreateNewBreakpoint();

  breakpoint->SetSettings(settings, [](const zxdb::Err& err) {
    if (!err.ok()) {
      FXL_LOG(INFO) << "Error in setting breakpoints: " << err.msg();
    }
  });
}

void InterceptionWorkflow::SetBreakpoints(uint64_t process_koid) {
  for (zxdb::Target* target : session_->system().GetTargets()) {
    if (target->GetState() == zxdb::Target::State::kRunning &&
        target->GetProcess()->GetKoid() == process_koid) {
      SetBreakpoints(target);
      return;
    }
  }
}

void InterceptionWorkflow::Go() {
  debug_ipc::MessageLoop* current = debug_ipc::MessageLoop::Current();
  current->Run();
  current->Cleanup();
}

namespace {

// Makes sure we never get stuck in the workflow at a breakpoint.
class AlwaysContinue {
 public:
  AlwaysContinue(zxdb::Thread* thread) : thread_(thread) {}
  ~AlwaysContinue() { thread_->Continue(); }

 private:
  zxdb::Thread* thread_;
};

}  // namespace

// The workflow for zx_channel syscalls.
template <class T>
void InterceptionWorkflow::OnZxChannelAction(zxdb::Thread* thread) {
  ZxChannelCallback& callback = (std::is_same_v<T, ZxChannelWriteParamsBuilder>)
                                    ? zx_channel_write_callback_
                                    : zx_channel_read_callback_;
  FXL_DCHECK(callback != nullptr) << "Callback not set for zx channels param";

  // It might be considered more readable to use a shared_ptr here.  However,
  // the callback passed to BuildZxChannelParamsAndContinue is stored in the
  // builder object.  If we use a shared_ptr, we will have a cycle between the
  // shared_ptr, the builder, and the callback, and the shared_ptr will never
  // get collected.
  T* builder = new T();
  builder->BuildZxChannelParamsAndContinue(
      thread->GetWeakPtr(), observer_.process_observer().thread_observer(),
      [thread_weak = thread->GetWeakPtr(), &callback, builder](
          const zxdb::Err& err, const ZxChannelParams& params) {
        // To ensure the builder gets deleted.
        std::unique_ptr<T> ptr(builder);
        AlwaysContinue ac(thread_weak.get());
        callback(err, params);
      });
}

}  // namespace fidlcat
