void file_set_name( vmi_instance_t vmi, char *name) { file_get_instance(vmi)->filename = strndup(name, 500); }
status_t file_init( vmi_instance_t vmi) { FILE *fhandle = NULL; int fd = -1; file_instance_t *fi = file_get_instance(vmi); /* open handle to memory file */ if ((fhandle = fopen(fi->filename, "rb")) == NULL) { errprint("Failed to open file for reading.\n"); goto fail; } fd = fileno(fhandle); fi->fhandle = fhandle; fi->fd = fd; memory_cache_init(vmi, file_get_memory, file_release_memory, ULONG_MAX); // memory_cache_init(vmi, file_get_memory, file_release_memory, 0); #if USE_MMAP /* try memory mapped file I/O */ uint64_t size = 0; if (VMI_FAILURE == file_get_memsize(vmi, &size)) { goto fail; } // if int mmap_flags = (MAP_PRIVATE | MAP_NORESERVE | MAP_POPULATE); #ifdef MMAP_HUGETLB // since kernel 2.6.32 mmap_flags |= MMAP_HUGETLB; #endif // MMAP_HUGETLB void *map = mmap(NULL, // addr size, // len PROT_READ, // prot mmap_flags, // flags fd, // file descriptor (off_t) 0); // offset if (MAP_FAILED == map) { perror("Failed to mmap file"); goto fail; } fi->map = map; // Note: madvise(.., MADV_SEQUENTIAL | MADV_WILLNEED) does not seem to // improve performance #endif // USE_MMAP vmi->hvm = 0; return VMI_SUCCESS; fail: file_destroy(vmi); return VMI_FAILURE; }
status_t file_get_name( vmi_instance_t vmi, char **name) { *name = strdup(file_get_instance(vmi)->filename); return VMI_SUCCESS; }
void * file_get_memory( vmi_instance_t vmi, addr_t paddr, uint32_t length) { void *memory = 0; if (paddr + length >= vmi->max_physical_address) { dbprint (VMI_DEBUG_FILE, "--%s: request for PA range [0x%.16"PRIx64"-0x%.16"PRIx64"] reads past end of file\n", __FUNCTION__, paddr, paddr + length); goto error_noprint; } // if memory = safe_malloc(length); #if USE_MMAP (void) memcpy(memory, ((uint8_t *) file_get_instance(vmi)->map) + paddr, length); #else off_t rc = lseek(file_get_instance(vmi)->fd, paddr, SEEK_SET); if ( rc < 0 || (addr_t)rc != paddr ) { goto error_print; } ssize_t rc2 = read(file_get_instance(vmi)->fd, memory, length); if ( rc2 < 0 || (size_t)rc2 != length ) { goto error_print; } #endif // USE_MMAP return memory; error_print: dbprint(VMI_DEBUG_WRITE, "%s: failed to read %d bytes at " "PA (offset) 0x%.16"PRIx64" [VM size 0x%.16"PRIx64"]\n", __FUNCTION__, length, paddr, vmi->allocated_ram_size); error_noprint: if (memory) free(memory); return NULL; }
status_t file_get_memsize( vmi_instance_t vmi, uint64_t *size) { status_t ret = VMI_FAILURE; struct stat s; if (fstat(file_get_instance(vmi)->fd, &s) == -1) { errprint("Failed to stat file.\n"); goto error_exit; } *size = s.st_size; ret = VMI_SUCCESS; error_exit: return ret; }
void file_destroy( vmi_instance_t vmi) { file_instance_t *fi = file_get_instance(vmi); #if USE_MMAP if (fi->map) { (void) munmap(fi->map, vmi->size); fi->map = 0; } #endif // USE_MMAP // fi->fhandle refers to fi->fd; closing both would be an error if (fi->fhandle) { fclose(fi->fhandle); fi->fhandle = 0; fi->fd = 0; } }
status_t file_get_memsize( vmi_instance_t vmi, uint64_t *allocated_ram_size, addr_t *max_physical_address) { status_t ret = VMI_FAILURE; struct stat s; if (fstat(file_get_instance(vmi)->fd, &s) == -1) { errprint("Failed to stat file.\n"); goto error_exit; } *allocated_ram_size = s.st_size; *max_physical_address = s.st_size; ret = VMI_SUCCESS; error_exit: return ret; }