server: Add a separate object to store the PE shared mapping file.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-10-04 10:06:14 +02:00
parent b34ea10112
commit 71903899aa
1 changed files with 74 additions and 26 deletions

View File

@ -81,6 +81,42 @@ static const struct object_ops ranges_ops =
ranges_destroy /* destroy */ ranges_destroy /* destroy */
}; };
/* file backing the shared sections of a PE image mapping */
struct shared_map
{
struct object obj; /* object header */
struct fd *fd; /* file descriptor of the mapped PE file */
struct file *file; /* temp file holding the shared data */
struct list entry; /* entry in global shared maps list */
};
static void shared_map_dump( struct object *obj, int verbose );
static void shared_map_destroy( struct object *obj );
static const struct object_ops shared_map_ops =
{
sizeof(struct shared_map), /* size */
shared_map_dump, /* dump */
no_get_type, /* get_type */
no_add_queue, /* add_queue */
NULL, /* remove_queue */
NULL, /* signaled */
NULL, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
no_map_access, /* map_access */
default_get_sd, /* get_sd */
default_set_sd, /* set_sd */
no_lookup_name, /* lookup_name */
no_link_name, /* link_name */
NULL, /* unlink_name */
no_open_file, /* open_file */
no_close_handle, /* close_handle */
shared_map_destroy /* destroy */
};
static struct list shared_map_list = LIST_INIT( shared_map_list );
/* memory view mapped in client address space */ /* memory view mapped in client address space */
struct memory_view struct memory_view
{ {
@ -102,8 +138,7 @@ struct mapping
enum cpu_type cpu; /* client CPU (for PE image mapping) */ enum cpu_type cpu; /* client CPU (for PE image mapping) */
pe_image_info_t image; /* image info (for PE image mapping) */ pe_image_info_t image; /* image info (for PE image mapping) */
struct ranges *committed; /* list of committed ranges in this mapping */ struct ranges *committed; /* list of committed ranges in this mapping */
struct file *shared_file; /* temp file for shared PE mapping */ struct shared_map *shared; /* temp file for shared PE mapping */
struct list shared_entry; /* entry in global shared PE mappings list */
}; };
static void mapping_dump( struct object *obj, int verbose ); static void mapping_dump( struct object *obj, int verbose );
@ -149,8 +184,6 @@ static const struct fd_ops mapping_fd_ops =
default_fd_reselect_async /* reselect_async */ default_fd_reselect_async /* reselect_async */
}; };
static struct list shared_list = LIST_INIT(shared_list);
static size_t page_mask; static size_t page_mask;
#define ROUND_SIZE(size) (((size) + page_mask) & ~page_mask) #define ROUND_SIZE(size) (((size) + page_mask) & ~page_mask)
@ -168,6 +201,21 @@ static void ranges_destroy( struct object *obj )
free( ranges->ranges ); free( ranges->ranges );
} }
static void shared_map_dump( struct object *obj, int verbose )
{
struct shared_map *shared = (struct shared_map *)obj;
fprintf( stderr, "Shared mapping fd=%p file=%p\n", shared->fd, shared->file );
}
static void shared_map_destroy( struct object *obj )
{
struct shared_map *shared = (struct shared_map *)obj;
release_object( shared->fd );
release_object( shared->file );
list_remove( &shared->entry );
}
/* extend a file beyond the current end of file */ /* extend a file beyond the current end of file */
static int grow_file( int unix_fd, file_pos_t new_size ) static int grow_file( int unix_fd, file_pos_t new_size )
{ {
@ -277,13 +325,13 @@ void free_mapped_views( struct process *process )
} }
/* find the shared PE mapping for a given mapping */ /* find the shared PE mapping for a given mapping */
static struct file *get_shared_file( struct mapping *mapping ) static struct shared_map *get_shared_file( struct fd *fd )
{ {
struct mapping *ptr; struct shared_map *ptr;
LIST_FOR_EACH_ENTRY( ptr, &shared_list, struct mapping, shared_entry ) LIST_FOR_EACH_ENTRY( ptr, &shared_map_list, struct shared_map, entry )
if (is_same_file_fd( ptr->fd, mapping->fd )) if (is_same_file_fd( ptr->fd, fd ))
return (struct file *)grab_object( ptr->shared_file ); return (struct shared_map *)grab_object( ptr );
return NULL; return NULL;
} }
@ -397,6 +445,8 @@ static int find_committed_range( struct memory_view *view, file_pos_t start, mem
static int build_shared_mapping( struct mapping *mapping, int fd, static int build_shared_mapping( struct mapping *mapping, int fd,
IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) IMAGE_SECTION_HEADER *sec, unsigned int nb_sec )
{ {
struct shared_map *shared;
struct file *file;
unsigned int i; unsigned int i;
mem_size_t total_size; mem_size_t total_size;
size_t file_size, map_size, max_size; size_t file_size, map_size, max_size;
@ -420,13 +470,12 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
} }
if (!total_size) return 1; /* nothing to do */ if (!total_size) return 1; /* nothing to do */
if ((mapping->shared_file = get_shared_file( mapping ))) return 1; if ((mapping->shared = get_shared_file( mapping->fd ))) return 1;
/* create a temp file for the mapping */ /* create a temp file for the mapping */
if ((shared_fd = create_temp_file( total_size )) == -1) return 0; if ((shared_fd = create_temp_file( total_size )) == -1) return 0;
if (!(mapping->shared_file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) if (!(file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) return 0;
return 0;
if (!(buffer = malloc( max_size ))) goto error; if (!(buffer = malloc( max_size ))) goto error;
@ -457,11 +506,16 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error; if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error;
} }
free( buffer ); free( buffer );
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;
return 1; return 1;
error: error:
release_object( mapping->shared_file ); release_object( file );
mapping->shared_file = NULL;
free( buffer ); free( buffer );
return 0; return 0;
} }
@ -583,8 +637,6 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s
if (!build_shared_mapping( mapping, unix_fd, sec, nt.FileHeader.NumberOfSections )) goto error; if (!build_shared_mapping( mapping, unix_fd, sec, nt.FileHeader.NumberOfSections )) goto error;
if (mapping->shared_file) list_add_head( &shared_list, &mapping->shared_entry );
free( sec ); free( sec );
return 0; return 0;
@ -650,7 +702,7 @@ static struct object *create_mapping( struct object *root, const struct unicode_
mapping->size = size; mapping->size = size;
mapping->fd = NULL; mapping->fd = NULL;
mapping->shared_file = NULL; mapping->shared = NULL;
mapping->committed = NULL; mapping->committed = NULL;
if (!(mapping->flags = get_mapping_flags( handle, flags ))) goto error; if (!(mapping->flags = get_mapping_flags( handle, flags ))) goto error;
@ -747,9 +799,9 @@ static void mapping_dump( struct object *obj, int verbose )
{ {
struct mapping *mapping = (struct mapping *)obj; struct mapping *mapping = (struct mapping *)obj;
assert( obj->ops == &mapping_ops ); assert( obj->ops == &mapping_ops );
fprintf( stderr, "Mapping size=%08x%08x flags=%08x fd=%p shared_file=%p\n", fprintf( stderr, "Mapping size=%08x%08x flags=%08x fd=%p shared=%p\n",
(unsigned int)(mapping->size >> 32), (unsigned int)mapping->size, (unsigned int)(mapping->size >> 32), (unsigned int)mapping->size,
mapping->flags, mapping->fd, mapping->shared_file ); mapping->flags, mapping->fd, mapping->shared );
} }
static struct object_type *mapping_get_type( struct object *obj ) static struct object_type *mapping_get_type( struct object *obj )
@ -780,11 +832,7 @@ static void mapping_destroy( struct object *obj )
assert( obj->ops == &mapping_ops ); assert( obj->ops == &mapping_ops );
if (mapping->fd) release_object( mapping->fd ); if (mapping->fd) release_object( mapping->fd );
if (mapping->committed) release_object( mapping->committed ); if (mapping->committed) release_object( mapping->committed );
if (mapping->shared_file) if (mapping->shared) release_object( mapping->shared );
{
release_object( mapping->shared_file );
list_remove( &mapping->shared_entry );
}
} }
static enum server_fd_type mapping_get_fd_type( struct fd *fd ) static enum server_fd_type mapping_get_fd_type( struct fd *fd )
@ -857,8 +905,8 @@ DECL_HANDLER(get_mapping_info)
return; return;
} }
if (mapping->shared_file) if (mapping->shared)
reply->shared_file = alloc_handle( current->process, mapping->shared_file, reply->shared_file = alloc_handle( current->process, mapping->shared->file,
GENERIC_READ|GENERIC_WRITE, 0 ); GENERIC_READ|GENERIC_WRITE, 0 );
release_object( mapping ); release_object( mapping );
} }