| // 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. |
| |
| // This is a simple program that serves two purposes: |
| // 1) Serve as an example of how to use the library. |
| // 2) Provide a tool to exercise the library by hand. |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <src/lib/fxl/command_line.h> |
| #include <src/lib/fxl/log_settings_command_line.h> |
| #include <src/lib/fxl/logging.h> |
| |
| #include "garnet/lib/debugger_utils/jobs.h" |
| #include "garnet/lib/debugger_utils/util.h" |
| |
| #include "process.h" |
| #include "server.h" |
| |
| const char kUsageString[] = |
| "Usage: run_inferior [options] [--] path [arg1 ...]\n" |
| "Options:\n" |
| " --help Duh."; |
| |
| class SampleServer final : public inferior_control::Server { |
| public: |
| SampleServer() |
| : Server(debugger_utils::GetDefaultJob(), |
| debugger_utils::GetDefaultJob(), |
| sys::ServiceDirectory::CreateFromNamespace()) { |
| } |
| |
| bool Run() override { |
| // Start the main loop. |
| __UNUSED zx_status_t status = message_loop_.Run(); |
| |
| FXL_LOG(INFO) << "Main loop exited"; |
| |
| return true; |
| } |
| |
| bool RunInferior(const std::string& path, |
| const debugger_utils::Argv& argv) { |
| // The exception port loop must be started before we attach to the |
| // inferior. |
| if (!exception_port_.Run()) { |
| FXL_LOG(ERROR) << "Failed to initialize exception port!"; |
| return false; |
| } |
| |
| if (!StartInferior(path, argv)) { |
| return false; |
| } |
| |
| __UNUSED bool success = Run(); |
| FXL_DCHECK(success); |
| |
| // Tell the exception port to quit and wait for it to finish. |
| exception_port_.Quit(); |
| |
| return true; |
| } |
| |
| private: |
| bool StartInferior(const std::string& path, |
| const debugger_utils::Argv& argv) { |
| auto inferior = new inferior_control::Process(this, this); |
| set_current_process(inferior); |
| |
| std::unique_ptr<process::ProcessBuilder> builder; |
| if (!CreateProcessViaBuilder(path, argv, &builder)) { |
| FXL_LOG(ERROR) << "Unable to create process builder"; |
| return EXIT_FAILURE; |
| } |
| |
| builder->CloneAll(); |
| |
| if (!inferior->InitializeFromBuilder(std::move(builder))) { |
| FXL_LOG(ERROR) << "Unable to initialize inferior process"; |
| return EXIT_FAILURE; |
| } |
| |
| if (!inferior->Start()) { |
| FXL_LOG(ERROR) << "Unable to start process"; |
| return false; |
| } |
| |
| return true; |
| } |
| }; |
| |
| static void PrintUsageString() { puts(kUsageString); } |
| |
| int main(int argc, char **argv) { |
| auto cl = fxl::CommandLineFromArgcArgv(argc, argv); |
| if (!fxl::SetLogSettingsFromCommandLine(cl)) |
| return EXIT_FAILURE; |
| |
| if (cl.HasOption("help", nullptr)) { |
| PrintUsageString(); |
| return EXIT_SUCCESS; |
| } |
| |
| if (cl.positional_args().size() == 0) { |
| FXL_LOG(ERROR) << "Missing program"; |
| return EXIT_FAILURE; |
| } |
| debugger_utils::Argv inferior_argv{cl.positional_args().begin(), |
| cl.positional_args().end()}; |
| const std::string& path = inferior_argv[0]; |
| |
| FXL_LOG(INFO) << "Running: " << path; |
| FXL_LOG(INFO) << "Args: " << debugger_utils::ArgvToString(inferior_argv); |
| |
| SampleServer server{}; |
| if (!server.RunInferior(path, inferior_argv)) { |
| return EXIT_FAILURE; |
| } |
| |
| inferior_control::Process* inferior = server.current_process(); |
| if (inferior->return_code_is_set()) { |
| FXL_LOG(INFO) << "Process " << inferior->id() << " exited, rc " |
| << inferior->return_code(); |
| return inferior->return_code(); |
| } else { |
| FXL_LOG(INFO) << "Process " << inferior->id() << " crashed"; |
| return -1; |
| } |
| } |