From ced3892c65b33149a490b2c2191098c0c6aa1eeb Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 26 Jan 2021 11:55:37 +0100 Subject: [PATCH] ntdll: Create a SEC_IMAGE view also for .so builtins. Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/loader.c | 2 +- dlls/ntdll/unix/unix_private.h | 2 +- dlls/ntdll/unix/virtual.c | 47 +++++++++++++++++++--------------- include/wine/server_protocol.h | 3 ++- server/mapping.c | 30 +++++++++++++++++++++- server/protocol.def | 3 ++- server/trace.c | 1 + 7 files changed, 62 insertions(+), 26 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 5e2d5aeff7c..8caddb19abf 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1028,7 +1028,7 @@ static NTSTATUS dlopen_dll( const char *so_name, void **ret_module, pe_image_inf dlclose( handle ); return STATUS_NO_MEMORY; } - virtual_create_builtin_view( module ); + virtual_create_builtin_view( module, image_info ); *ret_module = module; return STATUS_SUCCESS; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index f8f50d0ab27..1d6ba95d2a1 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -179,7 +179,7 @@ extern void *anon_mmap_alloc( size_t size, int prot ) DECLSPEC_HIDDEN; extern void virtual_init(void) DECLSPEC_HIDDEN; extern ULONG_PTR get_system_affinity_mask(void) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN; +extern NTSTATUS virtual_create_builtin_view( void *module, pe_image_info_t *info ) DECLSPEC_HIDDEN; extern TEB *virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN; extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index e96bda722f6..c1e79a210f4 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2483,20 +2483,18 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) /*********************************************************************** * virtual_create_builtin_view */ -NTSTATUS virtual_create_builtin_view( void *module ) +NTSTATUS virtual_create_builtin_view( void *module, pe_image_info_t *info ) { NTSTATUS status; sigset_t sigset; IMAGE_DOS_HEADER *dos = module; IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew); - SIZE_T size = nt->OptionalHeader.SizeOfImage; + SIZE_T size = info->map_size; IMAGE_SECTION_HEADER *sec; struct file_view *view; - void *base; + void *base = wine_server_get_ptr( info->base ); int i; - size = ROUND_SIZE( module, size ); - base = ROUND_ADDR( module, page_mask ); server_enter_uninterrupted_section( &virtual_mutex, &sigset ); status = create_view( &view, base, size, SEC_IMAGE | SEC_FILE | VPROT_SYSTEM | VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC ); @@ -2517,10 +2515,25 @@ NTSTATUS virtual_create_builtin_view( void *module ) if (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE) flags |= VPROT_WRITE; set_page_vprot( (char *)base + sec[i].VirtualAddress, sec[i].Misc.VirtualSize, flags ); } - VIRTUAL_DEBUG_DUMP_VIEW( view ); - if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit; + + SERVER_START_REQ( map_view ) + { + req->base = wine_server_client_ptr( view->base ); + req->size = size; + wine_server_add_data( req, info, sizeof(*info) ); + status = wine_server_call( req ); + } + SERVER_END_REQ; + + if (status >= 0) + { + VIRTUAL_DEBUG_DUMP_VIEW( view ); + if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit; + } + else delete_view( view ); } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); + return status; } @@ -4065,22 +4078,14 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) server_enter_uninterrupted_section( &virtual_mutex, &sigset ); if ((view = find_view( addr, 0 )) && !is_view_valloc( view )) { - if (!(view->protect & VPROT_SYSTEM)) + SERVER_START_REQ( unmap_view ) { - SERVER_START_REQ( unmap_view ) - { - req->base = wine_server_client_ptr( view->base ); - status = wine_server_call( req ); - } - SERVER_END_REQ; - if (!status) delete_view( view ); - else FIXME( "failed to unmap %p %x\n", view->base, status ); - } - else - { - delete_view( view ); - status = STATUS_SUCCESS; + req->base = wine_server_client_ptr( view->base ); + status = wine_server_call( req ); } + SERVER_END_REQ; + if (!status) delete_view( view ); + else FIXME( "failed to unmap %p %x\n", view->base, status ); } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); return status; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 0dd5803a79e..f070c604fdd 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1903,6 +1903,7 @@ struct map_view_request client_ptr_t base; mem_size_t size; file_pos_t start; + /* VARARG(image,pe_image_info); */ }; struct map_view_reply { @@ -6190,7 +6191,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 653 +#define SERVER_PROTOCOL_VERSION 654 /* ### protocol_version end ### */ diff --git a/server/mapping.c b/server/mapping.c index 4e38e8e40da..9c51aa3bec7 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -316,6 +316,21 @@ static struct memory_view *find_mapped_view( struct process *process, client_ptr return NULL; } +/* add a view to the process list */ +static void add_process_view( struct process *process, struct memory_view *view ) +{ + if (view->flags & SEC_IMAGE) + { + if (!is_process_init_done( process ) && !(view->image.image_charact & IMAGE_FILE_DLL)) + { + /* main exe */ + list_add_head( &process->views, &view->entry ); + return; + } + } + list_add_tail( &process->views, &view->entry ); +} + static void free_memory_view( struct memory_view *view ) { if (view->fd) release_object( view->fd ); @@ -1097,6 +1112,19 @@ DECL_HANDLER(map_view) return; } + if (!req->mapping) /* image mapping for a .so dll */ + { + if (!(view = mem_alloc( sizeof(*view) ))) return; + memset( view, 0, sizeof(*view) ); + view->base = req->base; + view->size = req->size; + view->start = req->start; + view->flags = SEC_IMAGE; + memcpy( &view->image, get_req_data(), min( sizeof(view->image), get_req_data_size() )); + add_process_view( current->process, view ); + return; + } + if (!(mapping = get_mapping_obj( current->process, req->mapping, req->access ))) return; if (mapping->flags & SEC_IMAGE) @@ -1129,7 +1157,7 @@ DECL_HANDLER(map_view) view->image = mapping->image; if (view->base != mapping->image.base) set_error( STATUS_IMAGE_NOT_AT_BASE ); } - list_add_tail( ¤t->process->views, &view->entry ); + add_process_view( current->process, view ); } done: diff --git a/server/protocol.def b/server/protocol.def index e6c23aa77b0..bac6b58e215 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1515,11 +1515,12 @@ enum server_fd_type /* Add a memory view in the current process */ @REQ(map_view) - obj_handle_t mapping; /* file mapping handle */ + obj_handle_t mapping; /* file mapping handle, or 0 for .so builtin */ unsigned int access; /* wanted access rights */ client_ptr_t base; /* view base address (page-aligned) */ mem_size_t size; /* view size */ file_pos_t start; /* start offset in mapping */ + VARARG(image,pe_image_info);/* image info for .so builtins */ @END diff --git a/server/trace.c b/server/trace.c index 4c1ff57186b..750b83281c8 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2107,6 +2107,7 @@ static void dump_map_view_request( const struct map_view_request *req ) dump_uint64( ", base=", &req->base ); dump_uint64( ", size=", &req->size ); dump_uint64( ", start=", &req->start ); + dump_varargs_pe_image_info( ", image=", cur_size ); } static void dump_unmap_view_request( const struct unmap_view_request *req )