implement simple memory snapshot mechanismus
Uses Copy on Write to make it posible to restore the memory state after a snapshot was made. To restore all MemoryRegions created after the snapshot are removed.
This commit is contained in:
parent
065af19dc5
commit
80bd825420
|
@ -80,6 +80,10 @@ typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr,
|
||||||
typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||||
int len);
|
int len);
|
||||||
|
|
||||||
|
typedef MemoryRegion* (*uc_mem_cow_t)(struct uc_struct *uc,
|
||||||
|
MemoryRegion *current, hwaddr begin,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
typedef void (*uc_args_void_t)(void *);
|
typedef void (*uc_args_void_t)(void *);
|
||||||
|
|
||||||
typedef void (*uc_args_uc_t)(struct uc_struct *);
|
typedef void (*uc_args_uc_t)(struct uc_struct *);
|
||||||
|
@ -102,6 +106,8 @@ typedef void (*uc_mem_unmap_t)(struct uc_struct *, MemoryRegion *mr);
|
||||||
|
|
||||||
typedef MemoryRegion *(*uc_memory_mapping_t)(struct uc_struct *, hwaddr addr);
|
typedef MemoryRegion *(*uc_memory_mapping_t)(struct uc_struct *, hwaddr addr);
|
||||||
|
|
||||||
|
typedef void (*uc_memory_filter_t)(MemoryRegion *, int32_t);
|
||||||
|
|
||||||
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
|
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
|
||||||
|
|
||||||
typedef int (*uc_cpus_init)(struct uc_struct *, const char *);
|
typedef int (*uc_cpus_init)(struct uc_struct *, const char *);
|
||||||
|
@ -267,6 +273,7 @@ struct uc_struct {
|
||||||
|
|
||||||
uc_write_mem_t write_mem;
|
uc_write_mem_t write_mem;
|
||||||
uc_read_mem_t read_mem;
|
uc_read_mem_t read_mem;
|
||||||
|
uc_mem_cow_t memory_cow;
|
||||||
uc_args_void_t release; // release resource when uc_close()
|
uc_args_void_t release; // release resource when uc_close()
|
||||||
uc_args_uc_u64_t set_pc; // set PC for tracecode
|
uc_args_uc_u64_t set_pc; // set PC for tracecode
|
||||||
uc_get_pc_t get_pc;
|
uc_get_pc_t get_pc;
|
||||||
|
@ -280,6 +287,7 @@ struct uc_struct {
|
||||||
uc_args_uc_ram_size_t memory_map;
|
uc_args_uc_ram_size_t memory_map;
|
||||||
uc_args_uc_ram_size_ptr_t memory_map_ptr;
|
uc_args_uc_ram_size_ptr_t memory_map_ptr;
|
||||||
uc_memory_mapping_t memory_mapping;
|
uc_memory_mapping_t memory_mapping;
|
||||||
|
uc_memory_filter_t memory_filter_subregions;
|
||||||
uc_mem_unmap_t memory_unmap;
|
uc_mem_unmap_t memory_unmap;
|
||||||
uc_readonly_mem_t readonly_mem;
|
uc_readonly_mem_t readonly_mem;
|
||||||
uc_cpus_init cpus_init;
|
uc_cpus_init cpus_init;
|
||||||
|
@ -403,6 +411,7 @@ struct uc_struct {
|
||||||
PVOID seh_handle;
|
PVOID seh_handle;
|
||||||
void *seh_closure;
|
void *seh_closure;
|
||||||
#endif
|
#endif
|
||||||
|
int32_t snapshot_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
||||||
|
|
|
@ -1345,6 +1345,12 @@ size_t uc_context_size(uc_engine *uc);
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_context_free(uc_context *context);
|
uc_err uc_context_free(uc_context *context);
|
||||||
|
|
||||||
|
UNICORN_EXPORT
|
||||||
|
uc_err uc_snapshot(uc_engine *uc);
|
||||||
|
|
||||||
|
UNICORN_EXPORT
|
||||||
|
uc_err uc_restore_latest_snapshot(uc_engine *uc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_aarch64
|
#define memory_map memory_map_aarch64
|
||||||
#define memory_map_io memory_map_io_aarch64
|
#define memory_map_io memory_map_io_aarch64
|
||||||
#define memory_map_ptr memory_map_ptr_aarch64
|
#define memory_map_ptr memory_map_ptr_aarch64
|
||||||
|
#define memory_cow memory_cow_aarch64
|
||||||
#define memory_unmap memory_unmap_aarch64
|
#define memory_unmap memory_unmap_aarch64
|
||||||
#define memory_free memory_free_aarch64
|
#define memory_free memory_free_aarch64
|
||||||
#define flatview_unref flatview_unref_aarch64
|
#define flatview_unref flatview_unref_aarch64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_aarch64
|
#define memory_region_del_subregion memory_region_del_subregion_aarch64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_aarch64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_aarch64
|
||||||
#define memory_region_find memory_region_find_aarch64
|
#define memory_region_find memory_region_find_aarch64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_aarch64
|
||||||
#define memory_listener_register memory_listener_register_aarch64
|
#define memory_listener_register memory_listener_register_aarch64
|
||||||
#define memory_listener_unregister memory_listener_unregister_aarch64
|
#define memory_listener_unregister memory_listener_unregister_aarch64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_aarch64
|
#define address_space_remove_listeners address_space_remove_listeners_aarch64
|
||||||
|
|
|
@ -2155,6 +2155,22 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uc->snapshot_level && mr->ram && mr->priority < uc->snapshot_level) {
|
||||||
|
mr = memory_cow(uc, mr, addr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE);
|
||||||
|
if (!mr) {
|
||||||
|
uc->invalid_addr = paddr;
|
||||||
|
uc->invalid_error = UC_ERR_NOMEM;
|
||||||
|
cpu_exit(uc->cpu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* refill tlb after CoW */
|
||||||
|
tlb_fill(env_cpu(env), paddr, size, MMU_DATA_STORE,
|
||||||
|
mmu_idx, retaddr);
|
||||||
|
index = tlb_index(env, mmu_idx, addr);
|
||||||
|
entry = tlb_entry(env, mmu_idx, addr);
|
||||||
|
tlb_addr = tlb_addr_write(entry);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle anything that isn't just a straight memory access. */
|
/* Handle anything that isn't just a straight memory access. */
|
||||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||||
CPUIOTLBEntry *iotlbentry;
|
CPUIOTLBEntry *iotlbentry;
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_arm
|
#define memory_map memory_map_arm
|
||||||
#define memory_map_io memory_map_io_arm
|
#define memory_map_io memory_map_io_arm
|
||||||
#define memory_map_ptr memory_map_ptr_arm
|
#define memory_map_ptr memory_map_ptr_arm
|
||||||
|
#define memory_cow memory_cow_arm
|
||||||
#define memory_unmap memory_unmap_arm
|
#define memory_unmap memory_unmap_arm
|
||||||
#define memory_free memory_free_arm
|
#define memory_free memory_free_arm
|
||||||
#define flatview_unref flatview_unref_arm
|
#define flatview_unref flatview_unref_arm
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_arm
|
#define memory_region_del_subregion memory_region_del_subregion_arm
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_arm
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_arm
|
||||||
#define memory_region_find memory_region_find_arm
|
#define memory_region_find memory_region_find_arm
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_arm
|
||||||
#define memory_listener_register memory_listener_register_arm
|
#define memory_listener_register memory_listener_register_arm
|
||||||
#define memory_listener_unregister memory_listener_unregister_arm
|
#define memory_listener_unregister memory_listener_unregister_arm
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_arm
|
#define address_space_remove_listeners address_space_remove_listeners_arm
|
||||||
|
|
|
@ -687,6 +687,35 @@ void memory_region_add_subregion(MemoryRegion *mr,
|
||||||
hwaddr offset,
|
hwaddr offset,
|
||||||
MemoryRegion *subregion);
|
MemoryRegion *subregion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* memory_region_add_subregion_overlap: Add a subregion to a container
|
||||||
|
* with overlap.
|
||||||
|
*
|
||||||
|
* Adds a subregion at @offset. The subregion may overlap with other
|
||||||
|
* subregions. Conflicts are resolved by having a higher @priority hide a
|
||||||
|
* lower @priority. Subregions without priority are taken as @priority 0.
|
||||||
|
* A region may only be added once as a subregion (unless removed with
|
||||||
|
* memory_region_del_subregion()); use memory_region_init_alias() if you
|
||||||
|
* want a region to be a subregion in multiple locations.
|
||||||
|
*
|
||||||
|
* @mr: the region to contain the new subregion; must be a container
|
||||||
|
* initialized with memory_region_init().
|
||||||
|
* @offset: the offset relative to @mr where @subregion is added.
|
||||||
|
* @subregion: the subregion to be added.
|
||||||
|
* @priority: used for resolving overlaps; highest priority wins.
|
||||||
|
*/
|
||||||
|
void memory_region_add_subregion_overlap(MemoryRegion *mr,
|
||||||
|
hwaddr offset,
|
||||||
|
MemoryRegion *subregion,
|
||||||
|
int priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* memory_region_filter_subregions: filter subregios by priority.
|
||||||
|
*
|
||||||
|
* remove all subregions beginning by a specified subregion
|
||||||
|
*/
|
||||||
|
void memory_region_filter_subregions(MemoryRegion *mr, int32_t level);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* memory_region_get_ram_addr: Get the ram address associated with a memory
|
* memory_region_get_ram_addr: Get the ram address associated with a memory
|
||||||
* region
|
* region
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_m68k
|
#define memory_map memory_map_m68k
|
||||||
#define memory_map_io memory_map_io_m68k
|
#define memory_map_io memory_map_io_m68k
|
||||||
#define memory_map_ptr memory_map_ptr_m68k
|
#define memory_map_ptr memory_map_ptr_m68k
|
||||||
|
#define memory_cow memory_cow_m68k
|
||||||
#define memory_unmap memory_unmap_m68k
|
#define memory_unmap memory_unmap_m68k
|
||||||
#define memory_free memory_free_m68k
|
#define memory_free memory_free_m68k
|
||||||
#define flatview_unref flatview_unref_m68k
|
#define flatview_unref flatview_unref_m68k
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_m68k
|
#define memory_region_del_subregion memory_region_del_subregion_m68k
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_m68k
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_m68k
|
||||||
#define memory_region_find memory_region_find_m68k
|
#define memory_region_find memory_region_find_m68k
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_m68k
|
||||||
#define memory_listener_register memory_listener_register_m68k
|
#define memory_listener_register memory_listener_register_m68k
|
||||||
#define memory_listener_unregister memory_listener_unregister_m68k
|
#define memory_listener_unregister memory_listener_unregister_m68k
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_m68k
|
#define address_space_remove_listeners address_space_remove_listeners_m68k
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_mips
|
#define memory_map memory_map_mips
|
||||||
#define memory_map_io memory_map_io_mips
|
#define memory_map_io memory_map_io_mips
|
||||||
#define memory_map_ptr memory_map_ptr_mips
|
#define memory_map_ptr memory_map_ptr_mips
|
||||||
|
#define memory_cow memory_cow_mips
|
||||||
#define memory_unmap memory_unmap_mips
|
#define memory_unmap memory_unmap_mips
|
||||||
#define memory_free memory_free_mips
|
#define memory_free memory_free_mips
|
||||||
#define flatview_unref flatview_unref_mips
|
#define flatview_unref flatview_unref_mips
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_mips
|
#define memory_region_del_subregion memory_region_del_subregion_mips
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips
|
||||||
#define memory_region_find memory_region_find_mips
|
#define memory_region_find memory_region_find_mips
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_mips
|
||||||
#define memory_listener_register memory_listener_register_mips
|
#define memory_listener_register memory_listener_register_mips
|
||||||
#define memory_listener_unregister memory_listener_unregister_mips
|
#define memory_listener_unregister memory_listener_unregister_mips
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_mips
|
#define address_space_remove_listeners address_space_remove_listeners_mips
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_mips64
|
#define memory_map memory_map_mips64
|
||||||
#define memory_map_io memory_map_io_mips64
|
#define memory_map_io memory_map_io_mips64
|
||||||
#define memory_map_ptr memory_map_ptr_mips64
|
#define memory_map_ptr memory_map_ptr_mips64
|
||||||
|
#define memory_cow memory_cow_mips64
|
||||||
#define memory_unmap memory_unmap_mips64
|
#define memory_unmap memory_unmap_mips64
|
||||||
#define memory_free memory_free_mips64
|
#define memory_free memory_free_mips64
|
||||||
#define flatview_unref flatview_unref_mips64
|
#define flatview_unref flatview_unref_mips64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_mips64
|
#define memory_region_del_subregion memory_region_del_subregion_mips64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips64
|
||||||
#define memory_region_find memory_region_find_mips64
|
#define memory_region_find memory_region_find_mips64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_mips64
|
||||||
#define memory_listener_register memory_listener_register_mips64
|
#define memory_listener_register memory_listener_register_mips64
|
||||||
#define memory_listener_unregister memory_listener_unregister_mips64
|
#define memory_listener_unregister memory_listener_unregister_mips64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_mips64
|
#define address_space_remove_listeners address_space_remove_listeners_mips64
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_mips64el
|
#define memory_map memory_map_mips64el
|
||||||
#define memory_map_io memory_map_io_mips64el
|
#define memory_map_io memory_map_io_mips64el
|
||||||
#define memory_map_ptr memory_map_ptr_mips64el
|
#define memory_map_ptr memory_map_ptr_mips64el
|
||||||
|
#define memory_cow memory_cow_mips64el
|
||||||
#define memory_unmap memory_unmap_mips64el
|
#define memory_unmap memory_unmap_mips64el
|
||||||
#define memory_free memory_free_mips64el
|
#define memory_free memory_free_mips64el
|
||||||
#define flatview_unref flatview_unref_mips64el
|
#define flatview_unref flatview_unref_mips64el
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_mips64el
|
#define memory_region_del_subregion memory_region_del_subregion_mips64el
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips64el
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mips64el
|
||||||
#define memory_region_find memory_region_find_mips64el
|
#define memory_region_find memory_region_find_mips64el
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_mips64el
|
||||||
#define memory_listener_register memory_listener_register_mips64el
|
#define memory_listener_register memory_listener_register_mips64el
|
||||||
#define memory_listener_unregister memory_listener_unregister_mips64el
|
#define memory_listener_unregister memory_listener_unregister_mips64el
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_mips64el
|
#define address_space_remove_listeners address_space_remove_listeners_mips64el
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_mipsel
|
#define memory_map memory_map_mipsel
|
||||||
#define memory_map_io memory_map_io_mipsel
|
#define memory_map_io memory_map_io_mipsel
|
||||||
#define memory_map_ptr memory_map_ptr_mipsel
|
#define memory_map_ptr memory_map_ptr_mipsel
|
||||||
|
#define memory_cow memory_cow_mipsel
|
||||||
#define memory_unmap memory_unmap_mipsel
|
#define memory_unmap memory_unmap_mipsel
|
||||||
#define memory_free memory_free_mipsel
|
#define memory_free memory_free_mipsel
|
||||||
#define flatview_unref flatview_unref_mipsel
|
#define flatview_unref flatview_unref_mipsel
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_mipsel
|
#define memory_region_del_subregion memory_region_del_subregion_mipsel
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mipsel
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_mipsel
|
||||||
#define memory_region_find memory_region_find_mipsel
|
#define memory_region_find memory_region_find_mipsel
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_mipsel
|
||||||
#define memory_listener_register memory_listener_register_mipsel
|
#define memory_listener_register memory_listener_register_mipsel
|
||||||
#define memory_listener_unregister memory_listener_unregister_mipsel
|
#define memory_listener_unregister memory_listener_unregister_mipsel
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_mipsel
|
#define address_space_remove_listeners address_space_remove_listeners_mipsel
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_ppc
|
#define memory_map memory_map_ppc
|
||||||
#define memory_map_io memory_map_io_ppc
|
#define memory_map_io memory_map_io_ppc
|
||||||
#define memory_map_ptr memory_map_ptr_ppc
|
#define memory_map_ptr memory_map_ptr_ppc
|
||||||
|
#define memory_cow memory_cow_ppc
|
||||||
#define memory_unmap memory_unmap_ppc
|
#define memory_unmap memory_unmap_ppc
|
||||||
#define memory_free memory_free_ppc
|
#define memory_free memory_free_ppc
|
||||||
#define flatview_unref flatview_unref_ppc
|
#define flatview_unref flatview_unref_ppc
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_ppc
|
#define memory_region_del_subregion memory_region_del_subregion_ppc
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_ppc
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_ppc
|
||||||
#define memory_region_find memory_region_find_ppc
|
#define memory_region_find memory_region_find_ppc
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_ppc
|
||||||
#define memory_listener_register memory_listener_register_ppc
|
#define memory_listener_register memory_listener_register_ppc
|
||||||
#define memory_listener_unregister memory_listener_unregister_ppc
|
#define memory_listener_unregister memory_listener_unregister_ppc
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_ppc
|
#define address_space_remove_listeners address_space_remove_listeners_ppc
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_ppc64
|
#define memory_map memory_map_ppc64
|
||||||
#define memory_map_io memory_map_io_ppc64
|
#define memory_map_io memory_map_io_ppc64
|
||||||
#define memory_map_ptr memory_map_ptr_ppc64
|
#define memory_map_ptr memory_map_ptr_ppc64
|
||||||
|
#define memory_cow memory_cow_ppc64
|
||||||
#define memory_unmap memory_unmap_ppc64
|
#define memory_unmap memory_unmap_ppc64
|
||||||
#define memory_free memory_free_ppc64
|
#define memory_free memory_free_ppc64
|
||||||
#define flatview_unref flatview_unref_ppc64
|
#define flatview_unref flatview_unref_ppc64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_ppc64
|
#define memory_region_del_subregion memory_region_del_subregion_ppc64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_ppc64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_ppc64
|
||||||
#define memory_region_find memory_region_find_ppc64
|
#define memory_region_find memory_region_find_ppc64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_ppc64
|
||||||
#define memory_listener_register memory_listener_register_ppc64
|
#define memory_listener_register memory_listener_register_ppc64
|
||||||
#define memory_listener_unregister memory_listener_unregister_ppc64
|
#define memory_listener_unregister memory_listener_unregister_ppc64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_ppc64
|
#define address_space_remove_listeners address_space_remove_listeners_ppc64
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_riscv32
|
#define memory_map memory_map_riscv32
|
||||||
#define memory_map_io memory_map_io_riscv32
|
#define memory_map_io memory_map_io_riscv32
|
||||||
#define memory_map_ptr memory_map_ptr_riscv32
|
#define memory_map_ptr memory_map_ptr_riscv32
|
||||||
|
#define memory_cow memory_cow_riscv32
|
||||||
#define memory_unmap memory_unmap_riscv32
|
#define memory_unmap memory_unmap_riscv32
|
||||||
#define memory_free memory_free_riscv32
|
#define memory_free memory_free_riscv32
|
||||||
#define flatview_unref flatview_unref_riscv32
|
#define flatview_unref flatview_unref_riscv32
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_riscv32
|
#define memory_region_del_subregion memory_region_del_subregion_riscv32
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_riscv32
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_riscv32
|
||||||
#define memory_region_find memory_region_find_riscv32
|
#define memory_region_find memory_region_find_riscv32
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_riscv32
|
||||||
#define memory_listener_register memory_listener_register_riscv32
|
#define memory_listener_register memory_listener_register_riscv32
|
||||||
#define memory_listener_unregister memory_listener_unregister_riscv32
|
#define memory_listener_unregister memory_listener_unregister_riscv32
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_riscv32
|
#define address_space_remove_listeners address_space_remove_listeners_riscv32
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_riscv64
|
#define memory_map memory_map_riscv64
|
||||||
#define memory_map_io memory_map_io_riscv64
|
#define memory_map_io memory_map_io_riscv64
|
||||||
#define memory_map_ptr memory_map_ptr_riscv64
|
#define memory_map_ptr memory_map_ptr_riscv64
|
||||||
|
#define memory_cow memory_cow_riscv64
|
||||||
#define memory_unmap memory_unmap_riscv64
|
#define memory_unmap memory_unmap_riscv64
|
||||||
#define memory_free memory_free_riscv64
|
#define memory_free memory_free_riscv64
|
||||||
#define flatview_unref flatview_unref_riscv64
|
#define flatview_unref flatview_unref_riscv64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_riscv64
|
#define memory_region_del_subregion memory_region_del_subregion_riscv64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_riscv64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_riscv64
|
||||||
#define memory_region_find memory_region_find_riscv64
|
#define memory_region_find memory_region_find_riscv64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_riscv64
|
||||||
#define memory_listener_register memory_listener_register_riscv64
|
#define memory_listener_register memory_listener_register_riscv64
|
||||||
#define memory_listener_unregister memory_listener_unregister_riscv64
|
#define memory_listener_unregister memory_listener_unregister_riscv64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_riscv64
|
#define address_space_remove_listeners address_space_remove_listeners_riscv64
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_s390x
|
#define memory_map memory_map_s390x
|
||||||
#define memory_map_io memory_map_io_s390x
|
#define memory_map_io memory_map_io_s390x
|
||||||
#define memory_map_ptr memory_map_ptr_s390x
|
#define memory_map_ptr memory_map_ptr_s390x
|
||||||
|
#define memory_cow memory_cow_s390x
|
||||||
#define memory_unmap memory_unmap_s390x
|
#define memory_unmap memory_unmap_s390x
|
||||||
#define memory_free memory_free_s390x
|
#define memory_free memory_free_s390x
|
||||||
#define flatview_unref flatview_unref_s390x
|
#define flatview_unref flatview_unref_s390x
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_s390x
|
#define memory_region_del_subregion memory_region_del_subregion_s390x
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_s390x
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_s390x
|
||||||
#define memory_region_find memory_region_find_s390x
|
#define memory_region_find memory_region_find_s390x
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_s390x
|
||||||
#define memory_listener_register memory_listener_register_s390x
|
#define memory_listener_register memory_listener_register_s390x
|
||||||
#define memory_listener_unregister memory_listener_unregister_s390x
|
#define memory_listener_unregister memory_listener_unregister_s390x
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_s390x
|
#define address_space_remove_listeners address_space_remove_listeners_s390x
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
//#define DEBUG_UNASSIGNED
|
//#define DEBUG_UNASSIGNED
|
||||||
|
|
||||||
|
void memory_region_transaction_begin(void);
|
||||||
|
void memory_region_transaction_commit(MemoryRegion *mr);
|
||||||
|
|
||||||
typedef struct AddrRange AddrRange;
|
typedef struct AddrRange AddrRange;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -49,7 +52,7 @@ MemoryRegion *memory_map(struct uc_struct *uc, hwaddr begin, size_t size, uint32
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_region_add_subregion(uc->system_memory, begin, ram);
|
memory_region_add_subregion_overlap(uc->system_memory, begin, ram, uc->snapshot_level);
|
||||||
|
|
||||||
if (uc->cpu) {
|
if (uc->cpu) {
|
||||||
tlb_flush(uc->cpu);
|
tlb_flush(uc->cpu);
|
||||||
|
@ -79,6 +82,48 @@ MemoryRegion *memory_map_ptr(struct uc_struct *uc, hwaddr begin, size_t size, ui
|
||||||
return ram;
|
return ram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void make_contained(struct uc_struct *uc, MemoryRegion *current)
|
||||||
|
{
|
||||||
|
hwaddr addr = current->addr;
|
||||||
|
MemoryRegion *container = g_new(MemoryRegion, 1);
|
||||||
|
memory_region_init(uc, container, int128_get64(current->size));
|
||||||
|
memory_region_del_subregion(uc->system_memory, current);
|
||||||
|
memory_region_add_subregion_overlap(container, 0, current, current->priority);
|
||||||
|
memory_region_add_subregion(uc->system_memory, addr, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryRegion *memory_cow(struct uc_struct *uc, MemoryRegion *current, hwaddr begin, size_t size)
|
||||||
|
{
|
||||||
|
hwaddr offset;
|
||||||
|
hwaddr current_offset;
|
||||||
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
|
|
||||||
|
if (current->container == uc->system_memory) {
|
||||||
|
make_contained(uc, current);
|
||||||
|
}
|
||||||
|
offset = begin - current->container->addr;;
|
||||||
|
current_offset = offset - current->addr;
|
||||||
|
|
||||||
|
memory_region_init_ram(uc, ram, size, current->perms);
|
||||||
|
if (ram->addr == -1 || !ram->ram_block) {
|
||||||
|
g_free(ram);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memory_region_transaction_begin();
|
||||||
|
|
||||||
|
memcpy(ramblock_ptr(ram->ram_block, 0), ramblock_ptr(current->ram_block, current_offset), size);
|
||||||
|
memory_region_add_subregion_overlap(current->container, offset, ram, uc->snapshot_level);
|
||||||
|
|
||||||
|
if (uc->cpu) {
|
||||||
|
tlb_flush(uc->cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
uc->memory_region_update_pending = true;
|
||||||
|
memory_region_transaction_commit(ram);
|
||||||
|
|
||||||
|
return ram;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t mmio_read_wrapper(struct uc_struct *uc, void *opaque, hwaddr addr, unsigned size)
|
static uint64_t mmio_read_wrapper(struct uc_struct *uc, void *opaque, hwaddr addr, unsigned size)
|
||||||
{
|
{
|
||||||
mmio_cbs* cbs = (mmio_cbs*)opaque;
|
mmio_cbs* cbs = (mmio_cbs*)opaque;
|
||||||
|
@ -148,6 +193,21 @@ MemoryRegion *memory_map_io(struct uc_struct *uc, ram_addr_t begin, size_t size,
|
||||||
return mmio;
|
return mmio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memory_region_filter_subregions(MemoryRegion *mr, int32_t level)
|
||||||
|
{
|
||||||
|
MemoryRegion *subregion, *subregion_next;
|
||||||
|
memory_region_transaction_begin();
|
||||||
|
QTAILQ_FOREACH_SAFE(subregion, &mr->subregions, subregions_link, subregion_next) {
|
||||||
|
if (subregion->priority >= level) {
|
||||||
|
memory_region_del_subregion(mr, subregion);
|
||||||
|
subregion->destructor(subregion);
|
||||||
|
g_free(subregion);
|
||||||
|
mr->uc->memory_region_update_pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory_region_transaction_commit(mr);
|
||||||
|
}
|
||||||
|
|
||||||
void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
|
void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -179,16 +239,15 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
|
||||||
|
|
||||||
int memory_free(struct uc_struct *uc)
|
int memory_free(struct uc_struct *uc)
|
||||||
{
|
{
|
||||||
int i;
|
MemoryRegion *subregion, *subregion_next;
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr = uc->system_memory;
|
||||||
|
|
||||||
for (i = 0; i < uc->mapped_block_count; i++) {
|
QTAILQ_FOREACH_SAFE(subregion, &mr->subregions, subregions_link, subregion_next) {
|
||||||
mr = uc->mapped_blocks[i];
|
subregion->enabled = false;
|
||||||
mr->enabled = false;
|
memory_region_del_subregion(uc->system_memory, subregion);
|
||||||
memory_region_del_subregion(uc->system_memory, mr);
|
subregion->destructor(subregion);
|
||||||
mr->destructor(mr);
|
|
||||||
/* destroy subregion */
|
/* destroy subregion */
|
||||||
g_free(mr);
|
g_free(subregion);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -886,6 +945,7 @@ static void memory_region_destructor_none(MemoryRegion *mr)
|
||||||
|
|
||||||
static void memory_region_destructor_ram(MemoryRegion *mr)
|
static void memory_region_destructor_ram(MemoryRegion *mr)
|
||||||
{
|
{
|
||||||
|
memory_region_filter_subregions(mr, 0);
|
||||||
qemu_ram_free(mr->uc, mr->ram_block);
|
qemu_ram_free(mr->uc, mr->ram_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_sparc
|
#define memory_map memory_map_sparc
|
||||||
#define memory_map_io memory_map_io_sparc
|
#define memory_map_io memory_map_io_sparc
|
||||||
#define memory_map_ptr memory_map_ptr_sparc
|
#define memory_map_ptr memory_map_ptr_sparc
|
||||||
|
#define memory_cow memory_cow_sparc
|
||||||
#define memory_unmap memory_unmap_sparc
|
#define memory_unmap memory_unmap_sparc
|
||||||
#define memory_free memory_free_sparc
|
#define memory_free memory_free_sparc
|
||||||
#define flatview_unref flatview_unref_sparc
|
#define flatview_unref flatview_unref_sparc
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_sparc
|
#define memory_region_del_subregion memory_region_del_subregion_sparc
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_sparc
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_sparc
|
||||||
#define memory_region_find memory_region_find_sparc
|
#define memory_region_find memory_region_find_sparc
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_sparc
|
||||||
#define memory_listener_register memory_listener_register_sparc
|
#define memory_listener_register memory_listener_register_sparc
|
||||||
#define memory_listener_unregister memory_listener_unregister_sparc
|
#define memory_listener_unregister memory_listener_unregister_sparc
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_sparc
|
#define address_space_remove_listeners address_space_remove_listeners_sparc
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_sparc64
|
#define memory_map memory_map_sparc64
|
||||||
#define memory_map_io memory_map_io_sparc64
|
#define memory_map_io memory_map_io_sparc64
|
||||||
#define memory_map_ptr memory_map_ptr_sparc64
|
#define memory_map_ptr memory_map_ptr_sparc64
|
||||||
|
#define memory_cow memory_cow_sparc64
|
||||||
#define memory_unmap memory_unmap_sparc64
|
#define memory_unmap memory_unmap_sparc64
|
||||||
#define memory_free memory_free_sparc64
|
#define memory_free memory_free_sparc64
|
||||||
#define flatview_unref flatview_unref_sparc64
|
#define flatview_unref flatview_unref_sparc64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_sparc64
|
#define memory_region_del_subregion memory_region_del_subregion_sparc64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_sparc64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_sparc64
|
||||||
#define memory_region_find memory_region_find_sparc64
|
#define memory_region_find memory_region_find_sparc64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_sparc64
|
||||||
#define memory_listener_register memory_listener_register_sparc64
|
#define memory_listener_register memory_listener_register_sparc64
|
||||||
#define memory_listener_unregister memory_listener_unregister_sparc64
|
#define memory_listener_unregister memory_listener_unregister_sparc64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_sparc64
|
#define address_space_remove_listeners address_space_remove_listeners_sparc64
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_tricore
|
#define memory_map memory_map_tricore
|
||||||
#define memory_map_io memory_map_io_tricore
|
#define memory_map_io memory_map_io_tricore
|
||||||
#define memory_map_ptr memory_map_ptr_tricore
|
#define memory_map_ptr memory_map_ptr_tricore
|
||||||
|
#define memory_cow memory_cow_tricore
|
||||||
#define memory_unmap memory_unmap_tricore
|
#define memory_unmap memory_unmap_tricore
|
||||||
#define memory_free memory_free_tricore
|
#define memory_free memory_free_tricore
|
||||||
#define flatview_unref flatview_unref_tricore
|
#define flatview_unref flatview_unref_tricore
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_tricore
|
#define memory_region_del_subregion memory_region_del_subregion_tricore
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_tricore
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_tricore
|
||||||
#define memory_region_find memory_region_find_tricore
|
#define memory_region_find memory_region_find_tricore
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_tricore
|
||||||
#define memory_listener_register memory_listener_register_tricore
|
#define memory_listener_register memory_listener_register_tricore
|
||||||
#define memory_listener_unregister memory_listener_unregister_tricore
|
#define memory_listener_unregister memory_listener_unregister_tricore
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_tricore
|
#define address_space_remove_listeners address_space_remove_listeners_tricore
|
||||||
|
|
|
@ -137,6 +137,8 @@ static inline void uc_common_init(struct uc_struct* uc)
|
||||||
uc->memory_map_io = memory_map_io;
|
uc->memory_map_io = memory_map_io;
|
||||||
uc->set_tlb = uc_set_tlb;
|
uc->set_tlb = uc_set_tlb;
|
||||||
uc->memory_mapping = find_memory_mapping;
|
uc->memory_mapping = find_memory_mapping;
|
||||||
|
uc->memory_filter_subregions = memory_region_filter_subregions;
|
||||||
|
uc->memory_cow = memory_cow;
|
||||||
|
|
||||||
if (!uc->release)
|
if (!uc->release)
|
||||||
uc->release = release_common;
|
uc->release = release_common;
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define memory_map memory_map_x86_64
|
#define memory_map memory_map_x86_64
|
||||||
#define memory_map_io memory_map_io_x86_64
|
#define memory_map_io memory_map_io_x86_64
|
||||||
#define memory_map_ptr memory_map_ptr_x86_64
|
#define memory_map_ptr memory_map_ptr_x86_64
|
||||||
|
#define memory_cow memory_cow_x86_64
|
||||||
#define memory_unmap memory_unmap_x86_64
|
#define memory_unmap memory_unmap_x86_64
|
||||||
#define memory_free memory_free_x86_64
|
#define memory_free memory_free_x86_64
|
||||||
#define flatview_unref flatview_unref_x86_64
|
#define flatview_unref flatview_unref_x86_64
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#define memory_region_del_subregion memory_region_del_subregion_x86_64
|
#define memory_region_del_subregion memory_region_del_subregion_x86_64
|
||||||
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_x86_64
|
#define memory_region_add_subregion_overlap memory_region_add_subregion_overlap_x86_64
|
||||||
#define memory_region_find memory_region_find_x86_64
|
#define memory_region_find memory_region_find_x86_64
|
||||||
|
#define memory_region_filter_subregions memory_region_filter_subregions_x86_64
|
||||||
#define memory_listener_register memory_listener_register_x86_64
|
#define memory_listener_register memory_listener_register_x86_64
|
||||||
#define memory_listener_unregister memory_listener_unregister_x86_64
|
#define memory_listener_unregister memory_listener_unregister_x86_64
|
||||||
#define address_space_remove_listeners address_space_remove_listeners_x86_64
|
#define address_space_remove_listeners address_space_remove_listeners_x86_64
|
||||||
|
|
|
@ -123,6 +123,7 @@ cpu_inl \
|
||||||
memory_map \
|
memory_map \
|
||||||
memory_map_io \
|
memory_map_io \
|
||||||
memory_map_ptr \
|
memory_map_ptr \
|
||||||
|
memory_cow \
|
||||||
memory_unmap \
|
memory_unmap \
|
||||||
memory_free \
|
memory_free \
|
||||||
flatview_unref \
|
flatview_unref \
|
||||||
|
@ -144,6 +145,7 @@ memory_region_add_subregion \
|
||||||
memory_region_del_subregion \
|
memory_region_del_subregion \
|
||||||
memory_region_add_subregion_overlap \
|
memory_region_add_subregion_overlap \
|
||||||
memory_region_find \
|
memory_region_find \
|
||||||
|
memory_region_filter_subregions \
|
||||||
memory_listener_register \
|
memory_listener_register \
|
||||||
memory_listener_unregister \
|
memory_listener_unregister \
|
||||||
address_space_remove_listeners \
|
address_space_remove_listeners \
|
||||||
|
|
|
@ -275,6 +275,73 @@ static void test_mem_protect_mmio(void)
|
||||||
OK(uc_close(uc));
|
OK(uc_close(uc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_snapshot(void)
|
||||||
|
{
|
||||||
|
uc_engine *uc;
|
||||||
|
uint32_t mem;
|
||||||
|
// mov eax, [0x2020]; inc eax; mov [0x2020], eax
|
||||||
|
char code[] = "\xa1\x20\x20\x00\x00\x00\x00\x00\x00\xff\xc0\xa3\x20\x20\x00"
|
||||||
|
"\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
|
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
||||||
|
OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL));
|
||||||
|
OK(uc_mem_write(uc, 0x1000, code, sizeof(code) - 1));
|
||||||
|
|
||||||
|
OK(uc_mem_map(uc, 0x2000, 0x1000, UC_PROT_ALL));
|
||||||
|
OK(uc_snapshot(uc));
|
||||||
|
|
||||||
|
OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 0));
|
||||||
|
OK(uc_mem_read(uc, 0x2020, &mem, sizeof(mem)));
|
||||||
|
TEST_CHECK(mem == 1);
|
||||||
|
OK(uc_snapshot(uc));
|
||||||
|
OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 0));
|
||||||
|
OK(uc_mem_read(uc, 0x2020, &mem, sizeof(mem)));
|
||||||
|
TEST_CHECK(mem == 2);
|
||||||
|
OK(uc_restore_latest_snapshot(uc));
|
||||||
|
//TODO check mem
|
||||||
|
OK(uc_mem_read(uc, 0x2020, &mem, sizeof(mem)));
|
||||||
|
TEST_CHECK(mem == 1);
|
||||||
|
OK(uc_restore_latest_snapshot(uc));
|
||||||
|
OK(uc_mem_read(uc, 0x2020, &mem, sizeof(mem)));
|
||||||
|
TEST_CHECK(mem == 0);
|
||||||
|
//TODO check mem
|
||||||
|
|
||||||
|
OK(uc_context_free(c0));
|
||||||
|
OK(uc_context_free(c1));
|
||||||
|
OK(uc_close(uc));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_context_snapshot(void)
|
||||||
|
{
|
||||||
|
uc_engine *uc;
|
||||||
|
uc_context *ctx;
|
||||||
|
uint64_t tmp = 1;
|
||||||
|
|
||||||
|
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
||||||
|
OK(uc_ctl_context_use_snapshots(uc, 1));
|
||||||
|
OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL));
|
||||||
|
OK(uc_context_alloc(uc, &ctx));
|
||||||
|
OK(uc_context_save(uc, ctx));
|
||||||
|
|
||||||
|
OK(uc_mem_write(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
TEST_CHECK(tmp == 1);
|
||||||
|
OK(uc_context_restore(uc, ctx));
|
||||||
|
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
TEST_CHECK(tmp == 0);
|
||||||
|
|
||||||
|
tmp = 2;
|
||||||
|
OK(uc_mem_write(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
TEST_CHECK(tmp == 2);
|
||||||
|
OK(uc_context_restore(uc, ctx));
|
||||||
|
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
||||||
|
TEST_CHECK(tmp == 0);
|
||||||
|
|
||||||
|
OK(uc_context_free(ctx));
|
||||||
|
OK(uc_close(uc));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_LIST = {{"test_map_correct", test_map_correct},
|
TEST_LIST = {{"test_map_correct", test_map_correct},
|
||||||
{"test_map_wrapping", test_map_wrapping},
|
{"test_map_wrapping", test_map_wrapping},
|
||||||
{"test_mem_protect", test_mem_protect},
|
{"test_mem_protect", test_mem_protect},
|
||||||
|
@ -286,4 +353,6 @@ TEST_LIST = {{"test_map_correct", test_map_correct},
|
||||||
{"test_map_big_memory", test_map_big_memory},
|
{"test_map_big_memory", test_map_big_memory},
|
||||||
{"test_mem_protect_remove_exec", test_mem_protect_remove_exec},
|
{"test_mem_protect_remove_exec", test_mem_protect_remove_exec},
|
||||||
{"test_mem_protect_mmio", test_mem_protect_mmio},
|
{"test_mem_protect_mmio", test_mem_protect_mmio},
|
||||||
|
{"test_snapshot", test_snapshot},
|
||||||
|
{"test_context_snapshot", test_context_snapshot},
|
||||||
{NULL, NULL}};
|
{NULL, NULL}};
|
||||||
|
|
111
uc.c
111
uc.c
|
@ -31,7 +31,6 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
|
||||||
static void clear_deleted_hooks(uc_engine *uc);
|
static void clear_deleted_hooks(uc_engine *uc);
|
||||||
static MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address);
|
|
||||||
|
|
||||||
static void *hook_insert(struct list *l, struct hook *h)
|
static void *hook_insert(struct list *l, struct hook *h)
|
||||||
{
|
{
|
||||||
|
@ -676,16 +675,27 @@ uc_err uc_reg_write2(uc_engine *uc, int regid, const void *value, size_t *size)
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t memory_region_len(uc_engine *uc, MemoryRegion *mr, uint64_t address, size_t count)
|
||||||
|
{
|
||||||
|
hwaddr end = mr->end;
|
||||||
|
while (mr->container != uc->system_memory) {
|
||||||
|
mr = mr->container;
|
||||||
|
end += mr->addr;
|
||||||
|
}
|
||||||
|
return (size_t)MIN(count, end - address);
|
||||||
|
}
|
||||||
|
|
||||||
// check if a memory area is mapped
|
// check if a memory area is mapped
|
||||||
// this is complicated because an area can overlap adjacent blocks
|
// this is complicated because an area can overlap adjacent blocks
|
||||||
static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
||||||
{
|
{
|
||||||
size_t count = 0, len;
|
size_t count = 0, len;
|
||||||
|
|
||||||
|
|
||||||
while (count < size) {
|
while (count < size) {
|
||||||
MemoryRegion *mr = find_memory_region(uc, address);
|
MemoryRegion *mr = uc->memory_mapping(uc, address);
|
||||||
if (mr) {
|
if (mr) {
|
||||||
len = (size_t)MIN(size - count, mr->end - address);
|
len = memory_region_len(uc, mr, address, size - count);
|
||||||
count += len;
|
count += len;
|
||||||
address += len;
|
address += len;
|
||||||
} else { // this address is not mapped in yet
|
} else { // this address is not mapped in yet
|
||||||
|
@ -714,9 +724,9 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size)
|
||||||
|
|
||||||
// memory area can overlap adjacent memory blocks
|
// memory area can overlap adjacent memory blocks
|
||||||
while (count < size) {
|
while (count < size) {
|
||||||
MemoryRegion *mr = find_memory_region(uc, address);
|
MemoryRegion *mr = uc->memory_mapping(uc, address);
|
||||||
if (mr) {
|
if (mr) {
|
||||||
len = (size_t)MIN(size - count, mr->end - address);
|
len = memory_region_len(uc, mr, address, size - count);
|
||||||
if (uc->read_mem(&uc->address_space_memory, address, bytes, len) ==
|
if (uc->read_mem(&uc->address_space_memory, address, bytes, len) ==
|
||||||
false) {
|
false) {
|
||||||
break;
|
break;
|
||||||
|
@ -755,7 +765,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
||||||
|
|
||||||
// memory area can overlap adjacent memory blocks
|
// memory area can overlap adjacent memory blocks
|
||||||
while (count < size) {
|
while (count < size) {
|
||||||
MemoryRegion *mr = find_memory_region(uc, address);
|
MemoryRegion *mr = uc->memory_mapping(uc, address);
|
||||||
if (mr) {
|
if (mr) {
|
||||||
uint32_t operms = mr->perms;
|
uint32_t operms = mr->perms;
|
||||||
if (!(operms & UC_PROT_WRITE)) { // write protected
|
if (!(operms & UC_PROT_WRITE)) { // write protected
|
||||||
|
@ -764,7 +774,13 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
||||||
uc->readonly_mem(mr, false);
|
uc->readonly_mem(mr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (size_t)MIN(size - count, mr->end - address);
|
len = memory_region_len(uc, mr, address, size - count);
|
||||||
|
if (uc->snapshot_level && uc->snapshot_level > mr->priority) {
|
||||||
|
mr = uc->memory_cow(uc, mr, address, len);
|
||||||
|
if (!mr) {
|
||||||
|
return UC_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (uc->write_mem(&uc->address_space_memory, address, bytes, len) ==
|
if (uc->write_mem(&uc->address_space_memory, address, bytes, len) ==
|
||||||
false) {
|
false) {
|
||||||
break;
|
break;
|
||||||
|
@ -1480,6 +1496,11 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||||
|
|
||||||
UC_INIT(uc);
|
UC_INIT(uc);
|
||||||
|
|
||||||
|
// snapshot and protection can't be mixed
|
||||||
|
if (uc->snapshot_level > 0) {
|
||||||
|
return UC_ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
// trivial case, no change
|
// trivial case, no change
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
|
@ -1501,6 +1522,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that user's entire requested block is mapped
|
// check that user's entire requested block is mapped
|
||||||
|
//TODO check if protected is possible
|
||||||
|
//deny after cow
|
||||||
if (!check_mem_area(uc, address, size)) {
|
if (!check_mem_area(uc, address, size)) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
@ -1510,14 +1533,14 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||||
addr = address;
|
addr = address;
|
||||||
count = 0;
|
count = 0;
|
||||||
while (count < size) {
|
while (count < size) {
|
||||||
mr = find_memory_region(uc, addr);
|
mr = uc->memory_mapping(uc, addr);
|
||||||
len = (size_t)MIN(size - count, mr->end - addr);
|
len = memory_region_len(uc, mr, addr, size - count);
|
||||||
if (mr->ram) {
|
if (mr->ram) {
|
||||||
if (!split_region(uc, mr, addr, len, false)) {
|
if (!split_region(uc, mr, addr, len, false)) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mr = find_memory_region(uc, addr);
|
mr = uc->memory_mapping(uc, addr);
|
||||||
// will this remove EXEC permission?
|
// will this remove EXEC permission?
|
||||||
if (((mr->perms & UC_PROT_EXEC) != 0) &&
|
if (((mr->perms & UC_PROT_EXEC) != 0) &&
|
||||||
((perms & UC_PROT_EXEC) == 0)) {
|
((perms & UC_PROT_EXEC) == 0)) {
|
||||||
|
@ -1531,7 +1554,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mr = find_memory_region(uc, addr);
|
mr = uc->memory_mapping(uc, addr);
|
||||||
mr->perms = perms;
|
mr->perms = perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1561,6 +1584,11 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
|
|
||||||
UC_INIT(uc);
|
UC_INIT(uc);
|
||||||
|
|
||||||
|
// snapshot and unmapping can't be mixed
|
||||||
|
if (uc->snapshot_level > 0) {
|
||||||
|
return UC_ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
// nothing to unmap
|
// nothing to unmap
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
|
@ -1577,6 +1605,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that user's entire requested block is mapped
|
// check that user's entire requested block is mapped
|
||||||
|
// TODO check for cow
|
||||||
if (!check_mem_area(uc, address, size)) {
|
if (!check_mem_area(uc, address, size)) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
@ -1586,8 +1615,8 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
addr = address;
|
addr = address;
|
||||||
count = 0;
|
count = 0;
|
||||||
while (count < size) {
|
while (count < size) {
|
||||||
mr = find_memory_region(uc, addr);
|
mr = uc->memory_mapping(uc, addr);
|
||||||
len = (size_t)MIN(size - count, mr->end - addr);
|
len = memory_region_len(uc, mr, addr, size - count);
|
||||||
if (!mr->ram) {
|
if (!mr->ram) {
|
||||||
if (!split_mmio_region(uc, mr, addr, len, true)) {
|
if (!split_mmio_region(uc, mr, addr, len, true)) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
|
@ -1600,7 +1629,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
|
|
||||||
// if we can retrieve the mapping, then no splitting took place
|
// if we can retrieve the mapping, then no splitting took place
|
||||||
// so unmap here
|
// so unmap here
|
||||||
mr = find_memory_region(uc, addr);
|
mr = uc->memory_mapping(uc, addr);
|
||||||
if (mr != NULL) {
|
if (mr != NULL) {
|
||||||
uc->memory_unmap(uc, mr);
|
uc->memory_unmap(uc, mr);
|
||||||
}
|
}
|
||||||
|
@ -1611,35 +1640,6 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the memory region of this address
|
|
||||||
static MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (uc->mapped_block_count == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try with the cache index first
|
|
||||||
i = uc->mapped_block_cache_index;
|
|
||||||
|
|
||||||
if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr &&
|
|
||||||
address <= uc->mapped_blocks[i]->end - 1) {
|
|
||||||
return uc->mapped_blocks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
i = bsearch_mapped_blocks(uc, address);
|
|
||||||
|
|
||||||
if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr &&
|
|
||||||
address <= uc->mapped_blocks[i]->end - 1) {
|
|
||||||
uc->mapped_block_cache_index = i;
|
|
||||||
return uc->mapped_blocks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// not found
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
|
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
|
||||||
void *user_data, uint64_t begin, uint64_t end, ...)
|
void *user_data, uint64_t begin, uint64_t end, ...)
|
||||||
|
@ -2598,6 +2598,31 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNICORN_EXPORT
|
||||||
|
uc_err uc_snapshot(struct uc_struct *uc)
|
||||||
|
{
|
||||||
|
if (uc->snapshot_level == INT32_MAX) {
|
||||||
|
return UC_ERR_RESOURCE;
|
||||||
|
}
|
||||||
|
uc->snapshot_level++;
|
||||||
|
return UC_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNICORN_EXPORT
|
||||||
|
uc_err uc_restore_latest_snapshot(struct uc_struct *uc)
|
||||||
|
{
|
||||||
|
MemoryRegion *subregion, *subregion_next;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH_SAFE(subregion, &uc->system_memory->subregions, subregions_link, subregion_next) {
|
||||||
|
uc->memory_filter_subregions(subregion, uc->snapshot_level);
|
||||||
|
if (QTAILQ_EMPTY(&subregion->subregions)) {
|
||||||
|
uc->memory_unmap(uc, subregion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uc->snapshot_level--;
|
||||||
|
return UC_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef UNICORN_TRACER
|
#ifdef UNICORN_TRACER
|
||||||
uc_tracer *get_tracer()
|
uc_tracer *get_tracer()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue