Store the list of loaded dlls in the server, and generate debug events
internally.
diff --git a/server/process.c b/server/process.c
index ddd8226..30a9bf5 100644
--- a/server/process.c
+++ b/server/process.c
@@ -143,7 +143,6 @@
process->prev = NULL;
process->thread_list = NULL;
process->debugger = NULL;
- process->exe_file = NULL;
process->handles = NULL;
process->exit_code = STILL_ACTIVE;
process->running_threads = 0;
@@ -157,6 +156,11 @@
process->info = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
+ process->exe.next = NULL;
+ process->exe.prev = NULL;
+ process->exe.file = NULL;
+ process->exe.dbg_offset = 0;
+ process->exe.dbg_size = 0;
gettimeofday( &process->start_time, NULL );
if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process;
@@ -176,7 +180,7 @@
/* retrieve the main exe file */
if (process->info->exe_file != -1)
{
- if (!(process->exe_file = get_file_obj( parent, process->info->exe_file,
+ if (!(process->exe.file = get_file_obj( parent, process->info->exe_file,
GENERIC_READ ))) goto error;
process->info->exe_file = -1;
}
@@ -225,7 +229,7 @@
else first_process = process->next;
if (process->info) free( process->info );
if (process->init_event) release_object( process->init_event );
- if (process->exe_file) release_object( process->exe_file );
+ if (process->exe.file) release_object( process->exe.file );
}
/* dump a process on stdout for debugging purposes */
@@ -263,17 +267,68 @@
access, &process_ops );
}
+/* add a dll to a process list */
+static struct process_dll *process_load_dll( struct process *process, struct file *file,
+ void *base )
+{
+ struct process_dll *dll;
+
+ /* make sure we don't already have one with the same base address */
+ for (dll = process->exe.next; dll; dll = dll->next) if (dll->base == base)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return NULL;
+ }
+
+ if ((dll = mem_alloc( sizeof(*dll) )))
+ {
+ dll->prev = &process->exe;
+ dll->file = NULL;
+ dll->base = base;
+ if (file) dll->file = (struct file *)grab_object( file );
+ if ((dll->next = process->exe.next)) dll->next->prev = dll;
+ process->exe.next = dll;
+ }
+ return dll;
+}
+
+/* remove a dll from a process list */
+static void process_unload_dll( struct process *process, void *base )
+{
+ struct process_dll *dll;
+
+ for (dll = process->exe.next; dll; dll = dll->next)
+ {
+ if (dll->base == base)
+ {
+ if (dll->file) release_object( dll->file );
+ if (dll->next) dll->next->prev = dll->prev;
+ if (dll->prev) dll->prev->next = dll->next;
+ free( dll );
+ generate_debug_event( current, UNLOAD_DLL_DEBUG_EVENT, base );
+ return;
+ }
+ }
+ set_error( STATUS_INVALID_PARAMETER );
+}
+
/* a process has been killed (i.e. its last thread died) */
-static void process_killed( struct process *process, int exit_code )
+static void process_killed( struct process *process )
{
assert( !process->thread_list );
- process->exit_code = exit_code;
gettimeofday( &process->end_time, NULL );
release_object( process->handles );
process->handles = NULL;
free_console( process );
- if (process->exe_file) release_object( process->exe_file );
- process->exe_file = NULL;
+ while (process->exe.next)
+ {
+ struct process_dll *dll = process->exe.next;
+ process->exe.next = dll->next;
+ if (dll->file) release_object( dll->file );
+ free( dll );
+ }
+ if (process->exe.file) release_object( process->exe.file );
+ process->exe.file = NULL;
wake_up( &process->obj, 0 );
if (!--running_processes)
{
@@ -308,8 +363,11 @@
if (!--process->running_threads)
{
/* we have removed the last running thread, exit the process */
- process_killed( process, thread->exit_code );
+ process->exit_code = thread->exit_code;
+ generate_debug_event( thread, EXIT_PROCESS_DEBUG_EVENT, process );
+ process_killed( process );
}
+ else generate_debug_event( thread, EXIT_THREAD_DEBUG_EVENT, thread );
release_object( thread );
}
@@ -580,8 +638,8 @@
req->cmd_show = info->cmd_show;
req->env_ptr = info->env_ptr;
strcpy( req->cmdline, info->cmdline );
- if (current->process->exe_file)
- req->exe_file = alloc_handle( current->process, current->process->exe_file,
+ if (current->process->exe.file)
+ req->exe_file = alloc_handle( current->process, current->process->exe.file,
GENERIC_READ, 0 );
free( info );
}
@@ -595,9 +653,9 @@
fatal_protocol_error( current, "init_process_done: no event\n" );
return;
}
- current->entry = req->entry;
- process->module = req->module;
- generate_debug_event( current, CREATE_PROCESS_DEBUG_EVENT );
+ current->entry = req->entry;
+ process->exe.base = req->module;
+ generate_startup_debug_events( current->process );
set_event( process->init_event );
release_object( process->init_event );
process->init_event = NULL;
@@ -678,3 +736,30 @@
release_object( process );
}
}
+
+/* notify the server that a dll has been loaded */
+DECL_HANDLER(load_dll)
+{
+ struct process_dll *dll;
+ struct file *file = NULL;
+
+ if ((req->handle != -1) &&
+ !(file = get_file_obj( current->process, req->handle, GENERIC_READ ))) return;
+
+ if ((dll = process_load_dll( current->process, file, req->base )))
+ {
+ dll->dbg_offset = req->dbg_offset;
+ dll->dbg_size = req->dbg_size;
+ dll->name = req->name;
+ /* only generate event if initialization is done */
+ if (!current->process->init_event)
+ generate_debug_event( current, LOAD_DLL_DEBUG_EVENT, dll );
+ }
+ if (file) release_object( file );
+}
+
+/* notify the server that a dll is being unloaded */
+DECL_HANDLER(unload_dll)
+{
+ process_unload_dll( current->process, req->base );
+}