Commit ea331926 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Report load dll events upon mapping a SEC_IMAGE view.

parent 4f2ed66a
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <windows.h> #include <windows.h>
#include <winternl.h> #include <winternl.h>
#include <winreg.h> #include <winreg.h>
#include <psapi.h>
#include "wine/test.h" #include "wine/test.h"
#include "wine/heap.h" #include "wine/heap.h"
#include "wine/rbtree.h" #include "wine/rbtree.h"
...@@ -828,7 +829,9 @@ static void doChild(int argc, char **argv) ...@@ -828,7 +829,9 @@ static void doChild(int argc, char **argv)
{ {
struct child_blackbox blackbox; struct child_blackbox blackbox;
const char *blackbox_file; const char *blackbox_file;
HANDLE parent; WCHAR path[MAX_PATH];
HMODULE mod;
HANDLE parent, file, map;
DWORD ppid; DWORD ppid;
BOOL debug; BOOL debug;
BOOL ret; BOOL ret;
...@@ -876,10 +879,49 @@ static void doChild(int argc, char **argv) ...@@ -876,10 +879,49 @@ static void doChild(int argc, char **argv)
NtCurrentTeb()->Peb->BeingDebugged = TRUE; NtCurrentTeb()->Peb->BeingDebugged = TRUE;
mod = LoadLibraryW( L"ole32.dll" );
FreeLibrary( mod );
GetSystemDirectoryW( path, MAX_PATH );
wcscat( path, L"\\oleaut32.dll" );
file = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
child_ok( file != INVALID_HANDLE_VALUE, "failed to open %s: %u\n", debugstr_w(path), GetLastError());
map = CreateFileMappingW( file, NULL, SEC_IMAGE | PAGE_READONLY, 0, 0, NULL );
child_ok( map != NULL, "failed to create mapping %s: %u\n", debugstr_w(path), GetLastError() );
mod = MapViewOfFile( map, FILE_MAP_READ, 0, 0, 0 );
child_ok( mod != NULL, "failed to map %s: %u\n", debugstr_w(path), GetLastError() );
CloseHandle( file );
CloseHandle( map );
UnmapViewOfFile( mod );
blackbox.failures = child_failures; blackbox.failures = child_failures;
save_blackbox(blackbox_file, &blackbox, sizeof(blackbox), NULL); save_blackbox(blackbox_file, &blackbox, sizeof(blackbox), NULL);
} }
static HMODULE ole32_mod, oleaut32_mod;
static void check_dll_event( HANDLE process, DEBUG_EVENT *ev )
{
WCHAR *p, module[MAX_PATH];
switch (ev->dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
break;
case LOAD_DLL_DEBUG_EVENT:
if (!GetMappedFileNameW( process, ev->u.LoadDll.lpBaseOfDll, module, MAX_PATH )) module[0] = 0;
if ((p = wcsrchr( module, '\\' ))) p++;
else p = module;
if (!wcsicmp( p, L"ole32.dll" )) ole32_mod = ev->u.LoadDll.lpBaseOfDll;
else if (!wcsicmp( p, L"oleaut32.dll" )) oleaut32_mod = ev->u.LoadDll.lpBaseOfDll;
break;
case UNLOAD_DLL_DEBUG_EVENT:
if (ev->u.UnloadDll.lpBaseOfDll == ole32_mod) ole32_mod = (HMODULE)1;
if (ev->u.UnloadDll.lpBaseOfDll == oleaut32_mod) oleaut32_mod = (HMODULE)1;
break;
}
}
static void test_debug_loop(int argc, char **argv) static void test_debug_loop(int argc, char **argv)
{ {
const char *arguments = " debugger child "; const char *arguments = " debugger child ";
...@@ -926,6 +968,7 @@ static void test_debug_loop(int argc, char **argv) ...@@ -926,6 +968,7 @@ static void test_debug_loop(int argc, char **argv)
if (!ret) break; if (!ret) break;
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
check_dll_event( pi.hProcess, &ev );
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
if (ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT && if (ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
...@@ -940,6 +983,9 @@ static void test_debug_loop(int argc, char **argv) ...@@ -940,6 +983,9 @@ static void test_debug_loop(int argc, char **argv)
if (!ret) break; if (!ret) break;
} }
ok( ole32_mod == (HMODULE)1, "ole32.dll was not reported\n" );
ok( oleaut32_mod == (HMODULE)1, "oleaut32.dll was not reported\n" );
ret = CloseHandle(pi.hThread); ret = CloseHandle(pi.hThread);
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
ret = CloseHandle(pi.hProcess); ret = CloseHandle(pi.hProcess);
......
...@@ -181,9 +181,7 @@ static void fill_exit_process_event( struct debug_event *event, const void *arg ...@@ -181,9 +181,7 @@ static void fill_exit_process_event( struct debug_event *event, const void *arg
static void fill_load_dll_event( struct debug_event *event, const void *arg ) static void fill_load_dll_event( struct debug_event *event, const void *arg )
{ {
struct process *process = event->sender->process; const struct memory_view *view = arg;
const struct process_dll *dll = arg;
struct memory_view *view = find_mapped_view( process, dll->base );
const pe_image_info_t *image_info = get_view_image_info( view, &event->data.load_dll.base ); const pe_image_info_t *image_info = get_view_image_info( view, &event->data.load_dll.base );
event->data.load_dll.dbg_offset = image_info->dbg_offset; event->data.load_dll.dbg_offset = image_info->dbg_offset;
...@@ -194,8 +192,8 @@ static void fill_load_dll_event( struct debug_event *event, const void *arg ) ...@@ -194,8 +192,8 @@ static void fill_load_dll_event( struct debug_event *event, const void *arg )
static void fill_unload_dll_event( struct debug_event *event, const void *arg ) static void fill_unload_dll_event( struct debug_event *event, const void *arg )
{ {
const mod_handle_t *base = arg; const struct memory_view *view = arg;
event->data.unload_dll.base = *base; get_view_image_info( view, &event->data.unload_dll.base );
} }
typedef void (*fill_event_func)( struct debug_event *event, const void *arg ); typedef void (*fill_event_func)( struct debug_event *event, const void *arg );
...@@ -534,39 +532,6 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj ) ...@@ -534,39 +532,6 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj )
resume_process( process ); resume_process( process );
} }
/* generate all startup events of a given process */
void generate_startup_debug_events( struct process *process )
{
struct list *ptr;
struct memory_view *view = get_exe_view( process );
struct thread *thread, *first_thread = get_process_first_thread( process );
if (!view) return;
generate_debug_event( first_thread, DbgCreateProcessStateChange, view );
ptr = list_head( &process->dlls ); /* skip main module reported in create process event */
/* generate ntdll.dll load event */
if (ptr && (ptr = list_next( &process->dlls, ptr )))
{
struct process_dll *dll = LIST_ENTRY( ptr, struct process_dll, entry );
generate_debug_event( first_thread, DbgLoadDllStateChange, dll );
}
/* generate creation events */
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
{
if (thread != first_thread)
generate_debug_event( thread, DbgCreateThreadStateChange, NULL );
}
/* generate dll events (in loading order) */
while (ptr && (ptr = list_next( &process->dlls, ptr )))
{
struct process_dll *dll = LIST_ENTRY( ptr, struct process_dll, entry );
generate_debug_event( first_thread, DbgLoadDllStateChange, dll );
}
}
/* create a debug object */ /* create a debug object */
DECL_HANDLER(create_debug_obj) DECL_HANDLER(create_debug_obj)
{ {
......
...@@ -348,11 +348,15 @@ struct memory_view *get_exe_view( struct process *process ) ...@@ -348,11 +348,15 @@ struct memory_view *get_exe_view( struct process *process )
} }
/* add a view to the process list */ /* add a view to the process list */
static void add_process_view( struct process *process, struct memory_view *view ) static void add_process_view( struct thread *thread, struct memory_view *view )
{ {
struct process *process = thread->process;
if (view->flags & SEC_IMAGE) if (view->flags & SEC_IMAGE)
{ {
if (!is_process_init_done( process ) && !(view->image.image_charact & IMAGE_FILE_DLL)) if (is_process_init_done( process ))
generate_debug_event( thread, DbgLoadDllStateChange, view );
else if (!(view->image.image_charact & IMAGE_FILE_DLL))
{ {
/* main exe */ /* main exe */
list_add_head( &process->views, &view->entry ); list_add_head( &process->views, &view->entry );
...@@ -1001,6 +1005,42 @@ int get_view_nt_name( const struct memory_view *view, struct unicode_str *name ) ...@@ -1001,6 +1005,42 @@ int get_view_nt_name( const struct memory_view *view, struct unicode_str *name )
return 1; return 1;
} }
/* generate all startup events of a given process */
void generate_startup_debug_events( struct process *process )
{
struct memory_view *view;
struct list *ptr = list_head( &process->views );
struct thread *thread, *first_thread = get_process_first_thread( process );
if (!ptr) return;
view = LIST_ENTRY( ptr, struct memory_view, entry );
generate_debug_event( first_thread, DbgCreateProcessStateChange, view );
/* generate ntdll.dll load event */
while (ptr && (ptr = list_next( &process->views, ptr )))
{
view = LIST_ENTRY( ptr, struct memory_view, entry );
if (!(view->flags & SEC_IMAGE)) continue;
generate_debug_event( first_thread, DbgLoadDllStateChange, view );
break;
}
/* generate creation events */
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
{
if (thread != first_thread)
generate_debug_event( thread, DbgCreateThreadStateChange, NULL );
}
/* generate dll events (in loading order) */
while (ptr && (ptr = list_next( &process->views, ptr )))
{
view = LIST_ENTRY( ptr, struct memory_view, entry );
if (!(view->flags & SEC_IMAGE)) continue;
generate_debug_event( first_thread, DbgLoadDllStateChange, view );
}
}
static void mapping_dump( struct object *obj, int verbose ) static void mapping_dump( struct object *obj, int verbose )
{ {
struct mapping *mapping = (struct mapping *)obj; struct mapping *mapping = (struct mapping *)obj;
...@@ -1142,7 +1182,7 @@ DECL_HANDLER(map_view) ...@@ -1142,7 +1182,7 @@ DECL_HANDLER(map_view)
view->start = req->start; view->start = req->start;
view->flags = SEC_IMAGE; view->flags = SEC_IMAGE;
memcpy( &view->image, get_req_data(), min( sizeof(view->image), get_req_data_size() )); memcpy( &view->image, get_req_data(), min( sizeof(view->image), get_req_data_size() ));
add_process_view( current->process, view ); add_process_view( current, view );
return; return;
} }
...@@ -1173,12 +1213,10 @@ DECL_HANDLER(map_view) ...@@ -1173,12 +1213,10 @@ DECL_HANDLER(map_view)
view->fd = !is_fd_removable( mapping->fd ) ? (struct fd *)grab_object( mapping->fd ) : NULL; view->fd = !is_fd_removable( mapping->fd ) ? (struct fd *)grab_object( mapping->fd ) : NULL;
view->committed = mapping->committed ? (struct ranges *)grab_object( mapping->committed ) : NULL; view->committed = mapping->committed ? (struct ranges *)grab_object( mapping->committed ) : NULL;
view->shared = mapping->shared ? (struct shared_map *)grab_object( mapping->shared ) : NULL; view->shared = mapping->shared ? (struct shared_map *)grab_object( mapping->shared ) : NULL;
if (mapping->flags & SEC_IMAGE) if (view->flags & SEC_IMAGE) view->image = mapping->image;
{ add_process_view( current, view );
view->image = mapping->image; if (view->flags & SEC_IMAGE && view->base != mapping->image.base)
if (view->base != mapping->image.base) set_error( STATUS_IMAGE_NOT_AT_BASE ); set_error( STATUS_IMAGE_NOT_AT_BASE );
}
add_process_view( current->process, view );
} }
done: done:
...@@ -1190,7 +1228,9 @@ DECL_HANDLER(unmap_view) ...@@ -1190,7 +1228,9 @@ DECL_HANDLER(unmap_view)
{ {
struct memory_view *view = find_mapped_view( current->process, req->base ); struct memory_view *view = find_mapped_view( current->process, req->base );
if (view) free_memory_view( view ); if (!view) return;
if (view->flags & SEC_IMAGE) generate_debug_event( current, DbgUnloadDllStateChange, view );
free_memory_view( view );
} }
/* get a range of committed pages in a file mapping */ /* get a range of committed pages in a file mapping */
......
...@@ -832,7 +832,6 @@ static void process_unload_dll( struct process *process, mod_handle_t base ) ...@@ -832,7 +832,6 @@ static void process_unload_dll( struct process *process, mod_handle_t base )
free( dll->filename ); free( dll->filename );
list_remove( &dll->entry ); list_remove( &dll->entry );
free( dll ); free( dll );
generate_debug_event( current, DbgUnloadDllStateChange, &base );
} }
else set_error( STATUS_INVALID_PARAMETER ); else set_error( STATUS_INVALID_PARAMETER );
} }
...@@ -1602,9 +1601,6 @@ DECL_HANDLER(load_dll) ...@@ -1602,9 +1601,6 @@ DECL_HANDLER(load_dll)
if ((dll = process_load_dll( current->process, req->base, get_req_data(), get_req_data_size() ))) if ((dll = process_load_dll( current->process, req->base, get_req_data(), get_req_data_size() )))
{ {
dll->name = req->name; dll->name = req->name;
/* only generate event if initialization is done */
if (is_process_init_done( current->process ))
generate_debug_event( current, DbgLoadDllStateChange, dll );
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment