AsmGrader 0.0.0
Loading...
Searching...
No Matches
memory_io_base.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <cstddef>
9#include <cstdint>
10#include <functional>
11#include <span>
12#include <type_traits>
13
14#include <sys/types.h>
15
16namespace asmgrader {
17
23{
24public:
25 explicit MemoryIOBase(pid_t pid)
26 : pid_{pid} {};
27 virtual ~MemoryIOBase() = default;
28
29 template <MemoryReadSupported T>
30 Result<T> read(std::uintptr_t address) {
31 return MemoryIOSerde<T>::read(address, *this);
32 }
33
34 template <MemoryReadSupported T>
35 requires std::is_trivial_v<T> // more complex types may have sizes that don't correspond
36 Result<std::vector<T>> read_array(std::uintptr_t address, std::size_t size) {
37 std::vector<T> result;
38 result.reserve(size);
39
40 for (std::uintptr_t current_address = address; size > 0; current_address += sizeof(T), --size) {
41 result.push_back(TRY(MemoryIOSerde<T>::read(current_address, *this)));
42 }
43
44 return result;
45 }
46
47 template <MemoryReadSupported T>
48 requires std::is_trivial_v<T> // more complex types may have sizes that don't correspond
49 Result<std::vector<T>> read_array(std::uintptr_t address, std::function<bool(const T&)> until_predicate) {
50 std::vector<T> result;
51
52 for (std::uintptr_t current_address = address;; current_address += sizeof(T)) {
53 T elem = TRY(MemoryIOSerde<T>::read(current_address, *this));
54
55 if (!until_predicate(elem)) {
56 break;
57 }
58
59 result.push_back(std::move(elem));
60 }
61
62 return result;
63 }
64
65 Result<ByteVector> read_bytes(std::uintptr_t address, std::size_t length) {
66 return this->read_block_impl(address, length);
67 }
68
69 // FIXME: The reinterpret_cast's to/from std::uintptr_t and pointer types seems kinda bad
70 template <MemoryReadSupported T>
72 if constexpr (std::is_pointer_v<T>) {
73 using NextType = std::remove_pointer_t<T>;
74
75 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
76 auto next_address = reinterpret_cast<std::uintptr_t>(TRY(read<T>(address)));
77
78 return TRY(read_deref_all<NextType>(next_address));
79 } else {
80 return TRY(read<T>(address));
81 }
82 }
83
84 template <MemoryWriteSupported T>
85 Result<std::size_t> write(std::uintptr_t address, const T& data) {
87 TRY(this->write_block_impl(address, bytes));
88 return bytes.size();
89 }
90
91 pid_t get_pid() const { return pid_; }
92
93private:
94 pid_t pid_;
95
96 template <typename T>
97 friend struct MemoryIOSerde;
98
99 virtual Result<ByteVector> read_until(std::uintptr_t address, const std::function<bool(std::byte)>& predicate);
100 virtual Result<ByteVector> read_until(std::uintptr_t address,
101 const std::function<bool(std::span<const std::byte>)>& predicate,
102 std::size_t block_size);
103
104 virtual Result<ByteVector> read_block_impl(std::uintptr_t address, std::size_t length) = 0;
105 virtual Result<void> write_block_impl(std::uintptr_t address, const ByteVector& data) = 0;
106};
107
108} // namespace asmgrader
Definition byte_vector.hpp:32
size_t size() const
Definition byte_vector.hpp:100
std::variant wrapper for a partial implementation of C++23's expected type
Definition expected.hpp:34
Base class for interacting with a tracee's memory in a variety of ways at a (relatively) high-level F...
Definition memory_io_base.hpp:23
pid_t get_pid() const
Definition memory_io_base.hpp:91
Result< std::size_t > write(std::uintptr_t address, const T &data)
Definition memory_io_base.hpp:85
MemoryIOBase(pid_t pid)
Definition memory_io_base.hpp:25
Result< std::vector< T > > read_array(std::uintptr_t address, std::function< bool(const T &)> until_predicate)
Definition memory_io_base.hpp:49
Result< remove_all_pointers_t< T > > read_deref_all(std::uintptr_t address)
Definition memory_io_base.hpp:71
Result< ByteVector > read_bytes(std::uintptr_t address, std::size_t length)
Definition memory_io_base.hpp:65
virtual ~MemoryIOBase()=default
Result< std::vector< T > > read_array(std::uintptr_t address, std::size_t size)
Definition memory_io_base.hpp:36
Result< T > read(std::uintptr_t address)
Definition memory_io_base.hpp:30
#define TRY(val)
If the supplied argument is an error (unexpected) type, then propegate it up the call stack....
Definition error_types.hpp:46
Definition asm_buffer.hpp:19
Example class implementation:
Definition memory_io_serde.hpp:31