forked from aquynh/unidos
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmem.c
146 lines (116 loc) · 3.03 KB
/
mem.c
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
#include <stdint.h>
#include <stddef.h>
#include <unicorn/unicorn.h>
#include <string.h>
#include "mem.h"
#include "global.h"
#include "defs.h"
struct mem_block
{
uint16_t segment;
uint16_t size;
struct mem_block* prev;
struct mem_block* next;
} * mem_blocks = NULL;
uint8_t mem_free(uint16_t seg)
{
for (struct mem_block* cur = mem_blocks; cur; cur = cur->next)
{
if (cur->segment == seg)
{
if (cur->prev)
{
cur->prev->next = cur->next;
}
if (cur->next)
{
cur->next->prev = cur->prev;
}
uc_err err = uc_mem_unmap(uc, cur->segment << 4, cur->size);
if (err)
{
printf("Failed to free memory block!\n");
print_uc_err(err);
free(cur);
return ERR_INSUFFICIENT_MEMORY;
}
free(cur);
return ERR_SUCCESS;
}
}
return ERR_INVALID_MEMORY_BLOCK_ADDRESS;
}
uint8_t mem_alloc(uint16_t size, uint16_t* seg)
{
uint32_t addr = 0x10000;
size = ALIGN(size, 4096);
do
{
uint32_t lim = addr + size;
if (addr >= 0xA0000 || lim >= 0xA0000)
{
printf("OUT OF MEMORY!\n");
return ERR_INSUFFICIENT_MEMORY;
}
for (struct mem_block* cur = mem_blocks; cur; cur = cur->next)
{
uint32_t begin = cur->segment << 4;
uint32_t end = begin + cur->size;
if ((addr < begin && begin < lim) || (addr < end && end < lim))
{
addr = end;
if (addr & 0xF)
addr = ALIGN(addr, 16);
continue;
}
}
break;
} while (true);
struct mem_block* blk = calloc(1, sizeof(struct mem_block));
blk->segment = addr >> 4;
blk->size = size;
uc_err err = uc_mem_map(uc, blk->segment << 4, blk->size, UC_PROT_ALL);
if (err)
{
printf("Failed to allocate memory block with size %04x\n", size);
print_uc_err(err);
return ERR_INSUFFICIENT_MEMORY;
}
*seg = blk->segment;
if (!mem_blocks)
{
mem_blocks = blk;
return ERR_SUCCESS;
}
struct mem_block* cur = mem_blocks;
while (cur->next)
cur = cur->next;
cur->next = blk;
blk->prev = cur;
return ERR_SUCCESS;
}
uint8_t mem_realloc(uint16_t size, uint16_t seg)
{
struct mem_block* cur = NULL;
for (cur = mem_blocks; cur; cur = cur->next)
{
if (cur->segment == seg)
break;
}
if (!cur)
return ERR_INVALID_MEMORY_BLOCK_ADDRESS;
uint16_t old_size = cur->size;
void* buf = malloc(old_size);
uc_mem_read(uc, cur->segment << 4, buf, old_size);
if (mem_free(seg))
{
return ERR_INSUFFICIENT_MEMORY;
}
uint16_t new_seg;
if (mem_alloc(size, &seg))
{
return ERR_INSUFFICIENT_MEMORY;
}
uc_mem_write(uc, seg << 4, buf, MIN(size, old_size));
return ERR_SUCCESS;
}