-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmm.cpp
More file actions
172 lines (123 loc) · 3.82 KB
/
mm.cpp
File metadata and controls
172 lines (123 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include "mm.hpp"
#include "platform.hpp"
namespace allity {
uint64_t memory_manager::read(uint32_t addr, int size) {
auto s = std::find_if(
m_blocks.begin(),
m_blocks.end(),
[addr](const memory_block& mb) {
return (addr >= mb.start) && (addr < mb.end);
}
);
if (s == m_blocks.end()) {
printf("allity: segv when reading from %016x\n", addr);
exit(1);
}
uint64_t offset = addr - s->start;
switch (size) {
case 0: return *((uint8_t*)(s->buf + offset));
case 1: return be(*(uint16_t*)(s->buf + offset));
case 2: return be(*(uint32_t*)(s->buf + offset));
case 3: return be(*(uint64_t*)(s->buf + offset));
}
printf("allity: invalid size when reading from %016x\n", addr);
return 0;
}
void memory_manager::write(uint32_t addr, uint64_t data, int size) {
auto s = std::find_if(
m_blocks.begin(),
m_blocks.end(),
[addr](const memory_block& mb) {
return (addr >= mb.start) && (addr < mb.end);
}
);
if (s == m_blocks.end()) {
printf("allity: segv when writing %x to %016x\n", data, addr);
exit(1);
}
uint64_t offset = addr - s->start;
switch (size) {
case 0: *((uint8_t*)(s->buf + offset)) = data; return;
case 1: *((uint16_t*)(s->buf + offset)) = be(data); return;
case 2: *((uint32_t*)(s->buf + offset)) = be(data); return;
case 3: *((uint64_t*)(s->buf + offset)) = be(data); return;
}
printf("allity: invalid size when writing to %016x\n", addr);
return;
}
const elf::file& memory_manager::file() const {
return m_file;
}
memory_block* memory_manager::alloc(uint64_t start, uint64_t size) {
memory_block mb;
mb.start = start;
mb.end = mb.start + size;
mb.buf = malloc(size);
m_blocks.push_back(mb);
return &m_blocks.back();
}
memory_block* memory_manager::alloc(uint64_t size) {
return alloc(0x100000000ull | rand(), size);
}
void memory_manager::free(uint64_t ptr) {
// To-do
}
bool memory_manager::load(const char* path) {
if (!m_file.open(path))
return false;
for (const auto& s : m_file.segments()) {
uint64_t size = s.file_size();
memory_block* mb;
if (size) {
mb = alloc(s.virtual_address(), size);
s.store(mb->buf, 0);
} else {
mb = alloc(s.virtual_address(), s.mem_size());
}
mb->attributes =
(s.is_executable() ? PF_X : 0) |
(s.is_writeable() ? PF_W : 0) |
(s.is_readable() ? PF_R : 0);
}
return true;
}
uint8_t mm_read8(void* udata, uint32_t addr) {
memory_manager* mm = (memory_manager*)udata;
return mm->read(addr, 0);
}
uint16_t mm_read16(void* udata, uint32_t addr) {
memory_manager* mm = (memory_manager*)udata;
return mm->read(addr, 1);
}
uint32_t mm_read32(void* udata, uint32_t addr) {
memory_manager* mm = (memory_manager*)udata;
return mm->read(addr, 2);
}
uint64_t mm_read64(void* udata, uint32_t addr) {
memory_manager* mm = (memory_manager*)udata;
return mm->read(addr, 3);
}
void mm_write8(void* udata, uint32_t addr, uint8_t data) {
memory_manager* mm = (memory_manager*)udata;
if (addr == 0xa0000000) {
putchar(data);
return;
}
mm->write(addr, data, 0);
}
void mm_write16(void* udata, uint32_t addr, uint16_t data) {
memory_manager* mm = (memory_manager*)udata;
mm->write(addr, data, 1);
}
void mm_write32(void* udata, uint32_t addr, uint32_t data) {
memory_manager* mm = (memory_manager*)udata;
mm->write(addr, data, 2);
}
void mm_write64(void* udata, uint32_t addr, uint64_t data) {
memory_manager* mm = (memory_manager*)udata;
mm->write(addr, data, 3);
}
}