Commit 44699c32 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Add a separate request to initialize the first thread of a process.

parent 123023ea
......@@ -1618,7 +1618,6 @@ static struct unix_funcs unix_funcs =
*/
static void start_main_thread(void)
{
BOOL suspend;
NTSTATUS status;
TEB *teb = virtual_alloc_first_teb();
......@@ -1626,8 +1625,7 @@ static void start_main_thread(void)
signal_alloc_thread( teb );
signal_init_thread( teb );
dbg_init();
server_init_process();
startup_info_size = server_init_thread( teb->Peb, &suspend );
startup_info_size = server_init_process();
virtual_map_user_shared_data();
init_cpu_info();
init_files();
......
......@@ -1413,14 +1413,61 @@ static int get_unix_tid(void)
/***********************************************************************
* init_thread_pipe
*
* Create the server->client communication pipe.
*/
static int init_thread_pipe(void)
{
int reply_pipe[2];
stack_t ss;
ss.ss_sp = get_signal_stack();
ss.ss_size = signal_stack_size;
ss.ss_flags = 0;
sigaltstack( &ss, NULL );
if (server_pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
if (server_pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
wine_server_send_fd( reply_pipe[1] );
wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
ntdll_get_thread_data()->reply_fd = reply_pipe[0];
return reply_pipe[1];
}
/***********************************************************************
* init_teb64
*
* Initialize the 64-bit part of the TEB for WoW64 threads.
*/
static void init_teb64( TEB *teb )
{
#ifndef _WIN64
TEB64 *teb64 = (TEB64 *)((char *)teb - teb_offset);
if (!is_wow64) return;
teb->GdiBatchCount = PtrToUlong( teb64 );
teb->WowTebOffset = -teb_offset;
teb64->ClientId.UniqueProcess = PtrToUlong( teb->ClientId.UniqueProcess );
teb64->ClientId.UniqueThread = PtrToUlong( teb->ClientId.UniqueThread );
#endif
}
/***********************************************************************
* server_init_process
*
* Start the server and create the initial socket pair.
*/
void server_init_process(void)
size_t server_init_process(void)
{
obj_handle_t version;
static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
const char *arch = getenv( "WINEARCH" );
const char *env_socket = getenv( "WINESERVERSOCKET" );
obj_handle_t version;
int ret, reply_pipe;
struct sigaction sig_act;
size_t info_size;
server_pid = -1;
if (env_socket)
......@@ -1473,6 +1520,60 @@ void server_init_process(void)
/* work around Ubuntu's ptrace breakage */
if (server_pid != -1) prctl( 0x59616d61 /* PR_SET_PTRACER */, server_pid );
#endif
/* ignore SIGPIPE so that we get an EPIPE error instead */
sig_act.sa_handler = SIG_IGN;
sig_act.sa_flags = 0;
sigemptyset( &sig_act.sa_mask );
sigaction( SIGPIPE, &sig_act, NULL );
reply_pipe = init_thread_pipe();
SERVER_START_REQ( init_first_thread )
{
req->unix_pid = getpid();
req->unix_tid = get_unix_tid();
req->teb = wine_server_client_ptr( NtCurrentTeb() );
req->peb = wine_server_client_ptr( NtCurrentTeb()->Peb );
req->reply_fd = reply_pipe;
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
req->debug_level = (TRACE_ON(server) != 0);
req->cpu = client_cpu;
ret = wine_server_call( req );
NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid);
info_size = reply->info_size;
server_start_time = reply->server_start;
server_cpus = reply->all_cpus;
}
SERVER_END_REQ;
close( reply_pipe );
#ifndef _WIN64
is_wow64 = (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0;
init_teb64( NtCurrentTeb() );
#endif
switch (ret)
{
case STATUS_SUCCESS:
if (arch)
{
if (!strcmp( arch, "win32" ) && (is_win64 || is_wow64))
fatal_error( "WINEARCH set to win32 but '%s' is a 64-bit installation.\n", config_dir );
if (!strcmp( arch, "win64" ) && !is_win64 && !is_wow64)
fatal_error( "WINEARCH set to win64 but '%s' is a 32-bit installation.\n", config_dir );
}
return info_size;
case STATUS_INVALID_IMAGE_WIN_64:
fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n", config_dir );
case STATUS_NOT_SUPPORTED:
fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n", config_dir );
case STATUS_INVALID_IMAGE_FORMAT:
fatal_error( "wineserver doesn't support the %s architecture\n", cpu_names[client_cpu] );
default:
server_protocol_error( "init_first_thread failed with status %x\n", ret );
}
}
......@@ -1530,88 +1631,25 @@ void server_init_process_done(void)
*
* Send an init thread request.
*/
size_t server_init_thread( void *entry_point, BOOL *suspend )
void server_init_thread( void *entry_point, BOOL *suspend )
{
static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
const char *arch = getenv( "WINEARCH" );
int ret;
int reply_pipe[2];
struct sigaction sig_act;
stack_t ss;
size_t info_size;
/* ignore SIGPIPE so that we get an EPIPE error instead */
sig_act.sa_handler = SIG_IGN;
sig_act.sa_flags = 0;
sigemptyset( &sig_act.sa_mask );
sigaction( SIGPIPE, &sig_act, NULL );
ss.ss_sp = get_signal_stack();
ss.ss_size = signal_stack_size;
ss.ss_flags = 0;
sigaltstack( &ss, NULL );
/* create the server->client communication pipes */
if (server_pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
if (server_pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
wine_server_send_fd( reply_pipe[1] );
wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
ntdll_get_thread_data()->reply_fd = reply_pipe[0];
close( reply_pipe[1] );
int reply_pipe = init_thread_pipe();
SERVER_START_REQ( init_thread )
{
req->unix_pid = getpid();
req->unix_tid = get_unix_tid();
req->teb = wine_server_client_ptr( NtCurrentTeb() );
req->entry = wine_server_client_ptr( entry_point );
req->reply_fd = reply_pipe[1];
req->reply_fd = reply_pipe;
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
req->debug_level = (TRACE_ON(server) != 0);
req->cpu = client_cpu;
ret = wine_server_call( req );
wine_server_call( req );
*suspend = reply->suspend;
NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid);
info_size = reply->info_size;
server_start_time = reply->server_start;
server_cpus = reply->all_cpus;
*suspend = reply->suspend;
}
SERVER_END_REQ;
#ifndef _WIN64
is_wow64 = (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0;
if (is_wow64)
{
TEB64 *teb64 = (TEB64 *)((char *)NtCurrentTeb() - teb_offset);
NtCurrentTeb()->GdiBatchCount = PtrToUlong( teb64 );
NtCurrentTeb()->WowTebOffset = -teb_offset;
teb64->ClientId.UniqueProcess = PtrToUlong( NtCurrentTeb()->ClientId.UniqueProcess );
teb64->ClientId.UniqueThread = PtrToUlong( NtCurrentTeb()->ClientId.UniqueThread );
}
#endif
switch (ret)
{
case STATUS_SUCCESS:
if (arch)
{
if (!strcmp( arch, "win32" ) && (is_win64 || is_wow64))
fatal_error( "WINEARCH set to win32 but '%s' is a 64-bit installation.\n", config_dir );
if (!strcmp( arch, "win64" ) && !is_win64 && !is_wow64)
fatal_error( "WINEARCH set to win64 but '%s' is a 32-bit installation.\n", config_dir );
}
return info_size;
case STATUS_INVALID_IMAGE_WIN_64:
fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n", config_dir );
case STATUS_NOT_SUPPORTED:
fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n", config_dir );
case STATUS_INVALID_IMAGE_FORMAT:
fatal_error( "wineserver doesn't support the %s architecture\n", cpu_names[client_cpu] );
default:
server_protocol_error( "init_thread failed with status %x\n", ret );
}
close( reply_pipe );
init_teb64( NtCurrentTeb() );
}
......
......@@ -157,9 +157,9 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *
apc_result_t *result ) DECLSPEC_HIDDEN;
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
extern void server_init_process(void) DECLSPEC_HIDDEN;
extern size_t server_init_process(void) DECLSPEC_HIDDEN;
extern void server_init_process_done(void) DECLSPEC_HIDDEN;
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
extern void server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
......
......@@ -893,29 +893,47 @@ struct init_process_done_reply
struct init_thread_request
struct init_first_thread_request
{
struct request_header __header;
int unix_pid;
int unix_tid;
int debug_level;
client_ptr_t teb;
client_ptr_t entry;
client_ptr_t peb;
int reply_fd;
int wait_fd;
client_cpu_t cpu;
char __pad_52[4];
};
struct init_thread_reply
struct init_first_thread_reply
{
struct reply_header __header;
process_id_t pid;
thread_id_t tid;
timeout_t server_start;
data_size_t info_size;
int version;
unsigned int all_cpus;
};
struct init_thread_request
{
struct request_header __header;
int unix_tid;
int reply_fd;
int wait_fd;
client_ptr_t teb;
client_ptr_t entry;
};
struct init_thread_reply
{
struct reply_header __header;
process_id_t pid;
thread_id_t tid;
int suspend;
char __pad_20[4];
};
......@@ -5373,6 +5391,7 @@ enum request
REQ_new_thread,
REQ_get_startup_info,
REQ_init_process_done,
REQ_init_first_thread,
REQ_init_thread,
REQ_terminate_process,
REQ_terminate_thread,
......@@ -5655,6 +5674,7 @@ union generic_request
struct new_thread_request new_thread_request;
struct get_startup_info_request get_startup_info_request;
struct init_process_done_request init_process_done_request;
struct init_first_thread_request init_first_thread_request;
struct init_thread_request init_thread_request;
struct terminate_process_request terminate_process_request;
struct terminate_thread_request terminate_thread_request;
......@@ -5935,6 +5955,7 @@ union generic_reply
struct new_thread_reply new_thread_reply;
struct get_startup_info_reply get_startup_info_reply;
struct init_process_done_reply init_process_done_reply;
struct init_first_thread_reply init_first_thread_reply;
struct init_thread_reply init_thread_reply;
struct terminate_process_reply terminate_process_reply;
struct terminate_thread_reply terminate_thread_reply;
......@@ -6208,7 +6229,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 662
#define SERVER_PROTOCOL_VERSION 663
/* ### protocol_version end ### */
......
......@@ -607,10 +607,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
return NULL;
}
/* initialize the current process and fill in the request */
data_size_t init_process( struct thread *thread )
/* get the process data size */
data_size_t get_process_startup_info_size( struct process *process )
{
struct process *process = thread->process;
struct startup_info *info = process->startup_info;
if (!info) return 0;
......
......@@ -108,7 +108,7 @@ extern void *get_ptid_entry( unsigned int id );
extern struct process *create_process( int fd, struct process *parent, int inherit_all, const startup_info_t *info,
const struct security_descriptor *sd, const obj_handle_t *handles,
unsigned int handle_count, struct token *token );
extern data_size_t init_process( struct thread *thread );
extern data_size_t get_process_startup_info_size( struct process *process );
extern struct thread *get_process_first_thread( struct process *process );
extern struct process *get_process_from_id( process_id_t id );
extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access );
......
......@@ -870,13 +870,13 @@ typedef struct
@END
/* Initialize a thread; called from the child after fork()/clone() */
@REQ(init_thread)
int unix_pid; /* Unix pid of new thread */
/* Initialize the first thread of a new process */
@REQ(init_first_thread)
int unix_pid; /* Unix pid of new process */
int unix_tid; /* Unix tid of new thread */
int debug_level; /* new debug level */
client_ptr_t teb; /* TEB of new thread (in thread address space) */
client_ptr_t entry; /* entry point or PEB if initial thread (in thread address space) */
client_ptr_t teb; /* TEB of new thread (in process address space) */
client_ptr_t peb; /* PEB of new process (in process address space) */
int reply_fd; /* fd for reply pipe */
int wait_fd; /* fd for blocking calls pipe */
client_cpu_t cpu; /* CPU that this thread is running on */
......@@ -885,8 +885,20 @@ typedef struct
thread_id_t tid; /* thread id of the new thread */
timeout_t server_start; /* server start time */
data_size_t info_size; /* total size of startup info */
int version; /* protocol version */
unsigned int all_cpus; /* bitset of supported CPUs */
@END
/* Initialize a new thread; called from the child after pthread_create() */
@REQ(init_thread)
int unix_tid; /* Unix tid of new thread */
int reply_fd; /* fd for reply pipe */
int wait_fd; /* fd for blocking calls pipe */
client_ptr_t teb; /* TEB of new thread (in thread address space) */
client_ptr_t entry; /* entry point (in thread address space) */
@REPLY
process_id_t pid; /* process id of the new thread's process */
thread_id_t tid; /* thread id of the new thread */
int suspend; /* is thread suspended? */
@END
......
......@@ -125,6 +125,7 @@ DECL_HANDLER(get_new_process_info);
DECL_HANDLER(new_thread);
DECL_HANDLER(get_startup_info);
DECL_HANDLER(init_process_done);
DECL_HANDLER(init_first_thread);
DECL_HANDLER(init_thread);
DECL_HANDLER(terminate_process);
DECL_HANDLER(terminate_thread);
......@@ -406,6 +407,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_new_thread,
(req_handler)req_get_startup_info,
(req_handler)req_init_process_done,
(req_handler)req_init_first_thread,
(req_handler)req_init_thread,
(req_handler)req_terminate_process,
(req_handler)req_terminate_thread,
......@@ -748,23 +750,31 @@ C_ASSERT( FIELD_OFFSET(struct init_process_done_request, entry) == 32 );
C_ASSERT( sizeof(struct init_process_done_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_reply, suspend) == 8 );
C_ASSERT( sizeof(struct init_process_done_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_tid) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, debug_level) == 20 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, unix_pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, unix_tid) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, debug_level) == 20 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, teb) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, peb) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, reply_fd) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, wait_fd) == 44 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, cpu) == 48 );
C_ASSERT( sizeof(struct init_first_thread_request) == 56 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, pid) == 8 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, tid) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, server_start) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, info_size) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, all_cpus) == 28 );
C_ASSERT( sizeof(struct init_first_thread_reply) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_tid) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, reply_fd) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, wait_fd) == 20 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, teb) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, entry) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, reply_fd) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, wait_fd) == 44 );
C_ASSERT( FIELD_OFFSET(struct init_thread_request, cpu) == 48 );
C_ASSERT( sizeof(struct init_thread_request) == 56 );
C_ASSERT( sizeof(struct init_thread_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, pid) == 8 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, tid) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, server_start) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, info_size) == 24 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, version) == 28 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, all_cpus) == 32 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 36 );
C_ASSERT( sizeof(struct init_thread_reply) == 40 );
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 16 );
C_ASSERT( sizeof(struct init_thread_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, exit_code) == 16 );
C_ASSERT( sizeof(struct terminate_process_request) == 24 );
......
......@@ -1384,24 +1384,20 @@ done:
release_object( process );
}
/* initialize a new thread */
DECL_HANDLER(init_thread)
static int init_thread( struct thread *thread, int reply_fd, int wait_fd )
{
struct process *process = current->process;
int wait_fd, reply_fd;
if ((reply_fd = thread_get_inflight_fd( current, req->reply_fd )) == -1)
if ((reply_fd = thread_get_inflight_fd( thread, reply_fd )) == -1)
{
set_error( STATUS_TOO_MANY_OPENED_FILES );
return;
return 0;
}
if ((wait_fd = thread_get_inflight_fd( current, req->wait_fd )) == -1)
if ((wait_fd = thread_get_inflight_fd( thread, wait_fd )) == -1)
{
set_error( STATUS_TOO_MANY_OPENED_FILES );
goto error;
}
if (current->reply_fd) /* already initialised */
if (thread->reply_fd) /* already initialised */
{
set_error( STATUS_INVALID_PARAMETER );
goto error;
......@@ -1409,59 +1405,74 @@ DECL_HANDLER(init_thread)
if (fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error;
current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj, 0 );
current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj, 0 );
if (!current->reply_fd || !current->wait_fd) return;
thread->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &thread->obj, 0 );
thread->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, &thread->obj, 0 );
return thread->reply_fd && thread->wait_fd;
if (!is_valid_address(req->teb))
error:
if (reply_fd != -1) close( reply_fd );
if (wait_fd != -1) close( wait_fd );
return 0;
}
/* initialize the first thread of a new process */
DECL_HANDLER(init_first_thread)
{
struct process *process = current->process;
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
if (!is_valid_address(req->teb) || !is_valid_address(req->peb))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
current->unix_pid = req->unix_pid;
if (!is_cpu_supported( req->cpu )) return;
current->unix_pid = process->unix_pid = req->unix_pid;
current->unix_tid = req->unix_tid;
current->teb = req->teb;
current->entry_point = process->peb ? req->entry : 0;
if (!process->peb) /* first thread, initialize the process too */
{
if (!is_cpu_supported( req->cpu )) return;
process->unix_pid = current->unix_pid;
process->peb = req->entry;
process->peb = req->peb;
process->cpu = req->cpu;
reply->info_size = init_process( current );
if (!process->parent_id)
process->affinity = current->affinity = get_thread_affinity( current );
else
set_thread_affinity( current, current->affinity );
}
else
{
if (req->cpu != process->cpu)
debug_level = max( debug_level, req->debug_level );
reply->pid = get_process_id( process );
reply->tid = get_thread_id( current );
reply->info_size = get_process_startup_info_size( process );
reply->server_start = server_start_time;
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
}
/* initialize a new thread */
DECL_HANDLER(init_thread)
{
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
if (!is_valid_address(req->teb))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (process->unix_pid != current->unix_pid)
process->unix_pid = -1; /* can happen with linuxthreads */
current->unix_pid = current->process->unix_pid;
current->unix_tid = req->unix_tid;
current->teb = req->teb;
current->entry_point = req->entry;
init_thread_context( current );
generate_debug_event( current, DbgCreateThreadStateChange, &req->entry );
set_thread_affinity( current, current->affinity );
}
debug_level = max( debug_level, req->debug_level );
reply->pid = get_process_id( process );
reply->pid = get_process_id( current->process );
reply->tid = get_thread_id( current );
reply->version = SERVER_PROTOCOL_VERSION;
reply->server_start = server_start_time;
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
reply->suspend = (current->suspend || process->suspend || current->context != NULL);
return;
error:
if (reply_fd != -1) close( reply_fd );
if (wait_fd != -1) close( wait_fd );
reply->suspend = (current->suspend || current->process->suspend || current->context != NULL);
}
/* terminate a thread */
......
......@@ -1392,26 +1392,40 @@ static void dump_init_process_done_reply( const struct init_process_done_reply *
fprintf( stderr, " suspend=%d", req->suspend );
}
static void dump_init_thread_request( const struct init_thread_request *req )
static void dump_init_first_thread_request( const struct init_first_thread_request *req )
{
fprintf( stderr, " unix_pid=%d", req->unix_pid );
fprintf( stderr, ", unix_tid=%d", req->unix_tid );
fprintf( stderr, ", debug_level=%d", req->debug_level );
dump_uint64( ", teb=", &req->teb );
dump_uint64( ", entry=", &req->entry );
dump_uint64( ", peb=", &req->peb );
fprintf( stderr, ", reply_fd=%d", req->reply_fd );
fprintf( stderr, ", wait_fd=%d", req->wait_fd );
dump_client_cpu( ", cpu=", &req->cpu );
}
static void dump_init_thread_reply( const struct init_thread_reply *req )
static void dump_init_first_thread_reply( const struct init_first_thread_reply *req )
{
fprintf( stderr, " pid=%04x", req->pid );
fprintf( stderr, ", tid=%04x", req->tid );
dump_timeout( ", server_start=", &req->server_start );
fprintf( stderr, ", info_size=%u", req->info_size );
fprintf( stderr, ", version=%d", req->version );
fprintf( stderr, ", all_cpus=%08x", req->all_cpus );
}
static void dump_init_thread_request( const struct init_thread_request *req )
{
fprintf( stderr, " unix_tid=%d", req->unix_tid );
fprintf( stderr, ", reply_fd=%d", req->reply_fd );
fprintf( stderr, ", wait_fd=%d", req->wait_fd );
dump_uint64( ", teb=", &req->teb );
dump_uint64( ", entry=", &req->entry );
}
static void dump_init_thread_reply( const struct init_thread_reply *req )
{
fprintf( stderr, " pid=%04x", req->pid );
fprintf( stderr, ", tid=%04x", req->tid );
fprintf( stderr, ", suspend=%d", req->suspend );
}
......@@ -4407,6 +4421,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_thread_request,
(dump_func)dump_get_startup_info_request,
(dump_func)dump_init_process_done_request,
(dump_func)dump_init_first_thread_request,
(dump_func)dump_init_thread_request,
(dump_func)dump_terminate_process_request,
(dump_func)dump_terminate_thread_request,
......@@ -4685,6 +4700,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_thread_reply,
(dump_func)dump_get_startup_info_reply,
(dump_func)dump_init_process_done_reply,
(dump_func)dump_init_first_thread_reply,
(dump_func)dump_init_thread_reply,
(dump_func)dump_terminate_process_reply,
(dump_func)dump_terminate_thread_reply,
......@@ -4963,6 +4979,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"new_thread",
"get_startup_info",
"init_process_done",
"init_first_thread",
"init_thread",
"terminate_process",
"terminate_thread",
......
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