16#include <fmt/format.h>
34 explicit Program(std::filesystem::path path, std::vector<std::string> args = {});
52 const std::filesystem::path&
get_path()
const;
53 const std::vector<std::string>&
get_args()
const;
57 template <
typename Func,
typename... Args>
60 template <
typename Func,
typename... Args>
64 std::uintptr_t
alloc_mem(std::size_t amt);
69 std::filesystem::path path_;
70 std::vector<std::string> args_;
72 std::unique_ptr<TracedSubprocess> subproc_;
73 std::unique_ptr<SymbolTable> symtab_;
75 std::size_t alloced_mem_{};
78template <
typename Func,
typename... Args>
82 Tracer& tracer = subproc_->get_tracer();
85 if (
auto res = subproc_->get_tracer().get_memory_io().read_bytes(subproc_->get_tracer().get_mmapped_addr(), 32);
87 LOG_TRACE(
"Memory (32 bytes) at start of mmaped addr (0x{:x}): {::x}",
88 subproc_->get_tracer().get_mmapped_addr(), *res);
91#if defined(ASMGRADER_AARCH64)
92 [[maybe_unused]] std::uintptr_t instr_pointer =
TRY(tracer.
get_registers()).pc;
93#elif defined(ASMGRADER_X86_64)
94 [[maybe_unused]] std::uintptr_t instr_pointer =
TRY(tracer.
get_registers()).rip;
96 LOG_TRACE(
"Jumping to: {:#X} from {:#X}", addr, instr_pointer);
99 auto run_res = tracer.
run();
102 return run_res.error();
109 if (run_res->get_kind() == Exited || run_res->get_kind() == Killed) {
110 TRY(subproc_->restart());
115 if (run_res->get_kind() != SignalCaught || run_res->get_code() != SIGTRAP) {
116 LOG_DEBUG(
"Unexpected return from function: kind={}, code={}", fmt::underlying(run_res->get_kind()),
117 run_res->get_code());
119 std::uintptr_t instr_addr =
121 subproc_->get_tracer().get_registers()->pc;
123 subproc_->get_tracer().get_registers()->rip;
125 if (
auto res = subproc_->get_tracer().get_memory_io().read_bytes(instr_addr, 16); res) {
126 LOG_TRACE(
"Memory (16 bytes) at point of instruction ptr (0x{:x}): {::x}", instr_addr, *res);
132 if constexpr (std::same_as<Ret, void>) {
145template <
typename Func,
typename... Args>
147 auto symbol = symtab_->find(name);
152 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:32
const std::vector< std::string > & get_args() const
Definition program.cpp:119
static Expected< void, std::string > check_is_compat_elf(const std::filesystem::path &path)
Definition program.cpp:58
Program(std::filesystem::path path, std::vector< std::string > args={})
Definition program.cpp:38
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:146
SymbolTable & get_symtab()
Definition program.cpp:86
Program & operator=(Program &&rhs)=default
Result< RunResult > run_until(const std::function< bool(SyscallRecord)> &pred)
Definition program.cpp:98
std::uintptr_t alloc_mem(std::size_t amt)
Definition program.cpp:102
Result< RunResult > run()
Definition program.cpp:94
TracedSubprocess & get_subproc()
Definition program.cpp:78
const std::filesystem::path & get_path() const
Definition program.cpp:115
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:17
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:223
Result< Ret > process_function_ret()
AFTER a function has been called, inspects register values (and memory if necessary) to construct the...
Definition tracer.hpp:277
Result< RunResult > run()
Run the child process. Records each syscall execution. Equivalent to run_until({})
Definition tracer.cpp:332
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:235
Result< void > setup_function_call(Args &&... args)
Definition tracer.hpp:173
#define TRY(val)
If the supplied argument is an error (unexpected) type, then propegate it up the call stack....
Definition error_types.hpp:52
#define LOG_TRACE(...)
Definition logging.hpp:40
#define LOG_DEBUG(...)
Definition logging.hpp:41
Definition asm_buffer.hpp:20
@ UnexpectedReturn
A function returned happened due to an unexpected condition.
@ UnresolvedSymbol
Failed to resolve a named symbol in a program.
@ UnknownError
As named; use this as little as possible.
Definition functional_traits.hpp:14
Record of a syscall for use with Tracer to keep track of which syscalls a child process invokes.
Definition syscall_record.hpp:22