mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 00:35:34 +00:00
uc_mem_read() & uc_mem_write() now can work on adjacent memory areas. this fixes issue #38
This commit is contained in:
parent
ff46b91a80
commit
810054ca6d
|
@ -5,4 +5,4 @@ uc = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||||
uc.mem_map(0x0000, 0x2000)
|
uc.mem_map(0x0000, 0x2000)
|
||||||
uc.mem_map(0x2000, 0x4000)
|
uc.mem_map(0x2000, 0x4000)
|
||||||
uc.mem_write(0x1000, 0x1004 * ' ')
|
uc.mem_write(0x1000, 0x1004 * ' ')
|
||||||
print 'Not reached on x86_64 Linux.'
|
print 'If not reached, then we have BUG (crash on x86_64 Linux).'
|
||||||
|
|
86
uc.c
86
uc.c
|
@ -340,6 +340,26 @@ uc_err uc_reg_write(uch handle, int regid, const void *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check if a memory area is mapped
|
||||||
|
// this is complicated because an area can overlap adjacent blocks
|
||||||
|
static bool check_mem_area(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
|
{
|
||||||
|
size_t count = 0, len;
|
||||||
|
|
||||||
|
while(count < size) {
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, address);
|
||||||
|
if (mr) {
|
||||||
|
len = MIN(size - count, mr->end - address);
|
||||||
|
count += len;
|
||||||
|
address += len;
|
||||||
|
} else // this address is not mapped in yet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count == size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
|
uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -349,39 +369,73 @@ uc_err uc_mem_read(uch handle, uint64_t address, uint8_t *bytes, size_t size)
|
||||||
// invalid handle
|
// invalid handle
|
||||||
return UC_ERR_UCH;
|
return UC_ERR_UCH;
|
||||||
|
|
||||||
if (uc->read_mem(&uc->as, address, bytes, size) == false)
|
if (!check_mem_area(uc, address, size))
|
||||||
return UC_ERR_MEM_READ;
|
return UC_ERR_MEM_READ;
|
||||||
|
|
||||||
return UC_ERR_OK;
|
size_t count = 0, len;
|
||||||
|
|
||||||
|
// memory area can overlap adjacent memory blocks
|
||||||
|
while(count < size) {
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, address);
|
||||||
|
if (mr) {
|
||||||
|
len = MIN(size - count, mr->end - address);
|
||||||
|
if (uc->read_mem(&uc->as, address, bytes, len) == false)
|
||||||
|
break;
|
||||||
|
count += len;
|
||||||
|
address += len;
|
||||||
|
bytes += len;
|
||||||
|
} else // this address is not mapped in yet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == size)
|
||||||
|
return UC_ERR_OK;
|
||||||
|
else
|
||||||
|
return UC_ERR_MEM_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size)
|
uc_err uc_mem_write(uch handle, uint64_t address, const uint8_t *bytes, size_t size)
|
||||||
{
|
{
|
||||||
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
struct uc_struct *uc = (struct uc_struct *)(uintptr_t)handle;
|
||||||
uint32_t operms;
|
|
||||||
|
|
||||||
if (handle == 0)
|
if (handle == 0)
|
||||||
// invalid handle
|
// invalid handle
|
||||||
return UC_ERR_UCH;
|
return UC_ERR_UCH;
|
||||||
|
|
||||||
MemoryRegion *mr = memory_mapping(uc, address);
|
if (!check_mem_area(uc, address, size))
|
||||||
if (mr == NULL)
|
|
||||||
return UC_ERR_MEM_WRITE;
|
return UC_ERR_MEM_WRITE;
|
||||||
|
|
||||||
operms = mr->perms;
|
size_t count = 0, len;
|
||||||
if (!(operms & UC_PROT_WRITE)) //write protected
|
|
||||||
//but this is not the program accessing memory, so temporarily mark writable
|
|
||||||
uc->readonly_mem(mr, false);
|
|
||||||
|
|
||||||
if (uc->write_mem(&uc->as, address, bytes, size) == false)
|
// memory area can overlap adjacent memory blocks
|
||||||
|
while(count < size) {
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, address);
|
||||||
|
if (mr) {
|
||||||
|
uint32_t operms = mr->perms;
|
||||||
|
if (!(operms & UC_PROT_WRITE)) // write protected
|
||||||
|
// but this is not the program accessing memory, so temporarily mark writable
|
||||||
|
uc->readonly_mem(mr, false);
|
||||||
|
|
||||||
|
len = MIN(size - count, mr->end - address);
|
||||||
|
if (uc->write_mem(&uc->as, address, bytes, len) == false)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(operms & UC_PROT_WRITE)) // write protected
|
||||||
|
// now write protect it again
|
||||||
|
uc->readonly_mem(mr, true);
|
||||||
|
|
||||||
|
count += len;
|
||||||
|
address += len;
|
||||||
|
bytes += len;
|
||||||
|
} else // this address is not mapped in yet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == size)
|
||||||
|
return UC_ERR_OK;
|
||||||
|
else
|
||||||
return UC_ERR_MEM_WRITE;
|
return UC_ERR_MEM_WRITE;
|
||||||
|
|
||||||
if (!(operms & UC_PROT_WRITE)) //write protected
|
|
||||||
//now write protect it again
|
|
||||||
uc->readonly_mem(mr, true);
|
|
||||||
|
|
||||||
return UC_ERR_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIMEOUT_STEP 2 // microseconds
|
#define TIMEOUT_STEP 2 // microseconds
|
||||||
|
|
Loading…
Reference in a new issue