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(0x2000, 0x4000)
|
||||
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
|
||||
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
|
||||
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_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
|
||||
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;
|
||||
uint32_t operms;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
return UC_ERR_UCH;
|
||||
|
||||
MemoryRegion *mr = memory_mapping(uc, address);
|
||||
if (mr == NULL)
|
||||
if (!check_mem_area(uc, address, size))
|
||||
return UC_ERR_MEM_WRITE;
|
||||
|
||||
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);
|
||||
size_t count = 0, len;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user