/* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { struct shared_map *shared; struct file *file; unsigned int i; mem_size_t total_size; size_t file_size, map_size, max_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; long toread; /* compute the total size of the shared mapping */ total_size = max_size = 0; for (i = 0; i < nb_sec; i++) { if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); if (file_size > max_size) max_size = file_size; total_size += map_size; } } if (!total_size) return 1; /* nothing to do */ if ((mapping->shared = get_shared_file( mapping->fd ))) return 1; /* create a temp file for the mapping */ if ((shared_fd = create_temp_file( total_size )) == -1) return 0; if (!(file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) return 0; if (!(buffer = malloc( max_size ))) goto error; /* copy the shared sections data into the temp file */ shared_pos = 0; for (i = 0; i < nb_sec; i++) { if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; get_section_sizes( &sec[i], &map_size, &read_pos, &file_size ); write_pos = shared_pos; shared_pos += map_size; if (!sec[i].PointerToRawData || !file_size) continue; toread = file_size; while (toread) { long res = pread( fd, buffer + file_size - toread, toread, read_pos ); if (!res && toread < 0x200) /* partial sector at EOF is not an error */ { file_size -= toread; break; } if (res <= 0) goto error; toread -= res; read_pos += res; } if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error; } if (!(shared = alloc_object( &shared_map_ops ))) goto error; shared->fd = (struct fd *)grab_object( mapping->fd ); shared->file = file; list_add_head( &shared_map_list, &shared->entry ); mapping->shared = shared; free( buffer ); return 1; error: release_object( file ); free( buffer ); return 0; }
/* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { unsigned int i, size, max_size, total_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; long toread; /* compute the total size of the shared mapping */ total_size = max_size = 0; for (i = 0; i < nb_sec; i++) { if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { size = get_section_filemap_size( &sec[i] ); if (size > max_size) max_size = size; total_size += get_section_map_size( &sec[i] ); } } if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */ if ((mapping->shared_file = get_shared_file( mapping ))) return 1; /* create a temp file for the mapping */ if (!(mapping->shared_file = create_temp_file( FILE_GENERIC_READ|FILE_GENERIC_WRITE ))) return 0; if (!grow_file( mapping->shared_file, total_size )) goto error; if ((shared_fd = get_file_unix_fd( mapping->shared_file )) == -1) goto error; if (!(buffer = malloc( max_size ))) goto error; /* copy the shared sections data into the temp file */ shared_pos = 0; for (i = 0; i < nb_sec; i++) { if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; write_pos = shared_pos; shared_pos += get_section_map_size( &sec[i] ); read_pos = sec[i].PointerToRawData; size = get_section_filemap_size( &sec[i] ); if (!read_pos || !size) continue; toread = size; while (toread) { long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos ); if (res <= 0) goto error; toread -= res; read_pos += res; } if (pwrite( shared_fd, buffer, size, write_pos ) != size) goto error; } free( buffer ); return 1; error: release_object( mapping->shared_file ); mapping->shared_file = NULL; if (buffer) free( buffer ); return 0; }