Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
ea0d028a
Commit
ea0d028a
authored
Mar 10, 2000
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added specific routines for OUTPUT_DEBUG_STRING and EXCEPTION debug events.
Generate a breakpoint event on process attach. Misc cleanups in request handling.
parent
ebd01a94
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
435 additions
and
366 deletions
+435
-366
exception.c
dlls/ntdll/exception.c
+20
-5
server.h
include/server.h
+20
-14
debugger.c
scheduler/debugger.c
+12
-48
context_i386.c
server/context_i386.c
+4
-6
debugger.c
server/debugger.c
+199
-142
file.c
server/file.c
+5
-3
main.c
server/main.c
+0
-2
object.h
server/object.h
+1
-2
process.c
server/process.c
+2
-2
request.c
server/request.c
+4
-6
request.h
server/request.h
+113
-106
thread.c
server/thread.c
+1
-0
thread.h
server/thread.h
+1
-0
trace.c
server/trace.c
+40
-21
make_requests
tools/make_requests
+4
-5
except.c
win32/except.c
+9
-4
No files found.
dlls/ntdll/exception.c
View file @
ea0d028a
...
...
@@ -13,9 +13,10 @@
#include "wine/exception.h"
#include "stackframe.h"
#include "miscemu.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
seh
)
DEFAULT_DEBUG_CHANNEL
(
seh
)
;
/* Exception record for handling exceptions happening inside exception handlers */
typedef
struct
...
...
@@ -84,6 +85,22 @@ static DWORD EXC_CallHandler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
}
/**********************************************************************
* EXC_SendEvent
*
* Send an EXCEPTION_DEBUG_EVENT event to the debugger.
*/
static
inline
int
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
int
first_chance
,
CONTEXT
*
context
)
{
struct
exception_event_request
*
req
=
get_req_buffer
();
req
->
record
=
*
rec
;
req
->
first
=
first_chance
;
req
->
context
=
*
context
;
if
(
!
server_call_noerr
(
REQ_EXCEPTION_EVENT
))
*
context
=
req
->
context
;
return
req
->
status
;
}
/*******************************************************************
* EXC_DefaultHandling
*
...
...
@@ -91,8 +108,7 @@ static DWORD EXC_CallHandler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
*/
static
void
EXC_DefaultHandling
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
if
(
DEBUG_SendExceptionEvent
(
rec
,
FALSE
,
context
)
==
DBG_CONTINUE
)
return
;
/* continue execution */
if
(
send_debug_event
(
rec
,
FALSE
,
context
)
==
DBG_CONTINUE
)
return
;
/* continue execution */
if
(
rec
->
ExceptionFlags
&
EH_STACK_INVALID
)
ERR
(
"Exception frame is not in stack limits => unable to dispatch exception.
\n
"
);
...
...
@@ -117,8 +133,7 @@ void WINAPI EXC_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
TRACE
(
"code=%lx flags=%lx
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
);
if
(
DEBUG_SendExceptionEvent
(
rec
,
TRUE
,
context
)
==
DBG_CONTINUE
)
return
;
/* continue execution */
if
(
send_debug_event
(
rec
,
TRUE
,
context
)
==
DBG_CONTINUE
)
return
;
/* continue execution */
frame
=
NtCurrentTeb
()
->
except
;
nested_frame
=
NULL
;
...
...
include/server.h
View file @
ea0d028a
...
...
@@ -31,14 +31,8 @@ typedef WCHAR path_t[MAX_PATH+1];
/* definitions of the event data depending on the event code */
struct
debug_event_exception
{
int
code
;
/* exception code */
int
flags
;
/* exception flags */
void
*
record
;
/* exception record ptr */
void
*
addr
;
/* exception address */
int
nb_params
;
/* exceptions parameters */
int
params
[
15
];
int
first_chance
;
/* first chance to handle it? */
CONTEXT
context
;
/* thread context */
EXCEPTION_RECORD
record
;
/* exception record */
int
first
;
/* first chance exception? */
};
struct
debug_event_create_thread
{
...
...
@@ -813,11 +807,22 @@ struct wait_debug_event_request
};
/* Send a
debug
event */
struct
send_debug
_event_request
/* Send a
n exception
event */
struct
exception
_event_request
{
OUT
int
status
;
/* event continuation status */
IN
debug_event_t
event
;
/* debug event data */
IN
EXCEPTION_RECORD
record
;
/* exception record */
IN
int
first
;
/* first chance exception? */
IN
CONTEXT
context
;
/* thread context */
OUT
int
status
;
/* event continuation status */
};
/* Send an output string to the debugger */
struct
output_debug_string_request
{
IN
void
*
string
;
/* string to display (in debugged process address space) */
IN
int
unicode
;
/* is it Unicode? */
IN
int
length
;
/* string length */
};
...
...
@@ -1164,7 +1169,8 @@ enum request
REQ_CREATE_SNAPSHOT
,
REQ_NEXT_PROCESS
,
REQ_WAIT_DEBUG_EVENT
,
REQ_SEND_DEBUG_EVENT
,
REQ_EXCEPTION_EVENT
,
REQ_OUTPUT_DEBUG_STRING
,
REQ_CONTINUE_DEBUG_EVENT
,
REQ_DEBUG_PROCESS
,
REQ_READ_PROCESS_MEMORY
,
...
...
@@ -1196,7 +1202,7 @@ enum request
REQ_NB_REQUESTS
};
#define SERVER_PROTOCOL_VERSION
2
#define SERVER_PROTOCOL_VERSION
3
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
scheduler/debugger.c
View file @
ea0d028a
...
...
@@ -7,39 +7,12 @@
#include <string.h>
#include "winerror.h"
#include "process.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
debugstr
);
/**********************************************************************
* DEBUG_SendExceptionEvent
*
* Send an EXCEPTION_DEBUG_EVENT event to the current process debugger.
*/
DWORD
DEBUG_SendExceptionEvent
(
EXCEPTION_RECORD
*
rec
,
BOOL
first_chance
,
CONTEXT
*
context
)
{
int
i
;
struct
send_debug_event_request
*
req
=
get_req_buffer
();
req
->
event
.
code
=
EXCEPTION_DEBUG_EVENT
;
req
->
event
.
info
.
exception
.
code
=
rec
->
ExceptionCode
;
req
->
event
.
info
.
exception
.
flags
=
rec
->
ExceptionFlags
;
req
->
event
.
info
.
exception
.
record
=
rec
->
ExceptionRecord
;
req
->
event
.
info
.
exception
.
addr
=
rec
->
ExceptionAddress
;
req
->
event
.
info
.
exception
.
nb_params
=
rec
->
NumberParameters
;
req
->
event
.
info
.
exception
.
first_chance
=
first_chance
;
req
->
event
.
info
.
exception
.
context
=
*
context
;
for
(
i
=
0
;
i
<
req
->
event
.
info
.
exception
.
nb_params
;
i
++
)
req
->
event
.
info
.
exception
.
params
[
i
]
=
rec
->
ExceptionInformation
[
i
];
if
(
!
server_call_noerr
(
REQ_SEND_DEBUG_EVENT
))
*
context
=
req
->
event
.
info
.
exception
.
context
;
return
req
->
status
;
}
/******************************************************************************
* WaitForDebugEvent (KERNEL32.720)
*
...
...
@@ -54,7 +27,6 @@ DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance, CONTEX
BOOL
WINAPI
WaitForDebugEvent
(
LPDEBUG_EVENT
event
,
DWORD
timeout
)
{
struct
wait_debug_event_request
*
req
=
get_req_buffer
();
int
i
;
req
->
timeout
=
timeout
;
if
(
server_call
(
REQ_WAIT_DEBUG_EVENT
))
return
FALSE
;
...
...
@@ -70,14 +42,8 @@ BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout )
SetLastError
(
ERROR_SEM_TIMEOUT
);
return
FALSE
;
case
EXCEPTION_DEBUG_EVENT
:
event
->
u
.
Exception
.
ExceptionRecord
.
ExceptionCode
=
req
->
event
.
info
.
exception
.
code
;
event
->
u
.
Exception
.
ExceptionRecord
.
ExceptionFlags
=
req
->
event
.
info
.
exception
.
flags
;
event
->
u
.
Exception
.
ExceptionRecord
.
ExceptionRecord
=
req
->
event
.
info
.
exception
.
record
;
event
->
u
.
Exception
.
ExceptionRecord
.
ExceptionAddress
=
req
->
event
.
info
.
exception
.
addr
;
event
->
u
.
Exception
.
ExceptionRecord
.
NumberParameters
=
req
->
event
.
info
.
exception
.
nb_params
;
for
(
i
=
0
;
i
<
req
->
event
.
info
.
exception
.
nb_params
;
i
++
)
event
->
u
.
Exception
.
ExceptionRecord
.
ExceptionInformation
[
i
]
=
req
->
event
.
info
.
exception
.
params
[
i
];
event
->
u
.
Exception
.
dwFirstChance
=
req
->
event
.
info
.
exception
.
first_chance
;
event
->
u
.
Exception
.
ExceptionRecord
=
req
->
event
.
info
.
exception
.
record
;
event
->
u
.
Exception
.
dwFirstChance
=
req
->
event
.
info
.
exception
.
first
;
break
;
case
CREATE_THREAD_DEBUG_EVENT
:
event
->
u
.
CreateThread
.
hThread
=
req
->
event
.
info
.
create_thread
.
handle
;
...
...
@@ -158,12 +124,11 @@ BOOL WINAPI DebugActiveProcess( DWORD pid )
*/
void
WINAPI
OutputDebugStringA
(
LPCSTR
str
)
{
struct
send_debug_event_request
*
req
=
get_req_buffer
();
req
->
event
.
code
=
OUTPUT_DEBUG_STRING_EVENT
;
req
->
event
.
info
.
output_string
.
string
=
(
void
*
)
str
;
req
->
event
.
info
.
output_string
.
unicode
=
0
;
req
->
event
.
info
.
output_string
.
length
=
strlen
(
str
)
+
1
;
server_call_noerr
(
REQ_SEND_DEBUG_EVENT
);
struct
output_debug_string_request
*
req
=
get_req_buffer
();
req
->
string
=
(
void
*
)
str
;
req
->
unicode
=
0
;
req
->
length
=
strlen
(
str
)
+
1
;
server_call_noerr
(
REQ_OUTPUT_DEBUG_STRING
);
TRACE
(
"%s
\n
"
,
str
);
}
...
...
@@ -173,12 +138,11 @@ void WINAPI OutputDebugStringA( LPCSTR str )
*/
void
WINAPI
OutputDebugStringW
(
LPCWSTR
str
)
{
struct
send_debug_event_request
*
req
=
get_req_buffer
();
req
->
event
.
code
=
OUTPUT_DEBUG_STRING_EVENT
;
req
->
event
.
info
.
output_string
.
string
=
(
void
*
)
str
;
req
->
event
.
info
.
output_string
.
unicode
=
1
;
req
->
event
.
info
.
output_string
.
length
=
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
);
server_call_noerr
(
REQ_SEND_DEBUG_EVENT
);
struct
output_debug_string_request
*
req
=
get_req_buffer
();
req
->
string
=
(
void
*
)
str
;
req
->
unicode
=
1
;
req
->
length
=
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
);
server_call_noerr
(
REQ_OUTPUT_DEBUG_STRING
);
TRACE
(
"%s
\n
"
,
debugstr_w
(
str
));
}
...
...
server/context_i386.c
View file @
ea0d028a
...
...
@@ -457,13 +457,12 @@ static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
DECL_HANDLER
(
get_thread_context
)
{
struct
thread
*
thread
;
CONTEXT
*
context
;
if
((
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_GET_CONTEXT
)))
{
if
(
(
context
=
get_debug_context
(
thread
))
)
/* thread is inside an exception event */
if
(
thread
->
context
)
/* thread is inside an exception event */
{
copy_context
(
&
req
->
context
,
context
,
req
->
flags
);
copy_context
(
&
req
->
context
,
thread
->
context
,
req
->
flags
);
}
else
{
...
...
@@ -481,13 +480,12 @@ DECL_HANDLER(get_thread_context)
DECL_HANDLER
(
set_thread_context
)
{
struct
thread
*
thread
;
CONTEXT
*
context
;
if
((
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_SET_CONTEXT
)))
{
if
(
(
context
=
get_debug_context
(
thread
))
)
/* thread is inside an exception event */
if
(
thread
->
context
)
/* thread is inside an exception event */
{
copy_context
(
context
,
&
req
->
context
,
req
->
flags
);
copy_context
(
thread
->
context
,
&
req
->
context
,
req
->
flags
);
}
else
{
...
...
server/debugger.c
View file @
ea0d028a
...
...
@@ -83,93 +83,132 @@ static const struct object_ops debug_ctx_ops =
};
/* initialise the fields that do not need to be filled by the client */
static
int
fill_debug_event
(
struct
debug_event
*
event
,
void
*
arg
)
/* routines to build an event according to its type */
static
int
fill_exception_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
memcpy
(
&
event
->
data
.
info
.
exception
,
arg
,
sizeof
(
event
->
data
.
info
.
exception
)
);
return
1
;
}
static
int
fill_create_thread_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
process
*
debugger
=
event
->
debugger
->
process
;
struct
process
*
process
;
struct
thread
*
thread
;
struct
process_dll
*
dll
;
struct
thread
*
thread
=
arg
;
int
handle
;
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
if
((
handle
=
alloc_handle
(
debugger
,
thread
,
THREAD_ALL_ACCESS
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
create_thread
.
handle
=
handle
;
event
->
data
.
info
.
create_thread
.
teb
=
thread
->
teb
;
event
->
data
.
info
.
create_thread
.
start
=
thread
->
entry
;
return
1
;
}
static
int
fill_create_process_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
process
*
debugger
=
event
->
debugger
->
process
;
struct
process
*
process
=
arg
;
struct
thread
*
thread
=
process
->
thread_list
;
int
handle
;
/* some events need special handling */
switch
(
event
->
data
.
code
)
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
if
((
handle
=
alloc_handle
(
debugger
,
process
,
PROCESS_ALL_ACCESS
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
create_process
.
process
=
handle
;
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
if
((
handle
=
alloc_handle
(
debugger
,
thread
,
THREAD_ALL_ACCESS
,
FALSE
))
==
-
1
)
{
case
CREATE_THREAD_DEBUG_EVENT
:
thread
=
arg
;
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
if
((
handle
=
alloc_handle
(
debugger
,
thread
,
THREAD_ALL_ACCESS
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
create_thread
.
handle
=
handle
;
event
->
data
.
info
.
create_thread
.
teb
=
thread
->
teb
;
event
->
data
.
info
.
create_thread
.
start
=
thread
->
entry
;
break
;
case
CREATE_PROCESS_DEBUG_EVENT
:
process
=
arg
;
thread
=
process
->
thread_list
;
/* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
if
((
handle
=
alloc_handle
(
debugger
,
process
,
PROCESS_ALL_ACCESS
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
create_process
.
process
=
handle
;
/* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
if
((
handle
=
alloc_handle
(
debugger
,
thread
,
THREAD_ALL_ACCESS
,
FALSE
))
==
-
1
)
{
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
process
);
return
0
;
}
event
->
data
.
info
.
create_process
.
thread
=
handle
;
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
process
);
return
0
;
}
event
->
data
.
info
.
create_process
.
thread
=
handle
;
handle
=
-
1
;
if
(
process
->
exe
.
file
&&
/* the doc says write access too, but this doesn't seem a good idea */
((
handle
=
alloc_handle
(
debugger
,
process
->
exe
.
file
,
GENERIC_READ
,
FALSE
))
==
-
1
))
{
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
process
);
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
thread
);
return
0
;
}
event
->
data
.
info
.
create_process
.
file
=
handle
;
event
->
data
.
info
.
create_process
.
teb
=
thread
->
teb
;
event
->
data
.
info
.
create_process
.
base
=
process
->
exe
.
base
;
event
->
data
.
info
.
create_process
.
start
=
thread
->
entry
;
event
->
data
.
info
.
create_process
.
dbg_offset
=
process
->
exe
.
dbg_offset
;
event
->
data
.
info
.
create_process
.
dbg_size
=
process
->
exe
.
dbg_size
;
event
->
data
.
info
.
create_process
.
name
=
0
;
event
->
data
.
info
.
create_process
.
unicode
=
0
;
break
;
case
LOAD_DLL_DEBUG_EVENT
:
dll
=
arg
;
handle
=
-
1
;
if
(
dll
->
file
&&
(
handle
=
alloc_handle
(
debugger
,
dll
->
file
,
GENERIC_READ
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
load_dll
.
handle
=
handle
;
event
->
data
.
info
.
load_dll
.
base
=
dll
->
base
;
event
->
data
.
info
.
load_dll
.
dbg_offset
=
dll
->
dbg_offset
;
event
->
data
.
info
.
load_dll
.
dbg_size
=
dll
->
dbg_size
;
event
->
data
.
info
.
load_dll
.
name
=
dll
->
name
;
event
->
data
.
info
.
load_dll
.
unicode
=
0
;
break
;
case
EXIT_PROCESS_DEBUG_EVENT
:
process
=
arg
;
event
->
data
.
info
.
exit
.
exit_code
=
process
->
exit_code
;
break
;
case
EXIT_THREAD_DEBUG_EVENT
:
thread
=
arg
;
event
->
data
.
info
.
exit
.
exit_code
=
thread
->
exit_code
;
break
;
case
UNLOAD_DLL_DEBUG_EVENT
:
event
->
data
.
info
.
unload_dll
.
base
=
arg
;
break
;
case
EXCEPTION_DEBUG_EVENT
:
case
OUTPUT_DEBUG_STRING_EVENT
:
case
RIP_EVENT
:
break
;
handle
=
-
1
;
if
(
process
->
exe
.
file
&&
/* the doc says write access too, but this doesn't seem a good idea */
((
handle
=
alloc_handle
(
debugger
,
process
->
exe
.
file
,
GENERIC_READ
,
FALSE
))
==
-
1
))
{
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
process
);
close_handle
(
debugger
,
event
->
data
.
info
.
create_process
.
thread
);
return
0
;
}
event
->
data
.
info
.
create_process
.
file
=
handle
;
event
->
data
.
info
.
create_process
.
teb
=
thread
->
teb
;
event
->
data
.
info
.
create_process
.
base
=
process
->
exe
.
base
;
event
->
data
.
info
.
create_process
.
start
=
thread
->
entry
;
event
->
data
.
info
.
create_process
.
dbg_offset
=
process
->
exe
.
dbg_offset
;
event
->
data
.
info
.
create_process
.
dbg_size
=
process
->
exe
.
dbg_size
;
event
->
data
.
info
.
create_process
.
name
=
0
;
event
->
data
.
info
.
create_process
.
unicode
=
0
;
return
1
;
}
static
int
fill_exit_thread_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
thread
*
thread
=
arg
;
event
->
data
.
info
.
exit
.
exit_code
=
thread
->
exit_code
;
return
1
;
}
static
int
fill_exit_process_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
process
*
process
=
arg
;
event
->
data
.
info
.
exit
.
exit_code
=
process
->
exit_code
;
return
1
;
}
static
int
fill_load_dll_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
process
*
debugger
=
event
->
debugger
->
process
;
struct
process_dll
*
dll
=
arg
;
int
handle
=
-
1
;
if
(
dll
->
file
&&
(
handle
=
alloc_handle
(
debugger
,
dll
->
file
,
GENERIC_READ
,
FALSE
))
==
-
1
)
return
0
;
event
->
data
.
info
.
load_dll
.
handle
=
handle
;
event
->
data
.
info
.
load_dll
.
base
=
dll
->
base
;
event
->
data
.
info
.
load_dll
.
dbg_offset
=
dll
->
dbg_offset
;
event
->
data
.
info
.
load_dll
.
dbg_size
=
dll
->
dbg_size
;
event
->
data
.
info
.
load_dll
.
name
=
dll
->
name
;
event
->
data
.
info
.
load_dll
.
unicode
=
0
;
return
1
;
}
static
int
fill_unload_dll_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
event
->
data
.
info
.
unload_dll
.
base
=
arg
;
return
1
;
}
static
int
fill_output_debug_string_event
(
struct
debug_event
*
event
,
void
*
arg
)
{
struct
output_debug_string_request
*
req
=
arg
;
event
->
data
.
info
.
output_string
.
string
=
req
->
string
;
event
->
data
.
info
.
output_string
.
unicode
=
req
->
unicode
;
event
->
data
.
info
.
output_string
.
length
=
req
->
length
;
return
1
;
}
typedef
int
(
*
fill_event_func
)(
struct
debug_event
*
event
,
void
*
arg
);
#define NB_DEBUG_EVENTS OUTPUT_DEBUG_STRING_EVENT
/* RIP_EVENT not supported */
static
const
fill_event_func
fill_debug_event
[
NB_DEBUG_EVENTS
]
=
{
fill_exception_event
,
/* EXCEPTION_DEBUG_EVENT */
fill_create_thread_event
,
/* CREATE_THREAD_DEBUG_EVENT */
fill_create_process_event
,
/* CREATE_PROCESS_DEBUG_EVENT */
fill_exit_thread_event
,
/* EXIT_THREAD_DEBUG_EVENT */
fill_exit_process_event
,
/* EXIT_PROCESS_DEBUG_EVENT */
fill_load_dll_event
,
/* LOAD_DLL_DEBUG_EVENT */
fill_unload_dll_event
,
/* UNLOAD_DLL_DEBUG_EVENT */
fill_output_debug_string_event
/* OUTPUT_DEBUG_STRING_EVENT */
};
/* unlink the first event from the queue */
static
void
unlink_event
(
struct
debug_ctx
*
debug_ctx
,
struct
debug_event
*
event
)
{
...
...
@@ -228,18 +267,13 @@ static void build_wait_debug_reply( struct thread *thread, struct object *obj, i
}
/* build a reply for the send_event request */
static
void
build_
send
_event_reply
(
struct
thread
*
thread
,
struct
object
*
obj
,
int
signaled
)
static
void
build_
exception
_event_reply
(
struct
thread
*
thread
,
struct
object
*
obj
,
int
signaled
)
{
struct
send_debug
_event_request
*
req
=
get_req_ptr
(
thread
);
struct
exception
_event_request
*
req
=
get_req_ptr
(
thread
);
struct
debug_event
*
event
=
(
struct
debug_event
*
)
obj
;
assert
(
obj
->
ops
==
&
debug_event_ops
);
req
->
status
=
event
->
status
;
/* copy the context into the reply */
if
(
event
->
data
.
code
==
EXCEPTION_DEBUG_EVENT
)
memcpy
(
&
req
->
event
.
info
.
exception
.
context
,
&
event
->
data
.
info
.
exception
.
context
,
sizeof
(
req
->
event
.
info
.
exception
.
context
)
);
thread
->
context
=
NULL
;
}
static
void
debug_event_dump
(
struct
object
*
obj
,
int
verbose
)
...
...
@@ -363,28 +397,27 @@ static int continue_debug_event( struct process *process, struct thread *thread,
}
/* queue a debug event for a debugger */
static
struct
debug_event
*
queue_debug_event
(
struct
thread
*
thread
,
int
code
,
void
*
arg
,
debug_event_t
*
data
)
static
struct
debug_event
*
queue_debug_event
(
struct
thread
*
thread
,
int
code
,
void
*
arg
)
{
struct
thread
*
debugger
=
thread
->
process
->
debugger
;
struct
debug_ctx
*
debug_ctx
=
debugger
->
debug_ctx
;
struct
debug_event
*
event
;
assert
(
code
>
0
&&
code
<=
NB_DEBUG_EVENTS
);
assert
(
debug_ctx
);
/* cannot queue a debug event for myself */
assert
(
debugger
->
process
!=
thread
->
process
);
/* build the event */
if
(
!
(
event
=
alloc_object
(
&
debug_event_ops
,
-
1
)))
return
NULL
;
event
->
next
=
NULL
;
event
->
prev
=
NULL
;
event
->
state
=
EVENT_QUEUED
;
event
->
sender
=
(
struct
thread
*
)
grab_object
(
thread
);
event
->
debugger
=
(
struct
thread
*
)
grab_object
(
debugger
);
if
(
data
)
memcpy
(
&
event
->
data
,
data
,
sizeof
(
event
->
data
)
);
event
->
next
=
NULL
;
event
->
prev
=
NULL
;
event
->
state
=
EVENT_QUEUED
;
event
->
sender
=
(
struct
thread
*
)
grab_object
(
thread
);
event
->
debugger
=
(
struct
thread
*
)
grab_object
(
debugger
);
event
->
data
.
code
=
code
;
if
(
!
fill_debug_event
(
event
,
arg
))
if
(
!
fill_debug_event
[
code
-
1
]
(
event
,
arg
))
{
event
->
data
.
code
=
-
1
;
/* make sure we don't attempt to close handles */
release_object
(
event
);
...
...
@@ -401,11 +434,43 @@ void generate_debug_event( struct thread *thread, int code, void *arg )
{
if
(
thread
->
process
->
debugger
)
{
struct
debug_event
*
event
=
queue_debug_event
(
thread
,
code
,
arg
,
NULL
);
struct
debug_event
*
event
=
queue_debug_event
(
thread
,
code
,
arg
);
if
(
event
)
release_object
(
event
);
}
}
/* attach a process to a debugger thread and suspend it */
static
int
debugger_attach
(
struct
process
*
process
,
struct
thread
*
debugger
)
{
struct
thread
*
thread
;
if
(
process
->
debugger
)
goto
error
;
/* already being debugged */
if
(
process
->
init_event
)
goto
error
;
/* still starting up */
/* make sure we don't create a debugging loop */
for
(
thread
=
debugger
;
thread
;
thread
=
thread
->
process
->
debugger
)
if
(
thread
->
process
==
process
)
goto
error
;
suspend_process
(
process
);
/* we must have been able to attach all threads */
for
(
thread
=
process
->
thread_list
;
thread
;
thread
=
thread
->
proc_next
)
if
(
!
thread
->
attached
)
{
fprintf
(
stderr
,
"%p not attached
\n
"
,
thread
);
resume_process
(
process
);
goto
error
;
}
if
(
set_process_debugger
(
process
,
debugger
))
return
1
;
resume_process
(
process
);
return
0
;
error:
set_error
(
STATUS_ACCESS_DENIED
);
return
0
;
}
/* generate all startup events of a given process */
void
generate_startup_debug_events
(
struct
process
*
process
)
{
...
...
@@ -426,40 +491,12 @@ void generate_startup_debug_events( struct process *process )
}
}
/* return a pointer to the context in case the thread is inside an exception event */
CONTEXT
*
get_debug_context
(
struct
thread
*
thread
)
{
struct
debug_event
*
event
;
struct
thread
*
debugger
=
thread
->
process
->
debugger
;
if
(
!
debugger
)
return
NULL
;
/* not being debugged */
assert
(
debugger
->
debug_ctx
);
/* find the exception event in the debugger's queue */
for
(
event
=
debugger
->
debug_ctx
->
event_head
;
event
;
event
=
event
->
next
)
if
(
event
->
sender
==
thread
&&
(
event
->
data
.
code
==
EXCEPTION_DEBUG_EVENT
))
return
&
event
->
data
.
info
.
exception
.
context
;
return
NULL
;
}
/* attach a process to a debugger thread */
int
debugger_attach
(
struct
process
*
process
,
struct
thread
*
debugger
)
/* set the debugger of a given process */
int
set_process_debugger
(
struct
process
*
process
,
struct
thread
*
debugger
)
{
struct
debug_ctx
*
debug_ctx
;
struct
thread
*
thread
;
if
(
process
->
debugger
)
/* already being debugged */
{
set_error
(
STATUS_ACCESS_DENIED
);
return
0
;
}
/* make sure we don't create a debugging loop */
for
(
thread
=
debugger
;
thread
;
thread
=
thread
->
process
->
debugger
)
if
(
thread
->
process
==
process
)
{
set_error
(
STATUS_ACCESS_DENIED
);
return
0
;
}
assert
(
!
process
->
debugger
);
if
(
!
debugger
->
debug_ctx
)
/* need to allocate a context */
{
...
...
@@ -515,34 +552,54 @@ DECL_HANDLER(continue_debug_event)
/* Start debugging an existing process */
DECL_HANDLER
(
debug_process
)
{
struct
debug_event_exception
data
;
struct
debug_event
*
event
;
struct
process
*
process
=
get_process_from_id
(
req
->
pid
);
if
(
!
process
)
return
;
if
(
debugger_attach
(
process
,
current
))
{
generate_startup_debug_events
(
process
);
/* FIXME: breakpoint exception event */
resume_process
(
process
);
data
.
record
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
data
.
record
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
data
.
record
.
ExceptionRecord
=
NULL
;
data
.
record
.
ExceptionAddress
=
process
->
thread_list
->
entry
;
/* FIXME */
data
.
record
.
NumberParameters
=
0
;
data
.
first
=
1
;
if
((
event
=
queue_debug_event
(
process
->
thread_list
,
EXCEPTION_DEBUG_EVENT
,
&
data
)))
release_object
(
event
);
}
release_object
(
process
);
}
/*
Send a debug
event */
DECL_HANDLER
(
send_debug
_event
)
/*
send an exception
event */
DECL_HANDLER
(
exception
_event
)
{
struct
debug_event
*
event
;
int
code
=
req
->
event
.
code
;
if
((
code
<=
0
)
||
(
code
>
RIP_EVENT
))
if
(
current
->
process
->
debugger
)
{
fatal_protocol_error
(
current
,
"send_debug_event: bad code %d
\n
"
,
code
);
return
;
struct
debug_event_exception
data
;
struct
debug_event
*
event
;
data
.
record
=
req
->
record
;
data
.
first
=
req
->
first
;
if
((
event
=
queue_debug_event
(
current
,
EXCEPTION_DEBUG_EVENT
,
&
data
)))
{
struct
object
*
obj
=
&
event
->
obj
;
current
->
context
=
&
req
->
context
;
sleep_on
(
1
,
&
obj
,
0
,
-
1
,
build_exception_event_reply
);
release_object
(
event
);
}
}
req
->
status
=
0
;
if
(
current
->
process
->
debugger
&&
((
event
=
queue_debug_event
(
current
,
code
,
NULL
,
&
req
->
event
))))
}
/* send an output string to the debugger */
DECL_HANDLER
(
output_debug_string
)
{
if
(
current
->
process
->
debugger
)
{
/* wait for continue_debug_event */
struct
object
*
obj
=
&
event
->
obj
;
sleep_on
(
1
,
&
obj
,
0
,
-
1
,
build_send_event_reply
);
release_object
(
event
);
struct
debug_event
*
event
=
queue_debug_event
(
current
,
OUTPUT_DEBUG_STRING_EVENT
,
req
);
if
(
event
)
release_object
(
event
);
}
}
server/file.c
View file @
ea0d028a
...
...
@@ -468,15 +468,17 @@ DECL_HANDLER(alloc_file_handle)
struct
file
*
file
;
req
->
handle
=
-
1
;
if
(
(
fd
=
dup
(
fd
))
!=
-
1
)
if
(
current
->
pass_fd
!=
-
1
)
{
if
((
file
=
create_file_for_fd
(
fd
,
req
->
access
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
0
)))
if
((
file
=
create_file_for_fd
(
current
->
pass_fd
,
req
->
access
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
0
)))
{
req
->
handle
=
alloc_handle
(
current
->
process
,
file
,
req
->
access
,
0
);
release_object
(
file
);
}
current
->
pass_fd
=
-
1
;
}
else
file_set_error
(
);
else
set_error
(
STATUS_INVALID_PARAMETER
);
}
/* get a Unix fd to read from a file */
...
...
server/main.c
View file @
ea0d028a
...
...
@@ -60,7 +60,6 @@ static void sigterm_handler()
/* initialize signal handling */
static
void
signal_init
(
void
)
{
#if 0
if
(
!
debug_level
)
{
switch
(
fork
())
...
...
@@ -74,7 +73,6 @@ static void signal_init(void)
exit
(
0
);
}
}
#endif
signal
(
SIGPIPE
,
SIG_IGN
);
signal
(
SIGHUP
,
sigterm_handler
);
signal
(
SIGINT
,
sigterm_handler
);
...
...
server/object.h
View file @
ea0d028a
...
...
@@ -153,11 +153,10 @@ extern int free_console( struct process *process );
/* debugger functions */
extern
int
debugger_attach
(
struct
process
*
process
,
struct
thread
*
debugger
);
extern
int
set_process_debugger
(
struct
process
*
process
,
struct
thread
*
debugger
);
extern
void
generate_debug_event
(
struct
thread
*
thread
,
int
code
,
void
*
arg
);
extern
void
generate_startup_debug_events
(
struct
process
*
process
);
extern
void
debug_exit_thread
(
struct
thread
*
thread
);
extern
CONTEXT
*
get_debug_context
(
struct
thread
*
thread
);
/* mapping functions */
...
...
server/process.c
View file @
ea0d028a
...
...
@@ -201,9 +201,9 @@ struct thread *create_process( int fd, struct process *parent,
/* attach to the debugger if requested */
if
(
process
->
create_flags
&
(
DEBUG_PROCESS
|
DEBUG_ONLY_THIS_PROCESS
))
debugger_attach
(
process
,
current
);
set_process_debugger
(
process
,
current
);
else
if
(
parent
&&
parent
->
debugger
&&
!
(
parent
->
create_flags
&
DEBUG_ONLY_THIS_PROCESS
))
debugger_attach
(
process
,
parent
->
debugger
);
set_process_debugger
(
process
,
parent
->
debugger
);
release_object
(
process
);
return
thread
;
...
...
server/request.c
View file @
ea0d028a
...
...
@@ -127,16 +127,16 @@ static void fatal_perror( const char *err, ... )
}
/* call a request handler */
static
void
call_req_handler
(
struct
thread
*
thread
,
enum
request
req
,
int
fd
)
static
inline
void
call_req_handler
(
struct
thread
*
thread
,
enum
request
req
)
{
current
=
thread
;
clear_error
();
if
(
debug_level
)
trace_request
(
req
,
fd
);
if
(
debug_level
)
trace_request
(
req
);
if
(
req
<
REQ_NB_REQUESTS
)
{
req_handlers
[
req
]
.
handler
(
current
->
buffer
,
fd
);
req_handlers
[
req
]
(
current
->
buffer
);
if
(
current
&&
!
current
->
wait
)
send_reply
(
current
);
current
=
NULL
;
return
;
...
...
@@ -186,10 +186,8 @@ void read_request( struct thread *thread )
if
(
ret
==
sizeof
(
req
))
{
int
pass_fd
=
thread
->
pass_fd
;
call_req_handler
(
thread
,
req
)
;
thread
->
pass_fd
=
-
1
;
call_req_handler
(
thread
,
req
,
pass_fd
);
if
(
pass_fd
!=
-
1
)
close
(
pass_fd
);
return
;
}
if
(
ret
==
-
1
)
...
...
server/request.h
View file @
ea0d028a
...
...
@@ -22,20 +22,26 @@
#define PROTOCOL_ERROR -3
/* request handler definition */
#define DECL_HANDLER(name) void req_##name( struct name##_request *req
, int fd
)
#define DECL_HANDLER(name) void req_##name( struct name##_request *req )
/* request functions */
#ifdef __GNUC__
extern
void
fatal_protocol_error
(
struct
thread
*
thread
,
const
char
*
err
,
...
)
__attribute__
((
format
(
printf
,
2
,
3
)));
#else
extern
void
fatal_protocol_error
(
struct
thread
*
thread
,
const
char
*
err
,
...
);
#endif
extern
void
read_request
(
struct
thread
*
thread
);
extern
int
write_request
(
struct
thread
*
thread
);
extern
void
fatal_protocol_error
(
struct
thread
*
thread
,
const
char
*
err
,
...
);
extern
void
set_reply_fd
(
struct
thread
*
thread
,
int
pass_fd
);
extern
void
send_reply
(
struct
thread
*
thread
);
extern
void
open_master_socket
(
void
);
extern
void
close_master_socket
(
void
);
extern
void
lock_master_socket
(
int
locked
);
extern
void
trace_request
(
enum
request
req
,
int
fd
);
extern
void
trace_request
(
enum
request
req
);
extern
void
trace_reply
(
struct
thread
*
thread
);
/* get the request buffer */
...
...
@@ -138,7 +144,8 @@ DECL_HANDLER(create_device);
DECL_HANDLER
(
create_snapshot
);
DECL_HANDLER
(
next_process
);
DECL_HANDLER
(
wait_debug_event
);
DECL_HANDLER
(
send_debug_event
);
DECL_HANDLER
(
exception_event
);
DECL_HANDLER
(
output_debug_string
);
DECL_HANDLER
(
continue_debug_event
);
DECL_HANDLER
(
debug_process
);
DECL_HANDLER
(
read_process_memory
);
...
...
@@ -170,108 +177,108 @@ DECL_HANDLER(get_atom_name);
#ifdef WANT_REQUEST_HANDLERS
static
const
struct
handler
{
void
(
*
handler
)(
void
*
req
,
int
fd
);
unsigned
int
min_size
;
}
req_handlers
[
REQ_NB_REQUESTS
]
=
{
{
(
void
(
*
)())
req_new_process
,
sizeof
(
struct
new_process_request
)
}
,
{
(
void
(
*
)())
req_new_thread
,
sizeof
(
struct
new_thread_request
)
}
,
{
(
void
(
*
)())
req_boot_done
,
sizeof
(
struct
boot_done_request
)
}
,
{
(
void
(
*
)())
req_init_process
,
sizeof
(
struct
init_process_request
)
}
,
{
(
void
(
*
)())
req_init_process_done
,
sizeof
(
struct
init_process_done_request
)
}
,
{
(
void
(
*
)())
req_init_thread
,
sizeof
(
struct
init_thread_request
)
}
,
{
(
void
(
*
)())
req_get_thread_buffer
,
sizeof
(
struct
get_thread_buffer_request
)
}
,
{
(
void
(
*
)())
req_terminate_process
,
sizeof
(
struct
terminate_process_request
)
}
,
{
(
void
(
*
)())
req_terminate_thread
,
sizeof
(
struct
terminate_thread_request
)
}
,
{
(
void
(
*
)())
req_get_process_info
,
sizeof
(
struct
get_process_info_request
)
}
,
{
(
void
(
*
)())
req_set_process_info
,
sizeof
(
struct
set_process_info_request
)
}
,
{
(
void
(
*
)())
req_get_thread_info
,
sizeof
(
struct
get_thread_info_request
)
}
,
{
(
void
(
*
)())
req_set_thread_info
,
sizeof
(
struct
set_thread_info_request
)
}
,
{
(
void
(
*
)())
req_suspend_thread
,
sizeof
(
struct
suspend_thread_request
)
}
,
{
(
void
(
*
)())
req_resume_thread
,
sizeof
(
struct
resume_thread_request
)
}
,
{
(
void
(
*
)())
req_load_dll
,
sizeof
(
struct
load_dll_request
)
}
,
{
(
void
(
*
)())
req_unload_dll
,
sizeof
(
struct
unload_dll_request
)
}
,
{
(
void
(
*
)())
req_queue_apc
,
sizeof
(
struct
queue_apc_request
)
}
,
{
(
void
(
*
)())
req_get_apcs
,
sizeof
(
struct
get_apcs_request
)
}
,
{
(
void
(
*
)())
req_close_handle
,
sizeof
(
struct
close_handle_request
)
}
,
{
(
void
(
*
)())
req_get_handle_info
,
sizeof
(
struct
get_handle_info_request
)
}
,
{
(
void
(
*
)())
req_set_handle_info
,
sizeof
(
struct
set_handle_info_request
)
}
,
{
(
void
(
*
)())
req_dup_handle
,
sizeof
(
struct
dup_handle_request
)
}
,
{
(
void
(
*
)())
req_open_process
,
sizeof
(
struct
open_process_request
)
}
,
{
(
void
(
*
)())
req_select
,
sizeof
(
struct
select_request
)
}
,
{
(
void
(
*
)())
req_create_event
,
sizeof
(
struct
create_event_request
)
}
,
{
(
void
(
*
)())
req_event_op
,
sizeof
(
struct
event_op_request
)
}
,
{
(
void
(
*
)())
req_open_event
,
sizeof
(
struct
open_event_request
)
}
,
{
(
void
(
*
)())
req_create_mutex
,
sizeof
(
struct
create_mutex_request
)
}
,
{
(
void
(
*
)())
req_release_mutex
,
sizeof
(
struct
release_mutex_request
)
}
,
{
(
void
(
*
)())
req_open_mutex
,
sizeof
(
struct
open_mutex_request
)
}
,
{
(
void
(
*
)())
req_create_semaphore
,
sizeof
(
struct
create_semaphore_request
)
}
,
{
(
void
(
*
)())
req_release_semaphore
,
sizeof
(
struct
release_semaphore_request
)
}
,
{
(
void
(
*
)())
req_open_semaphore
,
sizeof
(
struct
open_semaphore_request
)
}
,
{
(
void
(
*
)())
req_create_file
,
sizeof
(
struct
create_file_request
)
}
,
{
(
void
(
*
)())
req_alloc_file_handle
,
sizeof
(
struct
alloc_file_handle_request
)
}
,
{
(
void
(
*
)())
req_get_read_fd
,
sizeof
(
struct
get_read_fd_request
)
}
,
{
(
void
(
*
)())
req_get_write_fd
,
sizeof
(
struct
get_write_fd_request
)
}
,
{
(
void
(
*
)())
req_set_file_pointer
,
sizeof
(
struct
set_file_pointer_request
)
}
,
{
(
void
(
*
)())
req_truncate_file
,
sizeof
(
struct
truncate_file_request
)
}
,
{
(
void
(
*
)())
req_set_file_time
,
sizeof
(
struct
set_file_time_request
)
}
,
{
(
void
(
*
)())
req_flush_file
,
sizeof
(
struct
flush_file_request
)
}
,
{
(
void
(
*
)())
req_get_file_info
,
sizeof
(
struct
get_file_info_request
)
}
,
{
(
void
(
*
)())
req_lock_file
,
sizeof
(
struct
lock_file_request
)
}
,
{
(
void
(
*
)())
req_unlock_file
,
sizeof
(
struct
unlock_file_request
)
}
,
{
(
void
(
*
)())
req_create_pipe
,
sizeof
(
struct
create_pipe_request
)
}
,
{
(
void
(
*
)())
req_create_socket
,
sizeof
(
struct
create_socket_request
)
}
,
{
(
void
(
*
)())
req_accept_socket
,
sizeof
(
struct
accept_socket_request
)
}
,
{
(
void
(
*
)())
req_set_socket_event
,
sizeof
(
struct
set_socket_event_request
)
}
,
{
(
void
(
*
)())
req_get_socket_event
,
sizeof
(
struct
get_socket_event_request
)
}
,
{
(
void
(
*
)())
req_enable_socket_event
,
sizeof
(
struct
enable_socket_event_request
)
}
,
{
(
void
(
*
)())
req_alloc_console
,
sizeof
(
struct
alloc_console_request
)
}
,
{
(
void
(
*
)())
req_free_console
,
sizeof
(
struct
free_console_request
)
}
,
{
(
void
(
*
)())
req_open_console
,
sizeof
(
struct
open_console_request
)
}
,
{
(
void
(
*
)())
req_set_console_fd
,
sizeof
(
struct
set_console_fd_request
)
}
,
{
(
void
(
*
)())
req_get_console_mode
,
sizeof
(
struct
get_console_mode_request
)
}
,
{
(
void
(
*
)())
req_set_console_mode
,
sizeof
(
struct
set_console_mode_request
)
}
,
{
(
void
(
*
)())
req_set_console_info
,
sizeof
(
struct
set_console_info_request
)
}
,
{
(
void
(
*
)())
req_get_console_info
,
sizeof
(
struct
get_console_info_request
)
}
,
{
(
void
(
*
)())
req_write_console_input
,
sizeof
(
struct
write_console_input_request
)
}
,
{
(
void
(
*
)())
req_read_console_input
,
sizeof
(
struct
read_console_input_request
)
}
,
{
(
void
(
*
)())
req_create_change_notification
,
sizeof
(
struct
create_change_notification_request
)
}
,
{
(
void
(
*
)())
req_create_mapping
,
sizeof
(
struct
create_mapping_request
)
}
,
{
(
void
(
*
)())
req_open_mapping
,
sizeof
(
struct
open_mapping_request
)
}
,
{
(
void
(
*
)())
req_get_mapping_info
,
sizeof
(
struct
get_mapping_info_request
)
}
,
{
(
void
(
*
)())
req_create_device
,
sizeof
(
struct
create_device_request
)
}
,
{
(
void
(
*
)())
req_create_snapshot
,
sizeof
(
struct
create_snapshot_request
)
}
,
{
(
void
(
*
)())
req_next_process
,
sizeof
(
struct
next_process_request
)
}
,
{
(
void
(
*
)())
req_wait_debug_event
,
sizeof
(
struct
wait_debug_event_request
)
}
,
{
(
void
(
*
)())
req_send_debug_event
,
sizeof
(
struct
send_debug_event_request
)
}
,
{
(
void
(
*
)())
req_continue_debug_event
,
sizeof
(
struct
continue_debug_event_request
)
}
,
{
(
void
(
*
)())
req_debug_process
,
sizeof
(
struct
debug_process_request
)
}
,
{
(
void
(
*
)())
req_read_process_memory
,
sizeof
(
struct
read_process_memory_request
)
}
,
{
(
void
(
*
)())
req_write_process_memory
,
sizeof
(
struct
write_process_memory_request
)
}
,
{
(
void
(
*
)())
req_create_key
,
sizeof
(
struct
create_key_request
)
}
,
{
(
void
(
*
)())
req_open_key
,
sizeof
(
struct
open_key_request
)
}
,
{
(
void
(
*
)())
req_delete_key
,
sizeof
(
struct
delete_key_request
)
}
,
{
(
void
(
*
)())
req_close_key
,
sizeof
(
struct
close_key_request
)
}
,
{
(
void
(
*
)())
req_enum_key
,
sizeof
(
struct
enum_key_request
)
}
,
{
(
void
(
*
)())
req_query_key_info
,
sizeof
(
struct
query_key_info_request
)
}
,
{
(
void
(
*
)())
req_set_key_value
,
sizeof
(
struct
set_key_value_request
)
}
,
{
(
void
(
*
)())
req_get_key_value
,
sizeof
(
struct
get_key_value_request
)
}
,
{
(
void
(
*
)())
req_enum_key_value
,
sizeof
(
struct
enum_key_value_request
)
}
,
{
(
void
(
*
)())
req_delete_key_value
,
sizeof
(
struct
delete_key_value_request
)
}
,
{
(
void
(
*
)())
req_load_registry
,
sizeof
(
struct
load_registry_request
)
}
,
{
(
void
(
*
)())
req_save_registry
,
sizeof
(
struct
save_registry_request
)
}
,
{
(
void
(
*
)())
req_set_registry_levels
,
sizeof
(
struct
set_registry_levels_request
)
}
,
{
(
void
(
*
)())
req_create_timer
,
sizeof
(
struct
create_timer_request
)
}
,
{
(
void
(
*
)())
req_open_timer
,
sizeof
(
struct
open_timer_request
)
}
,
{
(
void
(
*
)())
req_set_timer
,
sizeof
(
struct
set_timer_request
)
}
,
{
(
void
(
*
)())
req_cancel_timer
,
sizeof
(
struct
cancel_timer_request
)
}
,
{
(
void
(
*
)())
req_get_thread_context
,
sizeof
(
struct
get_thread_context_request
)
}
,
{
(
void
(
*
)())
req_set_thread_context
,
sizeof
(
struct
set_thread_context_request
)
}
,
{
(
void
(
*
)())
req_get_selector_entry
,
sizeof
(
struct
get_selector_entry_request
)
}
,
{
(
void
(
*
)())
req_add_atom
,
sizeof
(
struct
add_atom_request
)
}
,
{
(
void
(
*
)())
req_delete_atom
,
sizeof
(
struct
delete_atom_request
)
}
,
{
(
void
(
*
)())
req_find_atom
,
sizeof
(
struct
find_atom_request
)
}
,
{
(
void
(
*
)())
req_get_atom_name
,
sizeof
(
struct
get_atom_name_request
)
}
,
typedef
void
(
*
req_handler
)(
void
*
req
);
static
const
req_handler
req_handlers
[
REQ_NB_REQUESTS
]
=
{
(
req_handler
)
req_new_process
,
(
req_handler
)
req_new_thread
,
(
req_handler
)
req_boot_done
,
(
req_handler
)
req_init_process
,
(
req_handler
)
req_init_process_done
,
(
req_handler
)
req_init_thread
,
(
req_handler
)
req_get_thread_buffer
,
(
req_handler
)
req_terminate_process
,
(
req_handler
)
req_terminate_thread
,
(
req_handler
)
req_get_process_info
,
(
req_handler
)
req_set_process_info
,
(
req_handler
)
req_get_thread_info
,
(
req_handler
)
req_set_thread_info
,
(
req_handler
)
req_suspend_thread
,
(
req_handler
)
req_resume_thread
,
(
req_handler
)
req_load_dll
,
(
req_handler
)
req_unload_dll
,
(
req_handler
)
req_queue_apc
,
(
req_handler
)
req_get_apcs
,
(
req_handler
)
req_close_handle
,
(
req_handler
)
req_get_handle_info
,
(
req_handler
)
req_set_handle_info
,
(
req_handler
)
req_dup_handle
,
(
req_handler
)
req_open_process
,
(
req_handler
)
req_select
,
(
req_handler
)
req_create_event
,
(
req_handler
)
req_event_op
,
(
req_handler
)
req_open_event
,
(
req_handler
)
req_create_mutex
,
(
req_handler
)
req_release_mutex
,
(
req_handler
)
req_open_mutex
,
(
req_handler
)
req_create_semaphore
,
(
req_handler
)
req_release_semaphore
,
(
req_handler
)
req_open_semaphore
,
(
req_handler
)
req_create_file
,
(
req_handler
)
req_alloc_file_handle
,
(
req_handler
)
req_get_read_fd
,
(
req_handler
)
req_get_write_fd
,
(
req_handler
)
req_set_file_pointer
,
(
req_handler
)
req_truncate_file
,
(
req_handler
)
req_set_file_time
,
(
req_handler
)
req_flush_file
,
(
req_handler
)
req_get_file_info
,
(
req_handler
)
req_lock_file
,
(
req_handler
)
req_unlock_file
,
(
req_handler
)
req_create_pipe
,
(
req_handler
)
req_create_socket
,
(
req_handler
)
req_accept_socket
,
(
req_handler
)
req_set_socket_event
,
(
req_handler
)
req_get_socket_event
,
(
req_handler
)
req_enable_socket_event
,
(
req_handler
)
req_alloc_console
,
(
req_handler
)
req_free_console
,
(
req_handler
)
req_open_console
,
(
req_handler
)
req_set_console_fd
,
(
req_handler
)
req_get_console_mode
,
(
req_handler
)
req_set_console_mode
,
(
req_handler
)
req_set_console_info
,
(
req_handler
)
req_get_console_info
,
(
req_handler
)
req_write_console_input
,
(
req_handler
)
req_read_console_input
,
(
req_handler
)
req_create_change_notification
,
(
req_handler
)
req_create_mapping
,
(
req_handler
)
req_open_mapping
,
(
req_handler
)
req_get_mapping_info
,
(
req_handler
)
req_create_device
,
(
req_handler
)
req_create_snapshot
,
(
req_handler
)
req_next_process
,
(
req_handler
)
req_wait_debug_event
,
(
req_handler
)
req_exception_event
,
(
req_handler
)
req_output_debug_string
,
(
req_handler
)
req_continue_debug_event
,
(
req_handler
)
req_debug_process
,
(
req_handler
)
req_read_process_memory
,
(
req_handler
)
req_write_process_memory
,
(
req_handler
)
req_create_key
,
(
req_handler
)
req_open_key
,
(
req_handler
)
req_delete_key
,
(
req_handler
)
req_close_key
,
(
req_handler
)
req_enum_key
,
(
req_handler
)
req_query_key_info
,
(
req_handler
)
req_set_key_value
,
(
req_handler
)
req_get_key_value
,
(
req_handler
)
req_enum_key_value
,
(
req_handler
)
req_delete_key_value
,
(
req_handler
)
req_load_registry
,
(
req_handler
)
req_save_registry
,
(
req_handler
)
req_set_registry_levels
,
(
req_handler
)
req_create_timer
,
(
req_handler
)
req_open_timer
,
(
req_handler
)
req_set_timer
,
(
req_handler
)
req_cancel_timer
,
(
req_handler
)
req_get_thread_context
,
(
req_handler
)
req_set_thread_context
,
(
req_handler
)
req_get_selector_entry
,
(
req_handler
)
req_add_atom
,
(
req_handler
)
req_delete_atom
,
(
req_handler
)
req_find_atom
,
(
req_handler
)
req_get_atom_name
,
};
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/thread.c
View file @
ea0d028a
...
...
@@ -126,6 +126,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
if
(
!
(
thread
=
alloc_object
(
&
thread_ops
,
fd
)))
return
NULL
;
thread
->
unix_pid
=
0
;
/* not known yet */
thread
->
context
=
NULL
;
thread
->
teb
=
NULL
;
thread
->
mutex
=
NULL
;
thread
->
debug_ctx
=
NULL
;
...
...
server/thread.h
View file @
ea0d028a
...
...
@@ -47,6 +47,7 @@ struct thread
int
attached
;
/* is thread attached with ptrace? */
int
exit_code
;
/* thread exit code */
int
unix_pid
;
/* Unix pid of client */
CONTEXT
*
context
;
/* current context if in an exception handler */
void
*
teb
;
/* TEB address (in client address space) */
void
*
entry
;
/* thread entry point (in client address space) */
int
priority
;
/* priority level */
...
...
server/trace.c
View file @
ea0d028a
...
...
@@ -79,23 +79,28 @@ static void dump_context( const CONTEXT *context )
#endif
}
static
void
dump_
debug_event_t
(
const
debug_event_t
*
event
)
static
void
dump_
exc_record
(
const
EXCEPTION_RECORD
*
rec
)
{
int
i
;
fprintf
(
stderr
,
"{code=%lx,flags=%lx,rec=%p,addr=%p,params={"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionRecord
,
rec
->
ExceptionAddress
);
for
(
i
=
0
;
i
<
rec
->
NumberParameters
;
i
++
)
{
if
(
i
)
fputc
(
','
,
stderr
);
fprintf
(
stderr
,
"%lx"
,
rec
->
ExceptionInformation
[
i
]
);
}
fputc
(
'}'
,
stderr
);
}
static
void
dump_debug_event_t
(
const
debug_event_t
*
event
)
{
switch
(
event
->
code
)
{
case
EXCEPTION_DEBUG_EVENT
:
fprintf
(
stderr
,
"{exception,code=%x,flags=%x,rec=%p,addr=%p,params={"
,
event
->
info
.
exception
.
code
,
event
->
info
.
exception
.
flags
,
event
->
info
.
exception
.
record
,
event
->
info
.
exception
.
addr
);
for
(
i
=
0
;
i
<
event
->
info
.
exception
.
nb_params
;
i
++
)
{
if
(
i
)
fputc
(
','
,
stderr
);
fprintf
(
stderr
,
"%x"
,
event
->
info
.
exception
.
params
[
i
]
);
}
fprintf
(
stderr
,
"},first_chance=%d,context="
,
event
->
info
.
exception
.
first_chance
);
dump_context
(
&
event
->
info
.
exception
.
context
);
fputc
(
'}'
,
stderr
);
fprintf
(
stderr
,
"{exception,"
);
dump_exc_record
(
&
event
->
info
.
exception
.
record
);
fprintf
(
stderr
,
",first=%d}"
,
event
->
info
.
exception
.
first
);
break
;
case
CREATE_THREAD_DEBUG_EVENT
:
fprintf
(
stderr
,
"{create_thread,thread=%d,teb=%p,start=%p}"
,
...
...
@@ -927,17 +932,28 @@ static void dump_wait_debug_event_reply( const struct wait_debug_event_request *
dump_debug_event_t
(
&
req
->
event
);
}
static
void
dump_
send_debug_event_request
(
const
struct
send_debug
_event_request
*
req
)
static
void
dump_
exception_event_request
(
const
struct
exception
_event_request
*
req
)
{
fprintf
(
stderr
,
" event="
);
dump_debug_event_t
(
&
req
->
event
);
fprintf
(
stderr
,
" record="
);
dump_exc_record
(
&
req
->
record
);
fprintf
(
stderr
,
","
);
fprintf
(
stderr
,
" first=%d,"
,
req
->
first
);
fprintf
(
stderr
,
" context="
);
dump_context
(
&
req
->
context
);
}
static
void
dump_
send_debug_event_reply
(
const
struct
send_debug
_event_request
*
req
)
static
void
dump_
exception_event_reply
(
const
struct
exception
_event_request
*
req
)
{
fprintf
(
stderr
,
" status=%d"
,
req
->
status
);
}
static
void
dump_output_debug_string_request
(
const
struct
output_debug_string_request
*
req
)
{
fprintf
(
stderr
,
" string=%p,"
,
req
->
string
);
fprintf
(
stderr
,
" unicode=%d,"
,
req
->
unicode
);
fprintf
(
stderr
,
" length=%d"
,
req
->
length
);
}
static
void
dump_continue_debug_event_request
(
const
struct
continue_debug_event_request
*
req
)
{
fprintf
(
stderr
,
" pid=%p,"
,
req
->
pid
);
...
...
@@ -1310,7 +1326,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_create_snapshot_request
,
(
dump_func
)
dump_next_process_request
,
(
dump_func
)
dump_wait_debug_event_request
,
(
dump_func
)
dump_send_debug_event_request
,
(
dump_func
)
dump_exception_event_request
,
(
dump_func
)
dump_output_debug_string_request
,
(
dump_func
)
dump_continue_debug_event_request
,
(
dump_func
)
dump_debug_process_request
,
(
dump_func
)
dump_read_process_memory_request
,
...
...
@@ -1411,7 +1428,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_create_snapshot_reply
,
(
dump_func
)
dump_next_process_reply
,
(
dump_func
)
dump_wait_debug_event_reply
,
(
dump_func
)
dump_send_debug_event_reply
,
(
dump_func
)
dump_exception_event_reply
,
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
dump_read_process_memory_reply
,
...
...
@@ -1512,7 +1530,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_snapshot"
,
"next_process"
,
"wait_debug_event"
,
"send_debug_event"
,
"exception_event"
,
"output_debug_string"
,
"continue_debug_event"
,
"debug_process"
,
"read_process_memory"
,
...
...
@@ -1546,7 +1565,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
void
trace_request
(
enum
request
req
,
int
fd
)
void
trace_request
(
enum
request
req
)
{
current
->
last_req
=
req
;
if
(
req
<
REQ_NB_REQUESTS
)
...
...
@@ -1556,7 +1575,7 @@ void trace_request( enum request req, int fd )
}
else
fprintf
(
stderr
,
"%08x: %d("
,
(
unsigned
int
)
current
,
req
);
if
(
fd
!=
-
1
)
fprintf
(
stderr
,
" ) fd=%d
\n
"
,
fd
);
if
(
current
->
pass_fd
!=
-
1
)
fprintf
(
stderr
,
" ) fd=%d
\n
"
,
current
->
pass_
fd
);
else
fprintf
(
stderr
,
" )
\n
"
);
}
...
...
tools/make_requests
View file @
ea0d028a
...
...
@@ -18,6 +18,7 @@
"path_t"
=>
"&dump_path_t"
,
"debug_event_t"
=>
"&dump_debug_event_t"
,
"CONTEXT"
=>
"&dump_context"
,
"EXCEPTION_RECORD"
=>
"&dump_exc_record"
,
"char[1]"
=>
"\\\"%s\\\""
,
"WCHAR[1]"
=>
"&dump_unicode_string"
);
...
...
@@ -80,13 +81,11 @@ my @request_lines = ();
foreach
$req
(
@requests
)
{
push
@request_lines
,
"DECL_HANDLER($req);\n"
;
}
push
@request_lines
,
"\n#ifdef WANT_REQUEST_HANDLERS\n\n"
;
push
@request_lines
,
"static const struct handler {\n"
;
push
@request_lines
,
" void (*handler)( void *req, int fd );\n"
;
push
@request_lines
,
" unsigned int min_size;\n"
;
push
@request_lines
,
"} req_handlers[REQ_NB_REQUESTS] = {\n"
;
push
@request_lines
,
"typedef void (*req_handler)( void *req );\n"
;
push
@request_lines
,
"static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n"
;
foreach
$req
(
@requests
)
{
push
@request_lines
,
"
{ (void(*)())req_$req, sizeof(struct ${req}_request) }
,\n"
;
push
@request_lines
,
"
(req_handler)req_$req
,\n"
;
}
push
@request_lines
,
"};\n#endif /* WANT_REQUEST_HANDLERS */\n"
;
...
...
win32/except.c
View file @
ea0d028a
...
...
@@ -34,9 +34,10 @@
#include "process.h"
#include "thread.h"
#include "stackframe.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
seh
)
DEFAULT_DEBUG_CHANNEL
(
seh
)
;
/*******************************************************************
...
...
@@ -69,12 +70,16 @@ void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const LPDWORD
*/
DWORD
WINAPI
UnhandledExceptionFilter
(
PEXCEPTION_POINTERS
epointers
)
{
struct
exception_event_request
*
req
=
get_req_buffer
();
char
message
[
80
];
PDB
*
pdb
=
PROCESS_Current
();
if
(
DEBUG_SendExceptionEvent
(
epointers
->
ExceptionRecord
,
FALSE
,
epointers
->
ContextRecord
)
==
DBG_CONTINUE
)
return
EXCEPTION_CONTINUE_EXECUTION
;
/* send a last chance event to the debugger */
req
->
record
=
*
epointers
->
ExceptionRecord
;
req
->
first
=
0
;
req
->
context
=
*
epointers
->
ContextRecord
;
if
(
!
server_call_noerr
(
REQ_EXCEPTION_EVENT
))
*
epointers
->
ContextRecord
=
req
->
context
;
if
(
req
->
status
==
DBG_CONTINUE
)
return
EXCEPTION_CONTINUE_EXECUTION
;
if
(
pdb
->
top_filter
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment