Implement x86 debug registers

This commit is contained in:
Cacodemon345
2024-01-14 15:26:40 +06:00
parent b8462142b7
commit f4f252c0b7
14 changed files with 352 additions and 87 deletions

View File

@@ -161,6 +161,57 @@ mem_log(const char *fmt, ...)
# define mem_log(fmt, ...)
#endif
/* Set trap for data address breakpoints. */
void
mem_debug_check_addr(uint32_t addr, int write)
{
int i = 0;
int set_trap = 0;
if (trap == 4)
return; /* Debug trap already pending. */
if (!(dr[7] & 0xFF))
return;
for (i = 0; i < 4; i++) {
uint32_t dr_addr = dr[i];
int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i)));
int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i);
if (!breakpoint_enabled)
continue;
if (!write && (len_type_pair & 3) != 3)
continue;
if ((len_type_pair & 3) != 1)
continue;
switch ((len_type_pair >> 2) & 3)
{
case 0x00:
if (dr_addr == addr) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
case 0x01:
if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
case 0x03:
dr_addr &= ~3;
if (addr >= dr_addr && addr < (dr_addr + 4)) {
set_trap = 1;
dr[6] |= (1 << i);
}
break;
}
}
if (set_trap)
trap = 4;
}
int
mem_addr_is_ram(uint32_t addr)
{
@@ -790,6 +841,7 @@ readmembl(uint32_t addr)
uint64_t a;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
mem_debug_check_addr(addr, 0);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
@@ -819,6 +871,7 @@ writemembl(uint32_t addr, uint8_t val)
uint64_t a;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
mem_debug_check_addr(addr, 1);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
@@ -905,6 +958,8 @@ readmemwl(uint32_t addr)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 0);
mem_debug_check_addr(addr + 1, 0);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2);
mem_logical_addr = addr;
@@ -963,6 +1018,8 @@ writememwl(uint32_t addr, uint16_t val)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 1);
mem_debug_check_addr(addr + 1, 1);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2);
mem_logical_addr = addr;
@@ -1139,8 +1196,10 @@ readmemll(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4);
mem_logical_addr = addr;
@@ -1213,8 +1272,10 @@ writememll(uint32_t addr, uint32_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4);
mem_logical_addr = addr;
@@ -1417,8 +1478,10 @@ readmemql(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8);
mem_logical_addr = addr;
@@ -1483,8 +1546,10 @@ writememql(uint32_t addr, uint64_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8);
mem_logical_addr = addr;
@@ -1582,8 +1647,10 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write)
uint32_t last_addr = addr + (num - 1);
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < num; i++)
mem_debug_check_addr(addr, write);
for (i = 0; i < num; i++) {
a64[i] = (uint64_t) addr;
}
for (i = 0; i < num; i++) {
if (cr0 >> 31) {

View File

@@ -243,6 +243,7 @@ readmembl_2386(uint32_t addr)
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
mem_debug_check_addr(addr, 0);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
@@ -270,6 +271,7 @@ writemembl_2386(uint32_t addr, uint8_t val)
mem_mapping_t *map;
uint64_t a;
mem_debug_check_addr(addr, 1);
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
addr64 = (uint64_t) addr;
@@ -347,6 +349,8 @@ readmemwl_2386(uint32_t addr)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 0);
mem_debug_check_addr(addr + 1, 0);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2);
mem_logical_addr = addr;
@@ -402,6 +406,8 @@ writememwl_2386(uint32_t addr, uint16_t val)
addr64a[0] = addr;
addr64a[1] = addr + 1;
mem_debug_check_addr(addr, 1);
mem_debug_check_addr(addr + 1, 1);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2);
mem_logical_addr = addr;
@@ -555,8 +561,10 @@ readmemll_2386(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4);
mem_logical_addr = addr;
@@ -626,8 +634,10 @@ writememll_2386(uint32_t addr, uint32_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4);
mem_logical_addr = addr;
@@ -807,8 +817,10 @@ readmemql_2386(uint32_t addr)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 0);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8);
mem_logical_addr = addr;
@@ -870,8 +882,10 @@ writememql_2386(uint32_t addr, uint64_t val)
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
addr64a[i] = (uint64_t) (addr + i);
mem_debug_check_addr(addr + i, 1);
}
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8);
mem_logical_addr = addr;
@@ -957,32 +971,35 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write)
uint32_t last_addr = addr + (num - 1);
uint64_t a = 0x0000000000000000ULL;
mem_debug_check_addr(addr, write);
for (i = 0; i < num; i++)
a64[i] = (uint64_t) addr;
for (i = 0; i < num; i++) {
if (cr0 >> 31) {
/* If we have encountered at least one page fault, mark all subsequent addresses as
having page faulted, prevents false negatives in readmem*l_no_mmut. */
if ((i > 0) && cpu_state.abrt && !high_page)
a64[i] = a64[i - 1];
/* If we are on the same page, there is no need to translate again, as we can just
reuse the previous result. */
else if (i == 0) {
a = mmutranslatereal_2386(addr, write);
a64[i] = (uint32_t) a;
} else if (!(addr & 0xfff)) {
a = mmutranslatereal_2386(last_addr, write);
a64[i] = (uint32_t) a;
if (!(cr0 >> 31))
return;
if (!cpu_state.abrt) {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
} else {
for (i = 0; i < num; i++) {
/* If we have encountered at least one page fault, mark all subsequent addresses as
having page faulted, prevents false negatives in readmem*l_no_mmut. */
if ((i > 0) && cpu_state.abrt && !high_page)
a64[i] = a64[i - 1];
/* If we are on the same page, there is no need to translate again, as we can just
reuse the previous result. */
else if (i == 0) {
a = mmutranslatereal_2386(addr, write);
a64[i] = (uint32_t) a;
} else if (!(addr & 0xfff)) {
a = mmutranslatereal_2386(last_addr, write);
a64[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
} else {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
addr++;