15#include <fmt/format.h>
33 explicit Program(std::filesystem::path path, std::vector<std::string> args = {});
47 const std::filesystem::path&
get_path()
const;
48 const std::vector<std::string>&
get_args()
const;
52 template <
typename Func,
typename... Args>
55 template <
typename Func,
typename... Args>
59 std::uintptr_t
alloc_mem(std::size_t amt);
64 std::filesystem::path path_;
65 std::vector<std::string> args_;
67 std::unique_ptr<TracedSubprocess> subproc_;
68 std::unique_ptr<SymbolTable> symtab_;
70 std::size_t alloced_mem_{};
73template <
typename Func,
typename... Args>
77 Tracer& tracer = subproc_->get_tracer();
80 if (
auto res = subproc_->get_tracer().get_memory_io().read_bytes(subproc_->get_tracer().get_mmapped_addr(), 32);
82 LOG_TRACE(
"Memory (32 bytes) at start of mmaped addr (0x{:x}): {::x}",
83 subproc_->get_tracer().get_mmapped_addr(), *res);
86#if defined(ASMGRADER_AARCH64)
87 [[maybe_unused]] std::uintptr_t instr_pointer =
TRY(tracer.
get_registers()).pc;
88#elif defined(ASMGRADER_X86_64)
89 [[maybe_unused]] std::uintptr_t instr_pointer =
TRY(tracer.
get_registers()).rip;
91 LOG_TRACE(
"Jumping to: {:#X} from {:#X}", addr, instr_pointer);
94 auto run_res = tracer.
run();
97 return run_res.error();
104 if (run_res->get_kind() == Exited || run_res->get_kind() == Killed) {
105 TRY(subproc_->restart());
110 if (run_res->get_kind() != SignalCaught || run_res->get_code() != SIGTRAP) {
111 LOG_DEBUG(
"Unexpected return from function: kind={}, code={}", fmt::underlying(run_res->get_kind()),
112 run_res->get_code());
114 std::uintptr_t instr_addr =
116 subproc_->get_tracer().get_registers()->pc;
118 subproc_->get_tracer().get_registers()->rip;
120 if (
auto res = subproc_->get_tracer().get_memory_io().read_bytes(instr_addr, 16); res) {
121 LOG_TRACE(
"Memory (16 bytes) at point of instruction ptr (0x{:x}): {::x}", instr_addr, *res);
124 return ErrorKind::UnexpectedReturn;
127 if constexpr (std::same_as<Ret, void>) {
133 return ErrorKind::UnknownError;
140template <
typename Func,
typename... Args>
142 auto symbol = symtab_->find(name);
144 return ErrorKind::UnresolvedSymbol;
147 LOG_TRACE(
"Resolved symbol {:?} at {:#X}", symbol->name, symbol->address);
std::variant wrapper for a partial implementation of C++23's expected type
Definition expected.hpp:34
A trivially-movable, but non-copyable type.
Definition class_traits.hpp:14
Definition program.hpp:31
const std::vector< std::string > & get_args() const
Definition program.cpp:104
Program(std::filesystem::path path, std::vector< std::string > args={})
Definition program.cpp:33
Program(Program &&other)=default
Result< typename FunctionTraits< Func >::Ret > call_function(std::string_view name, Args &&... args)
Returns the result of the function call, or nullopt if the symbol name was not found or some other er...
Definition program.hpp:141
SymbolTable & get_symtab()
Definition program.cpp:75
static Expected< void, std::string > check_is_elf(const std::filesystem::path &path)
Definition program.cpp:53
Program & operator=(Program &&rhs)=default
std::uintptr_t alloc_mem(std::size_t amt)
Definition program.cpp:87
Result< RunResult > run()
Definition program.cpp:83
TracedSubprocess & get_subproc()
Definition program.cpp:67
const std::filesystem::path & get_path() const
Definition program.cpp:100
Kind
Definition run_result.hpp:8
A basic symbol table, for simple interaction with a number of symbols loaded from an ELF file.
Definition symbol_table.hpp:14
A subprocess managed by a tracer.
Definition traced_subprocess.hpp:14
A lightweight wrapper of ptrace(2)
Definition tracer.hpp:49
Result< void > jump_to(std::uintptr_t address)
Set the child process's instruction pointer to address
Definition tracer.cpp:187
Result< Ret > process_function_ret()
AFTER a function has been called, inspects register values (and memory if necessary) to construct the...
Definition tracer.hpp:264
Result< RunResult > run()
Run the child process. Collect syscall info each time one is executed.
Definition tracer.cpp:297
Result< user_regs_struct > get_registers() const
Get the general purpose registers of the stopped tracee IMPORTANT: this is (obviously) architecture-d...
Definition tracer.cpp:199
Result< void > setup_function_call(Args &&... args)
Definition tracer.hpp:160
#define TRY(val)
If the supplied argument is an error (unexpected) type, then propegate it up the call stack....
Definition error_types.hpp:46
#define LOG_TRACE(...)
Definition logging.hpp:43
#define LOG_DEBUG(...)
Definition logging.hpp:44
Definition asm_buffer.hpp:19
Definition functional_traits.hpp:14