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
2333099c
Commit
2333099c
authored
Jun 09, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Move signal handlers to the Unix library.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
fd1be205
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
3581 additions
and
4152 deletions
+3581
-4152
exception.c
dlls/ntdll/exception.c
+0
-71
loader.c
dlls/ntdll/loader.c
+2
-3
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+0
-18
server.c
dlls/ntdll/server.c
+0
-153
signal_arm.c
dlls/ntdll/signal_arm.c
+0
-587
signal_arm64.c
dlls/ntdll/signal_arm64.c
+0
-458
signal_i386.c
dlls/ntdll/signal_i386.c
+0
-1489
signal_powerpc.c
dlls/ntdll/signal_powerpc.c
+1
-579
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+21
-697
thread.c
dlls/ntdll/thread.c
+1
-9
loader.c
dlls/ntdll/unix/loader.c
+0
-6
server.c
dlls/ntdll/unix/server.c
+32
-1
signal_arm.c
dlls/ntdll/unix/signal_arm.c
+508
-0
signal_arm64.c
dlls/ntdll/unix/signal_arm64.c
+431
-0
signal_i386.c
dlls/ntdll/unix/signal_i386.c
+1303
-7
signal_powerpc.c
dlls/ntdll/unix/signal_powerpc.c
+488
-0
signal_x86_64.c
dlls/ntdll/unix/signal_x86_64.c
+777
-1
thread.c
dlls/ntdll/unix/thread.c
+1
-10
unix_private.h
dlls/ntdll/unix/unix_private.h
+8
-7
virtual.c
dlls/ntdll/unix/virtual.c
+5
-5
unixlib.h
dlls/ntdll/unixlib.h
+2
-8
virtual.c
dlls/ntdll/virtual.c
+1
-43
No files found.
dlls/ntdll/exception.c
View file @
2333099c
...
...
@@ -105,77 +105,6 @@ static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLE
/**********************************************************************
* wait_suspend
*
* Wait until the thread is no longer suspended.
*/
void
wait_suspend
(
CONTEXT
*
context
)
{
int
saved_errno
=
errno
;
/* wait with 0 timeout, will only return once the thread is no longer suspended */
unix_funcs
->
server_select
(
NULL
,
0
,
SELECT_INTERRUPTIBLE
,
0
,
context
,
NULL
,
NULL
);
errno
=
saved_errno
;
}
/**********************************************************************
* send_debug_event
*
* Send an EXCEPTION_DEBUG_EVENT event to the debugger.
*/
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
int
first_chance
,
CONTEXT
*
context
)
{
NTSTATUS
ret
;
DWORD
i
;
obj_handle_t
handle
=
0
;
client_ptr_t
params
[
EXCEPTION_MAXIMUM_PARAMETERS
];
CONTEXT
exception_context
=
*
context
;
select_op_t
select_op
;
sigset_t
old_set
;
if
(
!
NtCurrentTeb
()
->
Peb
->
BeingDebugged
)
return
0
;
/* no debugger present */
pthread_sigmask
(
SIG_BLOCK
,
&
server_block_set
,
&
old_set
);
for
(
i
=
0
;
i
<
min
(
rec
->
NumberParameters
,
EXCEPTION_MAXIMUM_PARAMETERS
);
i
++
)
params
[
i
]
=
rec
->
ExceptionInformation
[
i
];
SERVER_START_REQ
(
queue_exception_event
)
{
req
->
first
=
first_chance
;
req
->
code
=
rec
->
ExceptionCode
;
req
->
flags
=
rec
->
ExceptionFlags
;
req
->
record
=
wine_server_client_ptr
(
rec
->
ExceptionRecord
);
req
->
address
=
wine_server_client_ptr
(
rec
->
ExceptionAddress
);
req
->
len
=
i
*
sizeof
(
params
[
0
]);
wine_server_add_data
(
req
,
params
,
req
->
len
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
handle
=
reply
->
handle
;
}
SERVER_END_REQ
;
if
(
handle
)
{
select_op
.
wait
.
op
=
SELECT_WAIT
;
select_op
.
wait
.
handles
[
0
]
=
handle
;
unix_funcs
->
server_select
(
&
select_op
,
offsetof
(
select_op_t
,
wait
.
handles
[
1
]
),
SELECT_INTERRUPTIBLE
,
TIMEOUT_INFINITE
,
&
exception_context
,
NULL
,
NULL
);
SERVER_START_REQ
(
get_exception_status
)
{
req
->
handle
=
handle
;
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
ret
>=
0
)
*
context
=
exception_context
;
}
pthread_sigmask
(
SIG_SETMASK
,
&
old_set
,
NULL
);
return
ret
;
}
/**********************************************************************
* call_vectored_handlers
*
* Call the vectored handlers chain.
...
...
dlls/ntdll/loader.c
View file @
2333099c
...
...
@@ -3826,8 +3826,6 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknow
WINE_MODREF
*
wm
;
LPCWSTR
load_path
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
DllPath
.
Buffer
;
pthread_sigmask
(
SIG_UNBLOCK
,
&
server_block_set
,
NULL
);
if
(
process_detaching
)
return
;
RtlEnterCriticalSection
(
&
loader_section
);
...
...
@@ -4359,6 +4357,7 @@ void __wine_process_init(void)
static
const
WCHAR
kernel32W
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
's'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'3'
,
'2'
,
'\\'
,
'k'
,
'e'
,
'r'
,
'n'
,
'e'
,
'l'
,
'3'
,
'2'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
void
(
WINAPI
*
kernel32_start_process
)(
LPTHREAD_START_ROUTINE
,
void
*
)
=
NULL
;
RTL_USER_PROCESS_PARAMETERS
*
params
;
WINE_MODREF
*
wm
;
NTSTATUS
status
;
...
...
@@ -4467,7 +4466,7 @@ void __wine_process_init(void)
teb
->
Tib
.
StackLimit
=
stack
.
StackLimit
;
teb
->
DeallocationStack
=
stack
.
DeallocationStack
;
server_init_process_done
(
);
unix_funcs
->
server_init_process_done
(
kernel32_start_process
);
}
/***********************************************************************
...
...
dlls/ntdll/ntdll_misc.h
View file @
2333099c
...
...
@@ -58,8 +58,6 @@ extern NTSTATUS close_handle( HANDLE ) DECLSPEC_HIDDEN;
extern
ULONG_PTR
get_system_affinity_mask
(
void
)
DECLSPEC_HIDDEN
;
/* exceptions */
extern
void
wait_suspend
(
CONTEXT
*
context
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
int
first_chance
,
CONTEXT
*
context
)
DECLSPEC_HIDDEN
;
extern
LONG
call_vectored_handlers
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
DECLSPEC_HIDDEN
;
extern
void
DECLSPEC_NORETURN
raise_status
(
NTSTATUS
status
,
EXCEPTION_RECORD
*
rec
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
set_thread_context
(
HANDLE
handle
,
const
context_t
*
context
,
BOOL
*
self
)
DECLSPEC_HIDDEN
;
...
...
@@ -75,14 +73,10 @@ extern LPCSTR debugstr_us( const UNICODE_STRING *str ) DECLSPEC_HIDDEN;
extern
LPCSTR
debugstr_ObjectAttributes
(
const
OBJECT_ATTRIBUTES
*
oa
)
DECLSPEC_HIDDEN
;
/* init routines */
extern
SIZE_T
signal_stack_size
DECLSPEC_HIDDEN
;
extern
SIZE_T
signal_stack_mask
DECLSPEC_HIDDEN
;
extern
void
signal_init_process
(
void
)
DECLSPEC_HIDDEN
;
extern
void
version_init
(
void
)
DECLSPEC_HIDDEN
;
extern
void
debug_init
(
void
)
DECLSPEC_HIDDEN
;
extern
TEB
*
thread_init
(
SIZE_T
*
info_size
,
BOOL
*
suspend
)
DECLSPEC_HIDDEN
;
extern
void
actctx_init
(
void
)
DECLSPEC_HIDDEN
;
extern
void
virtual_init
(
void
)
DECLSPEC_HIDDEN
;
extern
void
fill_cpu_info
(
void
)
DECLSPEC_HIDDEN
;
extern
void
heap_set_debug_flags
(
HANDLE
handle
)
DECLSPEC_HIDDEN
;
extern
void
init_unix_codepage
(
void
)
DECLSPEC_HIDDEN
;
...
...
@@ -102,17 +96,6 @@ extern const char *config_dir DECLSPEC_HIDDEN;
extern
timeout_t
server_start_time
DECLSPEC_HIDDEN
;
extern
unsigned
int
server_cpus
DECLSPEC_HIDDEN
;
extern
BOOL
is_wow64
DECLSPEC_HIDDEN
;
extern
NTSTATUS
exec_wineloader
(
char
**
argv
,
int
socketfd
,
const
pe_image_info_t
*
pe_info
)
DECLSPEC_HIDDEN
;
extern
void
server_init_process
(
void
)
DECLSPEC_HIDDEN
;
extern
void
server_init_process_done
(
void
)
DECLSPEC_HIDDEN
;
extern
sigset_t
server_block_set
DECLSPEC_HIDDEN
;
extern
void
server_enter_uninterrupted_section
(
RTL_CRITICAL_SECTION
*
cs
,
sigset_t
*
sigset
)
DECLSPEC_HIDDEN
;
extern
void
server_leave_uninterrupted_section
(
RTL_CRITICAL_SECTION
*
cs
,
sigset_t
*
sigset
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
server_select
(
const
select_op_t
*
select_op
,
data_size_t
size
,
UINT
flags
,
timeout_t
abs_timeout
,
CONTEXT
*
context
,
RTL_CRITICAL_SECTION
*
cs
,
user_apc_t
*
user_apc
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
server_wait
(
const
select_op_t
*
select_op
,
data_size_t
size
,
UINT
flags
,
const
LARGE_INTEGER
*
timeout
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
server_queue_process_apc
(
HANDLE
process
,
const
apc_call_t
*
call
,
apc_result_t
*
result
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
alloc_object_attributes
(
const
OBJECT_ATTRIBUTES
*
attr
,
struct
object_attributes
**
ret
,
data_size_t
*
ret_len
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
validate_open_object_attributes
(
const
OBJECT_ATTRIBUTES
*
attr
)
DECLSPEC_HIDDEN
;
...
...
@@ -130,7 +113,6 @@ extern const WCHAR system_dir[] DECLSPEC_HIDDEN;
extern
const
WCHAR
syswow64_dir
[]
DECLSPEC_HIDDEN
;
extern
const
struct
unix_funcs
*
unix_funcs
DECLSPEC_HIDDEN
;
extern
void
(
WINAPI
*
kernel32_start_process
)(
LPTHREAD_START_ROUTINE
,
void
*
)
DECLSPEC_HIDDEN
;
/* Device IO */
extern
NTSTATUS
CDROM_DeviceIoControl
(
HANDLE
hDevice
,
...
...
dlls/ntdll/server.c
View file @
2333099c
...
...
@@ -23,87 +23,18 @@
#include <assert.h>
#include <ctype.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_LWP_H
#include <lwp.h>
#endif
#ifdef HAVE_PTHREAD_NP_H
# include <pthread_np.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#ifdef HAVE_SYS_THR_H
#include <sys/thr.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef __APPLE__
#include <crt_externs.h>
#include <spawn.h>
#ifndef _POSIX_SPAWN_DISABLE_ASLR
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
#endif
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winnt.h"
#include "wine/library.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
#include "ddk/wdm.h"
/* Some versions of glibc don't define this */
#ifndef SCM_RIGHTS
#define SCM_RIGHTS 1
#endif
#ifndef MSG_CMSG_CLOEXEC
#define MSG_CMSG_CLOEXEC 0
#endif
#define SOCKETNAME "socket"
/* name of the socket file */
#define LOCKNAME "lock"
/* name of the lock file */
const
char
*
build_dir
=
NULL
;
const
char
*
data_dir
=
NULL
;
...
...
@@ -114,8 +45,6 @@ BOOL is_wow64 = FALSE;
timeout_t
server_start_time
=
0
;
/* time of server startup */
sigset_t
server_block_set
;
/* signals to block during server calls */
/***********************************************************************
* wine_server_call (NTDLL.@)
*
...
...
@@ -145,26 +74,6 @@ unsigned int CDECL wine_server_call( void *req_ptr )
/***********************************************************************
* server_enter_uninterrupted_section
*/
void
server_enter_uninterrupted_section
(
RTL_CRITICAL_SECTION
*
cs
,
sigset_t
*
sigset
)
{
pthread_sigmask
(
SIG_BLOCK
,
&
server_block_set
,
sigset
);
RtlEnterCriticalSection
(
cs
);
}
/***********************************************************************
* server_leave_uninterrupted_section
*/
void
server_leave_uninterrupted_section
(
RTL_CRITICAL_SECTION
*
cs
,
sigset_t
*
sigset
)
{
RtlLeaveCriticalSection
(
cs
);
pthread_sigmask
(
SIG_SETMASK
,
sigset
,
NULL
);
}
/***********************************************************************
* wine_server_send_fd (NTDLL.@)
*
* Send a file descriptor to the server.
...
...
@@ -238,65 +147,3 @@ void CDECL wine_server_release_fd( HANDLE handle, int unix_fd )
{
unix_funcs
->
server_release_fd
(
handle
,
unix_fd
);
}
/***********************************************************************
* server_init_process
*
* Start the server and create the initial socket pair.
*/
void
server_init_process
(
void
)
{
/* setup the signal mask */
sigemptyset
(
&
server_block_set
);
sigaddset
(
&
server_block_set
,
SIGALRM
);
sigaddset
(
&
server_block_set
,
SIGIO
);
sigaddset
(
&
server_block_set
,
SIGINT
);
sigaddset
(
&
server_block_set
,
SIGHUP
);
sigaddset
(
&
server_block_set
,
SIGUSR1
);
sigaddset
(
&
server_block_set
,
SIGUSR2
);
sigaddset
(
&
server_block_set
,
SIGCHLD
);
}
/***********************************************************************
* server_init_process_done
*/
void
server_init_process_done
(
void
)
{
#ifdef __i386__
extern
struct
ldt_copy
*
__wine_ldt_copy
;
#endif
PEB
*
peb
=
NtCurrentTeb
()
->
Peb
;
IMAGE_NT_HEADERS
*
nt
=
RtlImageNtHeader
(
peb
->
ImageBaseAddress
);
void
*
entry
=
(
char
*
)
peb
->
ImageBaseAddress
+
nt
->
OptionalHeader
.
AddressOfEntryPoint
;
NTSTATUS
status
;
int
suspend
;
unix_funcs
->
server_init_process_done
();
/* Install signal handlers; this cannot be done earlier, since we cannot
* send exceptions to the debugger before the create process event that
* is sent by REQ_INIT_PROCESS_DONE.
* We do need the handlers in place by the time the request is over, so
* we set them up here. If we segfault between here and the server call
* something is very wrong... */
signal_init_process
();
/* Signal the parent process to continue */
SERVER_START_REQ
(
init_process_done
)
{
req
->
module
=
wine_server_client_ptr
(
peb
->
ImageBaseAddress
);
#ifdef __i386__
req
->
ldt_copy
=
wine_server_client_ptr
(
__wine_ldt_copy
);
#endif
req
->
entry
=
wine_server_client_ptr
(
entry
);
req
->
gui
=
(
nt
->
OptionalHeader
.
Subsystem
!=
IMAGE_SUBSYSTEM_WINDOWS_CUI
);
status
=
wine_server_call
(
req
);
suspend
=
reply
->
suspend
;
}
SERVER_END_REQ
;
assert
(
!
status
);
unix_funcs
->
start_process
(
entry
,
suspend
,
kernel32_start_process
);
}
dlls/ntdll/signal_arm.c
View file @
2333099c
...
...
@@ -32,22 +32,6 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# endif
#endif
#ifdef HAVE_SYS_SIGNAL_H
# include <sys/signal.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
...
...
@@ -62,104 +46,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
#if defined(__ANDROID__) && !defined(HAVE_SYS_UCONTEXT_H)
typedef
struct
ucontext
{
unsigned
long
uc_flags
;
struct
ucontext
*
uc_link
;
stack_t
uc_stack
;
struct
sigcontext
uc_mcontext
;
sigset_t
uc_sigmask
;
unsigned
long
uc_regspace
[
128
]
__attribute__
((
__aligned__
(
8
)));
}
ucontext_t
;
#endif
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name)
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.arm_r##reg_num)
/* Special Registers access */
# define SP_sig(context) REG_sig(arm_sp, context)
/* Stack pointer */
# define LR_sig(context) REG_sig(arm_lr, context)
/* Link register */
# define PC_sig(context) REG_sig(arm_pc, context)
/* Program counter */
# define CPSR_sig(context) REG_sig(arm_cpsr, context)
/* Current State Register */
# define IP_sig(context) REG_sig(arm_ip, context)
/* Intra-Procedure-call scratch register */
# define FP_sig(context) REG_sig(arm_fp, context)
/* Frame pointer */
/* Exceptions */
# define ERROR_sig(context) REG_sig(error_code, context)
# define TRAP_sig(context) REG_sig(trap_no, context)
#elif defined(__FreeBSD__)
/* All Registers access - only for local access */
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.__gregs[reg_num])
/* Special Registers access */
# define SP_sig(context) REGn_sig(_REG_SP, context)
/* Stack pointer */
# define LR_sig(context) REGn_sig(_REG_LR, context)
/* Link register */
# define PC_sig(context) REGn_sig(_REG_PC, context)
/* Program counter */
# define CPSR_sig(context) REGn_sig(_REG_CPSR, context)
/* Current State Register */
# define IP_sig(context) REGn_sig(_REG_R12, context)
/* Intra-Procedure-call scratch register */
# define FP_sig(context) REGn_sig(_REG_FP, context)
/* Frame pointer */
#endif
/* linux */
enum
arm_trap_code
{
TRAP_ARM_UNKNOWN
=
-
1
,
/* Unknown fault (TRAP_sig not defined) */
TRAP_ARM_PRIVINFLT
=
6
,
/* Invalid opcode exception */
TRAP_ARM_PAGEFLT
=
14
,
/* Page fault */
TRAP_ARM_ALIGNFLT
=
17
,
/* Alignment check exception */
};
typedef
void
(
WINAPI
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/***********************************************************************
* get_trap_code
*
* Get the trap code for a signal.
*/
static
inline
enum
arm_trap_code
get_trap_code
(
int
signal
,
const
ucontext_t
*
sigcontext
)
{
#ifdef TRAP_sig
enum
arm_trap_code
trap
=
TRAP_sig
(
sigcontext
);
if
(
trap
)
return
trap
;
#endif
switch
(
signal
)
{
case
SIGILL
:
return
TRAP_ARM_PRIVINFLT
;
case
SIGSEGV
:
return
TRAP_ARM_PAGEFLT
;
case
SIGBUS
:
return
TRAP_ARM_ALIGNFLT
;
default:
return
TRAP_ARM_UNKNOWN
;
}
}
/***********************************************************************
* get_error_code
*
* Get the error code for a signal.
*/
static
inline
WORD
get_error_code
(
const
ucontext_t
*
sigcontext
)
{
#ifdef ERROR_sig
return
ERROR_sig
(
sigcontext
);
#else
return
0
;
#endif
}
/*******************************************************************
* is_valid_frame
...
...
@@ -171,69 +57,6 @@ static inline BOOL is_valid_frame( void *frame )
(
void
**
)
frame
<
(
void
**
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
1
);
}
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->R##x = REGn_sig(x,sigcontext)
/* Save normal registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
#undef C
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
Sp
=
SP_sig
(
sigcontext
);
/* Stack pointer */
context
->
Lr
=
LR_sig
(
sigcontext
);
/* Link register */
context
->
Pc
=
PC_sig
(
sigcontext
);
/* Program Counter */
context
->
Cpsr
=
CPSR_sig
(
sigcontext
);
/* Current State Register */
context
->
R11
=
FP_sig
(
sigcontext
);
/* Frame pointer */
context
->
R12
=
IP_sig
(
sigcontext
);
/* Intra-Procedure-call scratch register */
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
#define C(x) REGn_sig(x,sigcontext) = context->R##x
/* Restore normal registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
#undef C
SP_sig
(
sigcontext
)
=
context
->
Sp
;
/* Stack pointer */
LR_sig
(
sigcontext
)
=
context
->
Lr
;
/* Link register */
PC_sig
(
sigcontext
)
=
context
->
Pc
;
/* Program Counter */
CPSR_sig
(
sigcontext
)
=
context
->
Cpsr
;
/* Current State Register */
FP_sig
(
sigcontext
)
=
context
->
R11
;
/* Frame pointer */
IP_sig
(
sigcontext
)
=
context
->
R12
;
/* Intra-Procedure-call scratch register */
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
inline
void
save_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"not implemented
\n
"
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"not implemented
\n
"
);
}
/**************************************************************************
* __chkstk (NTDLL.@)
...
...
@@ -283,81 +106,6 @@ __ASM_GLOBAL_FUNC( set_cpu_context,
"pop {pc}"
)
extern
void
raise_func_trampoline_thumb
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline_thumb
,
".thumb
\n\t
"
"blx r2
\n\t
"
"bkpt"
)
extern
void
raise_func_trampoline_arm
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline_arm
,
".arm
\n\t
"
"blx r2
\n\t
"
"bkpt"
)
/***********************************************************************
* setup_exception_record
*
* Setup the exception record and context on the thread stack.
*/
static
EXCEPTION_RECORD
*
setup_exception
(
ucontext_t
*
sigcontext
,
raise_func
func
)
{
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
}
*
stack
;
DWORD
exception_code
=
0
;
stack
=
(
struct
stack_layout
*
)(
SP_sig
(
sigcontext
)
&
~
3
);
stack
--
;
/* push the stack_layout structure */
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
PC_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
/* now modify the sigcontext to return to the raise function */
SP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
if
(
CPSR_sig
(
sigcontext
)
&
0x20
)
PC_sig
(
sigcontext
)
=
(
DWORD
)
raise_func_trampoline_thumb
;
else
PC_sig
(
sigcontext
)
=
(
DWORD
)
raise_func_trampoline_arm
;
REGn_sig
(
0
,
sigcontext
)
=
(
DWORD
)
&
stack
->
rec
;
/* first arg for raise_func */
REGn_sig
(
1
,
sigcontext
)
=
(
DWORD
)
&
stack
->
context
;
/* second arg for raise_func */
REGn_sig
(
2
,
sigcontext
)
=
(
DWORD
)
func
;
/* the raise_func as third arg for the trampoline */
return
&
stack
->
rec
;
}
/**********************************************************************
* raise_segv_exception
*/
static
void
WINAPI
raise_segv_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
NTSTATUS
status
;
switch
(
rec
->
ExceptionCode
)
{
case
EXCEPTION_ACCESS_VIOLATION
:
if
(
rec
->
NumberParameters
==
2
)
{
if
(
!
(
rec
->
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
(
void
*
)
rec
->
ExceptionInformation
[
1
],
rec
->
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
}
break
;
}
status
=
NtRaiseException
(
rec
,
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
rec
);
done
:
set_cpu_context
(
context
);
}
/**********************************************************************
* call_stack_handlers
*
...
...
@@ -413,74 +161,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
/*******************************************************************
* raise_exception
*
* Implementation of NtRaiseException.
*/
static
NTSTATUS
raise_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
{
NTSTATUS
status
;
if
(
first_chance
)
{
DWORD
c
;
TRACE
(
"code=%x flags=%x addr=%p pc=%08x tid=%04x
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
context
->
Pc
,
GetCurrentThreadId
()
);
for
(
c
=
0
;
c
<
rec
->
NumberParameters
;
c
++
)
TRACE
(
" info[%d]=%08lx
\n
"
,
c
,
rec
->
ExceptionInformation
[
c
]
);
if
(
rec
->
ExceptionCode
==
EXCEPTION_WINE_STUB
)
{
if
(
rec
->
ExceptionInformation
[
1
]
>>
16
)
MESSAGE
(
"wine: Call from %p to unimplemented function %s.%s, aborting
\n
"
,
rec
->
ExceptionAddress
,
(
char
*
)
rec
->
ExceptionInformation
[
0
],
(
char
*
)
rec
->
ExceptionInformation
[
1
]
);
else
MESSAGE
(
"wine: Call from %p to unimplemented function %s.%ld, aborting
\n
"
,
rec
->
ExceptionAddress
,
(
char
*
)
rec
->
ExceptionInformation
[
0
],
rec
->
ExceptionInformation
[
1
]
);
}
else
{
TRACE
(
" r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x
\n
"
,
context
->
R0
,
context
->
R1
,
context
->
R2
,
context
->
R3
,
context
->
R4
,
context
->
R5
);
TRACE
(
" r6=%08x r7=%08x r8=%08x r9=%08x r10=%08x r11=%08x
\n
"
,
context
->
R6
,
context
->
R7
,
context
->
R8
,
context
->
R9
,
context
->
R10
,
context
->
R11
);
TRACE
(
" r12=%08x sp=%08x lr=%08x pc=%08x cpsr=%08x
\n
"
,
context
->
R12
,
context
->
Sp
,
context
->
Lr
,
context
->
Pc
,
context
->
Cpsr
);
}
status
=
send_debug_event
(
rec
,
TRUE
,
context
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
return
STATUS_SUCCESS
;
if
(
call_vectored_handlers
(
rec
,
context
)
==
EXCEPTION_CONTINUE_EXECUTION
)
return
STATUS_SUCCESS
;
if
((
status
=
call_stack_handlers
(
rec
,
context
))
!=
STATUS_UNHANDLED_EXCEPTION
)
return
status
;
}
/* last chance exception */
status
=
send_debug_event
(
rec
,
FALSE
,
context
);
if
(
status
!=
DBG_CONTINUE
)
{
if
(
rec
->
ExceptionFlags
&
EH_STACK_INVALID
)
ERR
(
"Exception frame is not in stack limits => unable to dispatch exception.
\n
"
);
else
if
(
rec
->
ExceptionCode
==
STATUS_NONCONTINUABLE_EXCEPTION
)
ERR
(
"Process attempted to continue execution after noncontinuable exception.
\n
"
);
else
ERR
(
"Unhandled exception code %x flags %x addr %p
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
);
NtTerminateProcess
(
NtCurrentProcess
(),
rec
->
ExceptionCode
);
}
return
STATUS_SUCCESS
;
}
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS
WINAPI
KiUserExceptionDispatcher
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
...
...
@@ -526,273 +206,6 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
EXCEPTION_RECORD
*
rec
;
ucontext_t
*
context
=
ucontext
;
/* check for page fault inside the thread stack */
if
(
get_trap_code
(
signal
,
context
)
==
TRAP_ARM_PAGEFLT
)
{
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
info
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
rec
=
setup_exception
(
context
,
raise_segv_exception
);
rec
->
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
return
;
}
}
rec
=
setup_exception
(
context
,
raise_segv_exception
);
if
(
rec
->
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
return
;
switch
(
get_trap_code
(
signal
,
context
))
{
case
TRAP_ARM_PRIVINFLT
:
/* Invalid opcode exception */
rec
->
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_ARM_PAGEFLT
:
/* Page fault */
rec
->
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
rec
->
NumberParameters
=
2
;
rec
->
ExceptionInformation
[
0
]
=
(
get_error_code
(
context
)
&
0x800
)
!=
0
;
rec
->
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
info
->
si_addr
;
break
;
case
TRAP_ARM_ALIGNFLT
:
/* Alignment check exception */
rec
->
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
case
TRAP_ARM_UNKNOWN
:
/* Unknown fault code */
rec
->
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
rec
->
NumberParameters
=
2
;
rec
->
ExceptionInformation
[
0
]
=
0
;
rec
->
ExceptionInformation
[
1
]
=
0xffffffff
;
break
;
default
:
ERR
(
"Got unexpected trap %d
\n
"
,
get_trap_code
(
signal
,
context
));
rec
->
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
switch
(
info
->
si_code
)
{
case
TRAP_TRACE
:
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
default
:
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
break
;
}
save_context
(
&
context
,
ucontext
);
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
ucontext
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_fpu
(
&
context
,
sigcontext
);
save_context
(
&
context
,
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
restore_fpu
(
&
context
,
sigcontext
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#ifdef SIGBUS
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
#ifdef SIGTRAP
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* RtlUnwind (NTDLL.@)
*/
...
...
dlls/ntdll/signal_arm64.c
View file @
2333099c
...
...
@@ -88,59 +88,6 @@ struct MSVCRT_JUMP_BUFFER
double
D
[
8
];
};
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name)
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.regs[reg_num])
/* Special Registers access */
# define SP_sig(context) REG_sig(sp, context)
/* Stack pointer */
# define PC_sig(context) REG_sig(pc, context)
/* Program counter */
# define PSTATE_sig(context) REG_sig(pstate, context)
/* Current State Register */
# define FP_sig(context) REGn_sig(29, context)
/* Frame pointer */
# define LR_sig(context) REGn_sig(30, context)
/* Link Register */
static
struct
_aarch64_ctx
*
get_extended_sigcontext
(
ucontext_t
*
sigcontext
,
unsigned
int
magic
)
{
struct
_aarch64_ctx
*
ctx
=
(
struct
_aarch64_ctx
*
)
sigcontext
->
uc_mcontext
.
__reserved
;
while
((
char
*
)
ctx
<
(
char
*
)(
&
sigcontext
->
uc_mcontext
+
1
)
&&
ctx
->
magic
&&
ctx
->
size
)
{
if
(
ctx
->
magic
==
magic
)
return
ctx
;
ctx
=
(
struct
_aarch64_ctx
*
)((
char
*
)
ctx
+
ctx
->
size
);
}
return
NULL
;
}
static
struct
fpsimd_context
*
get_fpsimd_context
(
ucontext_t
*
sigcontext
)
{
return
(
struct
fpsimd_context
*
)
get_extended_sigcontext
(
sigcontext
,
FPSIMD_MAGIC
);
}
static
DWORD64
get_fault_esr
(
ucontext_t
*
sigcontext
)
{
struct
esr_context
*
esr
=
(
struct
esr_context
*
)
get_extended_sigcontext
(
sigcontext
,
ESR_MAGIC
);
if
(
esr
)
return
esr
->
esr
;
return
0
;
}
#endif
/* linux */
static
const
size_t
teb_size
=
0x2000
;
/* we reserve two pages for the TEB */
typedef
void
(
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/* stack layout when calling an exception raise function */
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
void
*
redzone
[
2
];
};
struct
arm64_thread_data
{
void
*
exit_frame
;
/* exit frame pointer */
...
...
@@ -155,15 +102,6 @@ static inline struct arm64_thread_data *arm64_thread_data(void)
return
(
struct
arm64_thread_data
*
)
NtCurrentTeb
()
->
SystemReserved2
;
}
/***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
teb_size
;
}
/*******************************************************************
* is_valid_frame
...
...
@@ -175,85 +113,6 @@ static inline BOOL is_valid_frame( ULONG_PTR frame )
(
void
**
)
frame
<
(
void
**
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
1
);
}
/***********************************************************************
* is_inside_signal_stack
*
* Check if pointer is inside the signal stack.
*/
static
inline
BOOL
is_inside_signal_stack
(
void
*
ptr
)
{
return
((
char
*
)
ptr
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
ptr
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
);
}
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
DWORD
i
;
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
u
.
s
.
Fp
=
FP_sig
(
sigcontext
);
/* Frame pointer */
context
->
u
.
s
.
Lr
=
LR_sig
(
sigcontext
);
/* Link register */
context
->
Sp
=
SP_sig
(
sigcontext
);
/* Stack pointer */
context
->
Pc
=
PC_sig
(
sigcontext
);
/* Program Counter */
context
->
Cpsr
=
PSTATE_sig
(
sigcontext
);
/* Current State Register */
for
(
i
=
0
;
i
<=
28
;
i
++
)
context
->
u
.
X
[
i
]
=
REGn_sig
(
i
,
sigcontext
);
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
DWORD
i
;
FP_sig
(
sigcontext
)
=
context
->
u
.
s
.
Fp
;
/* Frame pointer */
LR_sig
(
sigcontext
)
=
context
->
u
.
s
.
Lr
;
/* Link register */
SP_sig
(
sigcontext
)
=
context
->
Sp
;
/* Stack pointer */
PC_sig
(
sigcontext
)
=
context
->
Pc
;
/* Program Counter */
PSTATE_sig
(
sigcontext
)
=
context
->
Cpsr
;
/* Current State Register */
for
(
i
=
0
;
i
<=
28
;
i
++
)
REGn_sig
(
i
,
sigcontext
)
=
context
->
u
.
X
[
i
];
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
void
save_fpu
(
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
struct
fpsimd_context
*
fp
=
get_fpsimd_context
(
sigcontext
);
if
(
!
fp
)
return
;
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
Fpcr
=
fp
->
fpcr
;
context
->
Fpsr
=
fp
->
fpsr
;
memcpy
(
context
->
V
,
fp
->
vregs
,
sizeof
(
context
->
V
)
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
void
restore_fpu
(
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
struct
fpsimd_context
*
fp
=
get_fpsimd_context
(
sigcontext
);
if
(
!
fp
)
return
;
fp
->
fpcr
=
context
->
Fpcr
;
fp
->
fpsr
=
context
->
Fpsr
;
memcpy
(
fp
->
vregs
,
context
->
V
,
sizeof
(
fp
->
vregs
)
);
}
/***********************************************************************
* RtlCaptureContext (NTDLL.@)
...
...
@@ -780,316 +639,6 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
/***********************************************************************
* setup_exception
*
* Setup the exception record and context on the thread stack.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
struct
stack_layout
*
stack
;
DWORD
exception_code
=
0
;
/* push the stack_layout structure */
stack
=
(
struct
stack_layout
*
)((
SP_sig
(
sigcontext
)
-
sizeof
(
*
stack
))
&
~
15
);
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
PC_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
save_fpu
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
extern
void
raise_func_trampoline
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
,
void
*
sp
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline
,
__ASM_CFI
(
".cfi_signal_frame
\n\t
"
)
"stp x29, x30, [sp, #-0x20]!
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_offset 32
\n\t
"
)
__ASM_CFI
(
".cfi_offset 29, -32
\n\t
"
)
__ASM_CFI
(
".cfi_offset 30, -24
\n\t
"
)
"mov x29, sp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register 29
\n\t
"
)
"str x3, [sp, 0x10]
\n\t
"
__ASM_CFI
(
".cfi_remember_state
\n\t
"
)
__ASM_CFI
(
".cfi_escape 0x0f,0x03,0x8d,0x10,0x06
\n\t
"
)
/* CFA */
__ASM_CFI
(
".cfi_escape 0x10,0x1d,0x02,0x8d,0x00
\n\t
"
)
/* x29 */
__ASM_CFI
(
".cfi_escape 0x10,0x1e,0x02,0x8d,0x08
\n\t
"
)
/* x30 */
"blr x2
\n\t
"
__ASM_CFI
(
".cfi_restore_state
\n\t
"
)
"brk #1"
)
/***********************************************************************
* setup_raise_exception
*
* Modify the signal context to call the exception raise function.
*/
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
NTSTATUS
status
=
send_debug_event
(
&
stack
->
rec
,
TRUE
,
&
stack
->
context
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
REGn_sig
(
3
,
sigcontext
)
=
SP_sig
(
sigcontext
);
/* original stack pointer, fourth arg for raise_func_trampoline */
SP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
stack
;
LR_sig
(
sigcontext
)
=
PC_sig
(
sigcontext
);
PC_sig
(
sigcontext
)
=
(
ULONG_PTR
)
raise_func_trampoline
;
/* raise_generic_exception; */
REGn_sig
(
0
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
rec
;
/* first arg for raise_generic_exception */
REGn_sig
(
1
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
context
;
/* second arg for raise_generic_exception */
REGn_sig
(
2
,
sigcontext
)
=
(
ULONG_PTR
)
KiUserExceptionDispatcher
;
/* third arg for raise_func_trampoline */
REGn_sig
(
18
,
sigcontext
)
=
(
ULONG_PTR
)
NtCurrentTeb
();
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
struct
stack_layout
*
stack
;
ucontext_t
*
context
=
ucontext
;
/* check for page fault inside the thread stack */
if
(
signal
==
SIGSEGV
)
{
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
info
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception
(
context
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception
(
context
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
signal
)
{
case
SIGILL
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
SIGSEGV
:
/* Segmentation fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
get_fault_esr
(
context
)
&
0x40
)
!=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
info
->
si_addr
;
if
(
!
(
stack
->
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
(
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
)))
return
;
break
;
case
SIGBUS
:
/* Alignment check exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default
:
ERR
(
"Got unexpected signal %i
\n
"
,
signal
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done
:
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
ucontext_t
*
context
=
ucontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
info
->
si_code
)
{
case
TRAP_TRACE
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
context
.
Pc
+=
4
;
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* usr2_handler
*
* Handler for SIGUSR2, used to set a thread context.
*/
static
void
usr2_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
*
context
=
InterlockedExchangePointer
(
(
void
**
)
&
arm64_thread_data
()
->
context
,
NULL
);
if
(
!
context
)
return
;
if
((
context
->
ContextFlags
&
~
CONTEXT_ARM64
)
&
CONTEXT_FLOATING_POINT
)
restore_fpu
(
context
,
sigcontext
);
restore_context
(
context
,
sigcontext
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
|
SA_ONSTACK
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr2_handler
;
if
(
sigaction
(
SIGUSR2
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#ifdef SIGBUS
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
#ifdef SIGTRAP
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* Definitions for Win32 unwind tables
*/
...
...
@@ -1691,13 +1240,6 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
unwind_done
:
if
(
!
dispatch
.
EstablisherFrame
)
break
;
if
(
is_inside_signal_stack
(
(
void
*
)
dispatch
.
EstablisherFrame
))
{
TRACE
(
"frame %lx is inside signal stack (%p-%p)
\n
"
,
dispatch
.
EstablisherFrame
,
get_signal_stack
(),
(
char
*
)
get_signal_stack
()
+
signal_stack_size
);
*
context
=
new_context
;
continue
;
}
if
(
!
is_valid_frame
(
dispatch
.
EstablisherFrame
))
{
ERR
(
"invalid frame %lx (%p-%p)
\n
"
,
dispatch
.
EstablisherFrame
,
...
...
dlls/ntdll/signal_i386.c
View file @
2333099c
...
...
@@ -35,19 +35,6 @@
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# endif
#endif
#ifdef HAVE_SYS_SIGNAL_H
# include <sys/signal.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
...
...
@@ -56,12 +43,6 @@
#include "wine/exception.h"
#include "wine/debug.h"
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#undef ERR
/* Solaris needs to define this */
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
/* not defined for x86, so copy the x86_64 definition */
...
...
@@ -91,405 +72,6 @@ typedef struct
BYTE
Reserved4
[
96
];
}
XMM_SAVE_AREA32
;
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef __linux__
#ifndef HAVE_SYS_UCONTEXT_H
enum
{
REG_GS
,
REG_FS
,
REG_ES
,
REG_DS
,
REG_EDI
,
REG_ESI
,
REG_EBP
,
REG_ESP
,
REG_EBX
,
REG_EDX
,
REG_ECX
,
REG_EAX
,
REG_TRAPNO
,
REG_ERR
,
REG_EIP
,
REG_CS
,
REG_EFL
,
REG_UESP
,
REG_SS
,
NGREG
};
typedef
int
greg_t
;
typedef
greg_t
gregset_t
[
NGREG
];
struct
_libc_fpreg
{
unsigned
short
significand
[
4
];
unsigned
short
exponent
;
};
struct
_libc_fpstate
{
unsigned
long
cw
;
unsigned
long
sw
;
unsigned
long
tag
;
unsigned
long
ipoff
;
unsigned
long
cssel
;
unsigned
long
dataoff
;
unsigned
long
datasel
;
struct
_libc_fpreg
_st
[
8
];
unsigned
long
status
;
};
typedef
struct
_libc_fpstate
*
fpregset_t
;
typedef
struct
{
gregset_t
gregs
;
fpregset_t
fpregs
;
unsigned
long
oldmask
;
unsigned
long
cr2
;
}
mcontext_t
;
typedef
struct
ucontext
{
unsigned
long
uc_flags
;
struct
ucontext
*
uc_link
;
stack_t
uc_stack
;
mcontext_t
uc_mcontext
;
sigset_t
uc_sigmask
;
}
ucontext_t
;
#endif
/* HAVE_SYS_UCONTEXT_H */
#define EAX_sig(context) ((context)->uc_mcontext.gregs[REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[REG_EBP])
#define ESP_sig(context) ((context)->uc_mcontext.gregs[REG_ESP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((FLOATING_SAVE_AREA*)((context)->uc_mcontext.fpregs))
#define FPUX_sig(context) (FPU_sig(context) && !((context)->uc_mcontext.fpregs->status >> 16) ? (XMM_SAVE_AREA32 *)(FPU_sig(context) + 1) : NULL)
#ifdef __ANDROID__
/* custom signal restorer since we may have unmapped the one in vdso, and bionic doesn't check for that */
void
rt_sigreturn
(
void
);
__ASM_GLOBAL_FUNC
(
rt_sigreturn
,
"movl $173,%eax
\n\t
"
/* NR_rt_sigreturn */
"int $0x80"
);
#endif
#elif defined (__BSDI__)
#include <machine/frame.h>
typedef
struct
trapframe
ucontext_t
;
#define EAX_sig(context) ((context)->tf_eax)
#define EBX_sig(context) ((context)->tf_ebx)
#define ECX_sig(context) ((context)->tf_ecx)
#define EDX_sig(context) ((context)->tf_edx)
#define ESI_sig(context) ((context)->tf_esi)
#define EDI_sig(context) ((context)->tf_edi)
#define EBP_sig(context) ((context)->tf_ebp)
#define CS_sig(context) ((context)->tf_cs)
#define DS_sig(context) ((context)->tf_ds)
#define ES_sig(context) ((context)->tf_es)
#define SS_sig(context) ((context)->tf_ss)
#define EFL_sig(context) ((context)->tf_eflags)
#define EIP_sig(context) (*((unsigned long*)&(context)->tf_eip))
#define ESP_sig(context) (*((unsigned long*)&(context)->tf_esp))
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <machine/trap.h>
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->uc_mcontext.mc_eax)
#define EBX_sig(context) ((context)->uc_mcontext.mc_ebx)
#define ECX_sig(context) ((context)->uc_mcontext.mc_ecx)
#define EDX_sig(context) ((context)->uc_mcontext.mc_edx)
#define ESI_sig(context) ((context)->uc_mcontext.mc_esi)
#define EDI_sig(context) ((context)->uc_mcontext.mc_edi)
#define EBP_sig(context) ((context)->uc_mcontext.mc_ebp)
#define CS_sig(context) ((context)->uc_mcontext.mc_cs)
#define DS_sig(context) ((context)->uc_mcontext.mc_ds)
#define ES_sig(context) ((context)->uc_mcontext.mc_es)
#define FS_sig(context) ((context)->uc_mcontext.mc_fs)
#define GS_sig(context) ((context)->uc_mcontext.mc_gs)
#define SS_sig(context) ((context)->uc_mcontext.mc_ss)
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
#define EFL_sig(context) ((context)->uc_mcontext.mc_eflags)
#define EIP_sig(context) ((context)->uc_mcontext.mc_eip)
#define ESP_sig(context) ((context)->uc_mcontext.mc_esp)
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#elif defined (__OpenBSD__)
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->sc_eax)
#define EBX_sig(context) ((context)->sc_ebx)
#define ECX_sig(context) ((context)->sc_ecx)
#define EDX_sig(context) ((context)->sc_edx)
#define ESI_sig(context) ((context)->sc_esi)
#define EDI_sig(context) ((context)->sc_edi)
#define EBP_sig(context) ((context)->sc_ebp)
#define CS_sig(context) ((context)->sc_cs)
#define DS_sig(context) ((context)->sc_ds)
#define ES_sig(context) ((context)->sc_es)
#define FS_sig(context) ((context)->sc_fs)
#define GS_sig(context) ((context)->sc_gs)
#define SS_sig(context) ((context)->sc_ss)
#define TRAP_sig(context) ((context)->sc_trapno)
#define ERROR_sig(context) ((context)->sc_err)
#define EFL_sig(context) ((context)->sc_eflags)
#define EIP_sig(context) ((context)->sc_eip)
#define ESP_sig(context) ((context)->sc_esp)
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#define T_MCHK T_MACHK
#define T_XMMFLT T_XFTRAP
#elif defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
#if defined(_SCO_DS) || defined(__sun)
#include <sys/regset.h>
#endif
#ifdef _SCO_DS
#define gregs regs
#endif
#define EAX_sig(context) ((context)->uc_mcontext.gregs[EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[EBP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[EIP])
#ifdef UESP
#define ESP_sig(context) ((context)->uc_mcontext.gregs[UESP])
#elif defined(R_ESP)
#define ESP_sig(context) ((context)->uc_mcontext.gregs[R_ESP])
#else
#define ESP_sig(context) ((context)->uc_mcontext.gregs[ESP])
#endif
#ifdef ERR
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[ERR])
#endif
#ifdef TRAPNO
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[TRAPNO])
#endif
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#elif defined (__APPLE__)
#include <i386/user_ldt.h>
/* work around silly renaming of struct members in OS X 10.5 */
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
#define EAX_sig(context) ((context)->uc_mcontext->__ss.__eax)
#define EBX_sig(context) ((context)->uc_mcontext->__ss.__ebx)
#define ECX_sig(context) ((context)->uc_mcontext->__ss.__ecx)
#define EDX_sig(context) ((context)->uc_mcontext->__ss.__edx)
#define ESI_sig(context) ((context)->uc_mcontext->__ss.__esi)
#define EDI_sig(context) ((context)->uc_mcontext->__ss.__edi)
#define EBP_sig(context) ((context)->uc_mcontext->__ss.__ebp)
#define CS_sig(context) ((context)->uc_mcontext->__ss.__cs)
#define DS_sig(context) ((context)->uc_mcontext->__ss.__ds)
#define ES_sig(context) ((context)->uc_mcontext->__ss.__es)
#define FS_sig(context) ((context)->uc_mcontext->__ss.__fs)
#define GS_sig(context) ((context)->uc_mcontext->__ss.__gs)
#define SS_sig(context) ((context)->uc_mcontext->__ss.__ss)
#define EFL_sig(context) ((context)->uc_mcontext->__ss.__eflags)
#define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__eip))
#define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__esp))
#define TRAP_sig(context) ((context)->uc_mcontext->__es.__trapno)
#define ERROR_sig(context) ((context)->uc_mcontext->__es.__err)
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
#else
#define EAX_sig(context) ((context)->uc_mcontext->ss.eax)
#define EBX_sig(context) ((context)->uc_mcontext->ss.ebx)
#define ECX_sig(context) ((context)->uc_mcontext->ss.ecx)
#define EDX_sig(context) ((context)->uc_mcontext->ss.edx)
#define ESI_sig(context) ((context)->uc_mcontext->ss.esi)
#define EDI_sig(context) ((context)->uc_mcontext->ss.edi)
#define EBP_sig(context) ((context)->uc_mcontext->ss.ebp)
#define CS_sig(context) ((context)->uc_mcontext->ss.cs)
#define DS_sig(context) ((context)->uc_mcontext->ss.ds)
#define ES_sig(context) ((context)->uc_mcontext->ss.es)
#define FS_sig(context) ((context)->uc_mcontext->ss.fs)
#define GS_sig(context) ((context)->uc_mcontext->ss.gs)
#define SS_sig(context) ((context)->uc_mcontext->ss.ss)
#define EFL_sig(context) ((context)->uc_mcontext->ss.eflags)
#define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
#define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.esp))
#define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
#define ERROR_sig(context) ((context)->uc_mcontext->es.err)
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->fs.fpu_fcw)
#endif
#elif defined(__NetBSD__)
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.__gregs[_REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.__gregs[_REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EBP])
#define ESP_sig(context) _UC_MACHINE_SP(context)
#define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_EFL])
#define EIP_sig(context) _UC_MACHINE_PC(context)
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&((context)->uc_mcontext.__fpregs))
#define T_MCHK T_MCA
#define T_XMMFLT T_XMM
#elif defined(__GNU__)
#include <mach/i386/mach_i386.h>
#include <mach/mach_traps.h>
#define EAX_sig(context) ((context)->uc_mcontext.gregs[REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[REG_EBP])
#define ESP_sig(context) ((context)->uc_mcontext.gregs[REG_ESP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((FLOATING_SAVE_AREA *)&(context)->uc_mcontext.fpregs.fp_reg_set.fpchip_state)
#define FPUX_sig(context) NULL
#else
#error You must define the signal context functions for your platform
#endif
/* linux */
/* stack layout when calling an exception raise function */
struct
stack_layout
{
void
*
ret_addr
;
/* return address from raise_generic_exception */
EXCEPTION_RECORD
*
rec_ptr
;
/* first arg for raise_generic_exception */
CONTEXT
*
context_ptr
;
/* second arg for raise_generic_exception */
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
DWORD
ebp
;
DWORD
eip
;
};
static
ULONG
first_ldt_entry
=
32
;
enum
i386_trap_code
{
TRAP_x86_UNKNOWN
=
-
1
,
/* Unknown fault (TRAP_sig not defined) */
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
TRAP_x86_DIVIDE
=
T_DIVIDE
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
T_TRCTRAP
,
/* Single-step exception */
TRAP_x86_NMI
=
T_NMI
,
/* NMI interrupt */
TRAP_x86_BPTFLT
=
T_BPTFLT
,
/* Breakpoint exception */
TRAP_x86_OFLOW
=
T_OFLOW
,
/* Overflow exception */
TRAP_x86_BOUND
=
T_BOUND
,
/* Bound range exception */
TRAP_x86_PRIVINFLT
=
T_PRIVINFLT
,
/* Invalid opcode exception */
TRAP_x86_DNA
=
T_DNA
,
/* Device not available exception */
TRAP_x86_DOUBLEFLT
=
T_DOUBLEFLT
,
/* Double fault exception */
TRAP_x86_FPOPFLT
=
T_FPOPFLT
,
/* Coprocessor segment overrun */
TRAP_x86_TSSFLT
=
T_TSSFLT
,
/* Invalid TSS exception */
TRAP_x86_SEGNPFLT
=
T_SEGNPFLT
,
/* Segment not present exception */
TRAP_x86_STKFLT
=
T_STKFLT
,
/* Stack fault */
TRAP_x86_PROTFLT
=
T_PROTFLT
,
/* General protection fault */
TRAP_x86_PAGEFLT
=
T_PAGEFLT
,
/* Page fault */
TRAP_x86_ARITHTRAP
=
T_ARITHTRAP
,
/* Floating point exception */
TRAP_x86_ALIGNFLT
=
T_ALIGNFLT
,
/* Alignment check exception */
TRAP_x86_MCHK
=
T_MCHK
,
/* Machine check exception */
TRAP_x86_CACHEFLT
=
T_XMMFLT
/* Cache flush exception */
#else
TRAP_x86_DIVIDE
=
0
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
1
,
/* Single-step exception */
TRAP_x86_NMI
=
2
,
/* NMI interrupt */
TRAP_x86_BPTFLT
=
3
,
/* Breakpoint exception */
TRAP_x86_OFLOW
=
4
,
/* Overflow exception */
TRAP_x86_BOUND
=
5
,
/* Bound range exception */
TRAP_x86_PRIVINFLT
=
6
,
/* Invalid opcode exception */
TRAP_x86_DNA
=
7
,
/* Device not available exception */
TRAP_x86_DOUBLEFLT
=
8
,
/* Double fault exception */
TRAP_x86_FPOPFLT
=
9
,
/* Coprocessor segment overrun */
TRAP_x86_TSSFLT
=
10
,
/* Invalid TSS exception */
TRAP_x86_SEGNPFLT
=
11
,
/* Segment not present exception */
TRAP_x86_STKFLT
=
12
,
/* Stack fault */
TRAP_x86_PROTFLT
=
13
,
/* General protection fault */
TRAP_x86_PAGEFLT
=
14
,
/* Page fault */
TRAP_x86_ARITHTRAP
=
16
,
/* Floating point exception */
TRAP_x86_ALIGNFLT
=
17
,
/* Alignment check exception */
TRAP_x86_MCHK
=
18
,
/* Machine check exception */
TRAP_x86_CACHEFLT
=
19
/* SIMD exception (via SIGFPE) if CPU is SSE capable
otherwise Cache flush exception (via SIGSEV) */
#endif
};
struct
x86_thread_data
{
...
...
@@ -513,13 +95,6 @@ static inline struct x86_thread_data *x86_thread_data(void)
return
(
struct
x86_thread_data
*
)
NtCurrentTeb
()
->
SystemReserved2
;
}
static
inline
WORD
get_cs
(
void
)
{
WORD
res
;
__asm__
(
"movw %%cs,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
WORD
get_ds
(
void
)
{
WORD
res
;
__asm__
(
"movw %%ds,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
WORD
get_fs
(
void
)
{
WORD
res
;
__asm__
(
"movw %%fs,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
WORD
get_gs
(
void
)
{
WORD
res
;
__asm__
(
"movw %%gs,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
void
set_fs
(
WORD
val
)
{
__asm__
(
"mov %0,%%fs"
::
"r"
(
val
));
}
static
inline
void
set_gs
(
WORD
val
)
{
__asm__
(
"mov %0,%%gs"
::
"r"
(
val
));
}
/* Exception record for handling exceptions happening inside exception handlers */
typedef
struct
{
...
...
@@ -532,61 +107,6 @@ extern DWORD EXC_CallHandler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_R
PEXCEPTION_HANDLER
handler
,
PEXCEPTION_HANDLER
nested_handler
);
/***********************************************************************
* is_gdt_sel
*/
static
inline
int
is_gdt_sel
(
WORD
sel
)
{
return
!
(
sel
&
4
);
}
/***********************************************************************
* ldt_is_system
*/
static
inline
int
ldt_is_system
(
WORD
sel
)
{
return
is_gdt_sel
(
sel
)
||
((
sel
>>
3
)
<
first_ldt_entry
);
}
/***********************************************************************
* get_trap_code
*
* Get the trap code for a signal.
*/
static
inline
enum
i386_trap_code
get_trap_code
(
const
ucontext_t
*
sigcontext
)
{
#ifdef TRAP_sig
return
TRAP_sig
(
sigcontext
);
#else
return
TRAP_x86_UNKNOWN
;
/* unknown trap code */
#endif
}
/***********************************************************************
* get_error_code
*
* Get the error code for a signal.
*/
static
inline
WORD
get_error_code
(
const
ucontext_t
*
sigcontext
)
{
#ifdef ERROR_sig
return
ERROR_sig
(
sigcontext
);
#else
return
0
;
#endif
}
/***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
4096
;
}
/***********************************************************************
* has_fpux
*/
static
inline
int
has_fpux
(
void
)
...
...
@@ -595,19 +115,6 @@ static inline int has_fpux(void)
}
/***********************************************************************
* get_current_teb
*
* Get the current teb based on the stack pointer.
*/
static
inline
TEB
*
get_current_teb
(
void
)
{
unsigned
long
esp
;
__asm__
(
"movl %%esp,%0"
:
"=g"
(
esp
)
);
return
(
TEB
*
)(
esp
&
~
signal_stack_mask
);
}
/*******************************************************************
* is_valid_frame
*/
...
...
@@ -753,111 +260,6 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
#ifdef __sun
/* We have to workaround two Solaris breakages:
* - Solaris doesn't restore %ds and %es before calling the signal handler so exceptions in 16-bit
* code crash badly.
* - Solaris inserts a libc trampoline to call our handler, but the trampoline expects that registers
* are setup correctly. So we need to insert our own trampoline below the libc trampoline to set %gs.
*/
extern
int
sigaction_syscall
(
int
sig
,
const
struct
sigaction
*
new
,
struct
sigaction
*
old
);
__ASM_GLOBAL_FUNC
(
sigaction_syscall
,
"movl $0x62,%eax
\n\t
"
"int $0x91
\n\t
"
"ret"
)
/* assume the same libc handler is used for all signals */
static
void
(
*
libc_sigacthandler
)(
int
signal
,
siginfo_t
*
siginfo
,
void
*
context
);
static
void
wine_sigacthandler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
x86_thread_data
*
thread_data
;
__asm__
__volatile__
(
"mov %ss,%ax; mov %ax,%ds; mov %ax,%es"
);
thread_data
=
(
struct
x86_thread_data
*
)
get_current_teb
()
->
SystemReserved2
;
set_fs
(
thread_data
->
fs
);
set_gs
(
thread_data
->
gs
);
libc_sigacthandler
(
signal
,
siginfo
,
sigcontext
);
}
static
int
solaris_sigaction
(
int
sig
,
const
struct
sigaction
*
new
,
struct
sigaction
*
old
)
{
struct
sigaction
real_act
;
if
(
sigaction
(
sig
,
new
,
old
)
==
-
1
)
return
-
1
;
/* retrieve the real handler and flags with a direct syscall */
sigaction_syscall
(
sig
,
NULL
,
&
real_act
);
libc_sigacthandler
=
real_act
.
sa_sigaction
;
real_act
.
sa_sigaction
=
wine_sigacthandler
;
sigaction_syscall
(
sig
,
&
real_act
,
NULL
);
return
0
;
}
#define sigaction(sig,new,old) solaris_sigaction(sig,new,old)
#endif
extern
void
clear_alignment_flag
(
void
);
__ASM_GLOBAL_FUNC
(
clear_alignment_flag
,
"pushfl
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"andl $~0x40000,(%esp)
\n\t
"
"popfl
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset -4
\n\t
"
)
"ret"
)
/***********************************************************************
* init_handler
*
* Handler initialization when the full context is not needed.
* Return the stack pointer to use for pushing the exception data.
*/
static
inline
void
*
init_handler
(
const
ucontext_t
*
sigcontext
,
WORD
*
fs
,
WORD
*
gs
)
{
TEB
*
teb
=
get_current_teb
();
clear_alignment_flag
();
/* get %fs and %gs at time of the fault */
#ifdef FS_sig
*
fs
=
LOWORD
(
FS_sig
(
sigcontext
));
#else
*
fs
=
get_fs
();
#endif
#ifdef GS_sig
*
gs
=
LOWORD
(
GS_sig
(
sigcontext
));
#else
*
gs
=
get_gs
();
#endif
#ifndef __sun
/* see above for Solaris handling */
{
struct
x86_thread_data
*
thread_data
=
(
struct
x86_thread_data
*
)
teb
->
SystemReserved2
;
set_fs
(
thread_data
->
fs
);
set_gs
(
thread_data
->
gs
);
}
#endif
if
(
!
ldt_is_system
(
CS_sig
(
sigcontext
))
||
!
ldt_is_system
(
SS_sig
(
sigcontext
)))
/* 16-bit mode */
{
/*
* Win16 or DOS protected mode. Note that during switch
* from 16-bit mode to linear mode, CS may be set to system
* segment before FS is restored. Fortunately, in this case
* SS is still non-system segment. This is why both CS and SS
* are checked.
*/
return
teb
->
WOW32Reserved
;
}
return
(
void
*
)(
ESP_sig
(
sigcontext
)
&
~
3
);
}
/***********************************************************************
* save_fpu
*
...
...
@@ -911,165 +313,6 @@ static inline void save_fpux( CONTEXT *context )
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
const
CONTEXT
*
context
)
{
FLOATING_SAVE_AREA
float_status
=
context
->
FloatSave
;
/* reset the current interrupt status */
float_status
.
StatusWord
&=
float_status
.
ControlWord
|
0xffffff80
;
#ifdef __GNUC__
__asm__
__volatile__
(
"frstor %0; fwait"
:
:
"m"
(
float_status
)
);
#endif
/* __GNUC__ */
}
/***********************************************************************
* fpux_to_fpu
*
* Build a standard FPU context from an extended one.
*/
static
void
fpux_to_fpu
(
FLOATING_SAVE_AREA
*
fpu
,
const
XMM_SAVE_AREA32
*
fpux
)
{
unsigned
int
i
,
tag
,
stack_top
;
fpu
->
ControlWord
=
fpux
->
ControlWord
|
0xffff0000
;
fpu
->
StatusWord
=
fpux
->
StatusWord
|
0xffff0000
;
fpu
->
ErrorOffset
=
fpux
->
ErrorOffset
;
fpu
->
ErrorSelector
=
fpux
->
ErrorSelector
|
(
fpux
->
ErrorOpcode
<<
16
);
fpu
->
DataOffset
=
fpux
->
DataOffset
;
fpu
->
DataSelector
=
fpux
->
DataSelector
;
fpu
->
Cr0NpxState
=
fpux
->
StatusWord
|
0xffff0000
;
stack_top
=
(
fpux
->
StatusWord
>>
11
)
&
7
;
fpu
->
TagWord
=
0xffff0000
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
memcpy
(
&
fpu
->
RegisterArea
[
10
*
i
],
&
fpux
->
FloatRegisters
[
i
],
10
);
if
(
!
(
fpux
->
TagWord
&
(
1
<<
i
)))
tag
=
3
;
/* empty */
else
{
const
M128A
*
reg
=
&
fpux
->
FloatRegisters
[(
i
-
stack_top
)
&
7
];
if
((
reg
->
High
&
0x7fff
)
==
0x7fff
)
/* exponent all ones */
{
tag
=
2
;
/* special */
}
else
if
(
!
(
reg
->
High
&
0x7fff
))
/* exponent all zeroes */
{
if
(
reg
->
Low
)
tag
=
2
;
/* special */
else
tag
=
1
;
/* zero */
}
else
{
if
(
reg
->
Low
>>
63
)
tag
=
0
;
/* valid */
else
tag
=
2
;
/* special */
}
}
fpu
->
TagWord
|=
tag
<<
(
2
*
i
);
}
}
/***********************************************************************
* save_context
*
* Build a context structure from the signal info.
*/
static
inline
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
,
WORD
fs
,
WORD
gs
)
{
FLOATING_SAVE_AREA
*
fpu
=
FPU_sig
(
sigcontext
);
XMM_SAVE_AREA32
*
fpux
=
FPUX_sig
(
sigcontext
);
memset
(
context
,
0
,
sizeof
(
*
context
));
context
->
ContextFlags
=
CONTEXT_FULL
|
CONTEXT_DEBUG_REGISTERS
;
context
->
Eax
=
EAX_sig
(
sigcontext
);
context
->
Ebx
=
EBX_sig
(
sigcontext
);
context
->
Ecx
=
ECX_sig
(
sigcontext
);
context
->
Edx
=
EDX_sig
(
sigcontext
);
context
->
Esi
=
ESI_sig
(
sigcontext
);
context
->
Edi
=
EDI_sig
(
sigcontext
);
context
->
Ebp
=
EBP_sig
(
sigcontext
);
context
->
EFlags
=
EFL_sig
(
sigcontext
);
context
->
Eip
=
EIP_sig
(
sigcontext
);
context
->
Esp
=
ESP_sig
(
sigcontext
);
context
->
SegCs
=
LOWORD
(
CS_sig
(
sigcontext
));
context
->
SegDs
=
LOWORD
(
DS_sig
(
sigcontext
));
context
->
SegEs
=
LOWORD
(
ES_sig
(
sigcontext
));
context
->
SegFs
=
fs
;
context
->
SegGs
=
gs
;
context
->
SegSs
=
LOWORD
(
SS_sig
(
sigcontext
));
context
->
Dr0
=
x86_thread_data
()
->
dr0
;
context
->
Dr1
=
x86_thread_data
()
->
dr1
;
context
->
Dr2
=
x86_thread_data
()
->
dr2
;
context
->
Dr3
=
x86_thread_data
()
->
dr3
;
context
->
Dr6
=
x86_thread_data
()
->
dr6
;
context
->
Dr7
=
x86_thread_data
()
->
dr7
;
if
(
fpu
)
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
FloatSave
=
*
fpu
;
}
if
(
fpux
)
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
|
CONTEXT_EXTENDED_REGISTERS
;
memcpy
(
context
->
ExtendedRegisters
,
fpux
,
sizeof
(
*
fpux
)
);
if
(
!
fpu
)
fpux_to_fpu
(
&
context
->
FloatSave
,
fpux
);
}
if
(
!
fpu
&&
!
fpux
)
save_fpu
(
context
);
}
/***********************************************************************
* restore_context
*
* Restore the signal info from the context.
*/
static
inline
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
FLOATING_SAVE_AREA
*
fpu
=
FPU_sig
(
sigcontext
);
XMM_SAVE_AREA32
*
fpux
=
FPUX_sig
(
sigcontext
);
x86_thread_data
()
->
dr0
=
context
->
Dr0
;
x86_thread_data
()
->
dr1
=
context
->
Dr1
;
x86_thread_data
()
->
dr2
=
context
->
Dr2
;
x86_thread_data
()
->
dr3
=
context
->
Dr3
;
x86_thread_data
()
->
dr6
=
context
->
Dr6
;
x86_thread_data
()
->
dr7
=
context
->
Dr7
;
EAX_sig
(
sigcontext
)
=
context
->
Eax
;
EBX_sig
(
sigcontext
)
=
context
->
Ebx
;
ECX_sig
(
sigcontext
)
=
context
->
Ecx
;
EDX_sig
(
sigcontext
)
=
context
->
Edx
;
ESI_sig
(
sigcontext
)
=
context
->
Esi
;
EDI_sig
(
sigcontext
)
=
context
->
Edi
;
EBP_sig
(
sigcontext
)
=
context
->
Ebp
;
EFL_sig
(
sigcontext
)
=
context
->
EFlags
;
EIP_sig
(
sigcontext
)
=
context
->
Eip
;
ESP_sig
(
sigcontext
)
=
context
->
Esp
;
CS_sig
(
sigcontext
)
=
context
->
SegCs
;
DS_sig
(
sigcontext
)
=
context
->
SegDs
;
ES_sig
(
sigcontext
)
=
context
->
SegEs
;
SS_sig
(
sigcontext
)
=
context
->
SegSs
;
#ifdef GS_sig
GS_sig
(
sigcontext
)
=
context
->
SegGs
;
#else
set_gs
(
context
->
SegGs
);
#endif
#ifdef FS_sig
FS_sig
(
sigcontext
)
=
context
->
SegFs
;
#else
set_fs
(
context
->
SegFs
);
#endif
if
(
fpu
)
*
fpu
=
context
->
FloatSave
;
if
(
fpux
)
memcpy
(
fpux
,
context
->
ExtendedRegisters
,
sizeof
(
*
fpux
)
);
if
(
!
fpu
&&
!
fpux
)
restore_fpu
(
context
);
}
/***********************************************************************
* RtlCaptureContext (NTDLL.@)
*/
__ASM_STDCALL_FUNC
(
RtlCaptureContext
,
4
,
...
...
@@ -1152,738 +395,6 @@ __ASM_STDCALL_FUNC( NtGetContextThread, 8,
"ret $8"
)
/***********************************************************************
* is_privileged_instr
*
* Check if the fault location is a privileged instruction.
* Based on the instruction emulation code in dlls/kernel/instr.c.
*/
static
inline
DWORD
is_privileged_instr
(
CONTEXT
*
context
)
{
BYTE
instr
[
16
];
unsigned
int
i
,
len
,
prefix_count
=
0
;
if
(
!
ldt_is_system
(
context
->
SegCs
))
return
0
;
len
=
unix_funcs
->
virtual_uninterrupted_read_memory
(
(
BYTE
*
)
context
->
Eip
,
instr
,
sizeof
(
instr
)
);
for
(
i
=
0
;
i
<
len
;
i
++
)
switch
(
instr
[
i
])
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x64
:
/* %fs: */
case
0x65
:
/* %gs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
EXCEPTION_ILLEGAL_INSTRUCTION
;
continue
;
case
0x0f
:
/* extended instruction */
if
(
i
==
len
-
1
)
return
0
;
switch
(
instr
[
i
+
1
])
{
case
0x20
:
/* mov crX, reg */
case
0x21
:
/* mov drX, reg */
case
0x22
:
/* mov reg, crX */
case
0x23
:
/* mov reg drX */
return
EXCEPTION_PRIV_INSTRUCTION
;
}
return
0
;
case
0x6c
:
/* insb (%dx) */
case
0x6d
:
/* insl (%dx) */
case
0x6e
:
/* outsb (%dx) */
case
0x6f
:
/* outsl (%dx) */
case
0xcd
:
/* int $xx */
case
0xe4
:
/* inb al,XX */
case
0xe5
:
/* in (e)ax,XX */
case
0xe6
:
/* outb XX,al */
case
0xe7
:
/* out XX,(e)ax */
case
0xec
:
/* inb (%dx),%al */
case
0xed
:
/* inl (%dx),%eax */
case
0xee
:
/* outb %al,(%dx) */
case
0xef
:
/* outl %eax,(%dx) */
case
0xf4
:
/* hlt */
case
0xfa
:
/* cli */
case
0xfb
:
/* sti */
return
EXCEPTION_PRIV_INSTRUCTION
;
default
:
return
0
;
}
return
0
;
}
/***********************************************************************
* check_invalid_gs
*
* Check for fault caused by invalid %gs value (some copy protection schemes mess with it).
*/
static
inline
BOOL
check_invalid_gs
(
ucontext_t
*
sigcontext
,
CONTEXT
*
context
)
{
unsigned
int
prefix_count
=
0
;
const
BYTE
*
instr
=
(
BYTE
*
)
context
->
Eip
;
WORD
system_gs
=
x86_thread_data
()
->
gs
;
if
(
context
->
SegGs
==
system_gs
)
return
FALSE
;
if
(
!
ldt_is_system
(
context
->
SegCs
))
return
FALSE
;
/* only handle faults in system libraries */
if
(
unix_funcs
->
virtual_is_valid_code_address
(
instr
,
1
))
return
FALSE
;
for
(;;)
switch
(
*
instr
)
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x64
:
/* %fs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
FALSE
;
instr
++
;
continue
;
case
0x65
:
/* %gs: */
TRACE
(
"%04x/%04x at %p, fixing up
\n
"
,
context
->
SegGs
,
system_gs
,
instr
);
#ifdef GS_sig
GS_sig
(
sigcontext
)
=
system_gs
;
#endif
return
TRUE
;
default
:
return
FALSE
;
}
}
#include "pshpack1.h"
union
atl_thunk
{
struct
{
DWORD
movl
;
/* movl this,4(%esp) */
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t1
;
struct
{
BYTE
movl
;
/* movl this,ecx */
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t2
;
struct
{
BYTE
movl1
;
/* movl this,edx */
DWORD
this
;
BYTE
movl2
;
/* movl func,ecx */
DWORD
func
;
WORD
jmp
;
/* jmp ecx */
}
t3
;
struct
{
BYTE
movl1
;
/* movl this,ecx */
DWORD
this
;
BYTE
movl2
;
/* movl func,eax */
DWORD
func
;
WORD
jmp
;
/* jmp eax */
}
t4
;
struct
{
DWORD
inst1
;
/* pop ecx
* pop eax
* push ecx
* jmp 4(%eax) */
WORD
inst2
;
}
t5
;
};
#include "poppack.h"
/**********************************************************************
* check_atl_thunk
*
* Check if code destination is an ATL thunk, and emulate it if so.
*/
static
BOOL
check_atl_thunk
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
const
union
atl_thunk
*
thunk
=
(
const
union
atl_thunk
*
)
stack
->
rec
.
ExceptionInformation
[
1
];
union
atl_thunk
thunk_copy
;
SIZE_T
thunk_len
;
thunk_len
=
unix_funcs
->
virtual_uninterrupted_read_memory
(
thunk
,
&
thunk_copy
,
sizeof
(
*
thunk
)
);
if
(
!
thunk_len
)
return
FALSE
;
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t1
)
&&
thunk_copy
.
t1
.
movl
==
0x042444c7
&&
thunk_copy
.
t1
.
jmp
==
0xe9
)
{
if
(
!
unix_funcs
->
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
+
1
,
&
thunk_copy
.
t1
.
this
,
sizeof
(
DWORD
)
))
{
EIP_sig
(
sigcontext
)
=
(
DWORD_PTR
)(
&
thunk
->
t1
.
func
+
1
)
+
thunk_copy
.
t1
.
func
;
TRACE
(
"emulating ATL thunk type 1 at %p, func=%08x arg=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
thunk_copy
.
t1
.
this
);
return
TRUE
;
}
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t2
)
&&
thunk_copy
.
t2
.
movl
==
0xb9
&&
thunk_copy
.
t2
.
jmp
==
0xe9
)
{
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t2
.
this
;
EIP_sig
(
sigcontext
)
=
(
DWORD_PTR
)(
&
thunk
->
t2
.
func
+
1
)
+
thunk_copy
.
t2
.
func
;
TRACE
(
"emulating ATL thunk type 2 at %p, func=%08x ecx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
ECX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t3
)
&&
thunk_copy
.
t3
.
movl1
==
0xba
&&
thunk_copy
.
t3
.
movl2
==
0xb9
&&
thunk_copy
.
t3
.
jmp
==
0xe1ff
)
{
EDX_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
this
;
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
func
;
EIP_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
func
;
TRACE
(
"emulating ATL thunk type 3 at %p, func=%08x ecx=%08x edx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
ECX_sig
(
sigcontext
),
EDX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t4
)
&&
thunk_copy
.
t4
.
movl1
==
0xb9
&&
thunk_copy
.
t4
.
movl2
==
0xb8
&&
thunk_copy
.
t4
.
jmp
==
0xe0ff
)
{
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
this
;
EAX_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
func
;
EIP_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
func
;
TRACE
(
"emulating ATL thunk type 4 at %p, func=%08x eax=%08x ecx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
EAX_sig
(
sigcontext
),
ECX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t5
)
&&
thunk_copy
.
t5
.
inst1
==
0xff515859
&&
thunk_copy
.
t5
.
inst2
==
0x0460
)
{
DWORD
func
,
sp
[
2
];
if
(
unix_funcs
->
virtual_uninterrupted_read_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
,
sp
,
sizeof
(
sp
)
)
==
sizeof
(
sp
)
&&
unix_funcs
->
virtual_uninterrupted_read_memory
(
(
DWORD
*
)
sp
[
1
]
+
1
,
&
func
,
sizeof
(
DWORD
)
)
==
sizeof
(
DWORD
)
&&
!
unix_funcs
->
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
+
1
,
&
sp
[
0
],
sizeof
(
sp
[
0
])
))
{
ECX_sig
(
sigcontext
)
=
sp
[
0
];
EAX_sig
(
sigcontext
)
=
sp
[
1
];
ESP_sig
(
sigcontext
)
+=
sizeof
(
DWORD
);
EIP_sig
(
sigcontext
)
=
func
;
TRACE
(
"emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08x esp=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
EAX_sig
(
sigcontext
),
ECX_sig
(
sigcontext
),
ESP_sig
(
sigcontext
)
);
return
TRUE
;
}
}
return
FALSE
;
}
/***********************************************************************
* setup_exception_record
*
* Setup the exception record and context on the thread stack.
*/
static
struct
stack_layout
*
setup_exception_record
(
ucontext_t
*
sigcontext
,
void
*
stack_ptr
,
WORD
fs
,
WORD
gs
)
{
struct
stack_layout
*
stack
=
stack_ptr
;
DWORD
exception_code
=
0
;
/* stack sanity checks */
if
((
char
*
)
stack
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
stack
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
)
{
WINE_ERR
(
"nested exception on signal stack in thread %04x eip %08x esp %08x stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
if
(
stack
-
1
>
stack
||
/* check for overflow in subtraction */
(
char
*
)
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
(
char
*
)
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
{
WARN
(
"exception outside of stack limits in thread %04x eip %08x esp %08x stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
(
char
*
)(
stack
-
1
);
WINE_ERR
(
"stack overflow %u bytes in thread %04x eip %08x esp %08x stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
)
{
/* stack access below stack limit, may be recoverable */
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
stack
-
1
))
{
case
0
:
/* not handled */
{
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
-
(
char
*
)(
stack
-
1
);
WINE_ERR
(
"stack overflow %u bytes in thread %04x eip %08x esp %08x stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
case
-
1
:
/* overflow */
exception_code
=
EXCEPTION_STACK_OVERFLOW
;
break
;
}
}
stack
--
;
/* push the stack_layout structure */
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED
(
stack
,
sizeof
(
*
stack
));
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE
(
stack
,
sizeof
(
*
stack
));
#endif
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
EIP_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
,
fs
,
gs
);
return
stack
;
}
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
WORD
fs
,
gs
;
void
*
stack
=
init_handler
(
sigcontext
,
&
fs
,
&
gs
);
return
setup_exception_record
(
sigcontext
,
stack
,
fs
,
gs
);
}
/***********************************************************************
* setup_raise_exception
*
* Change context to setup a call to a raise exception function.
*/
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
NTSTATUS
status
=
send_debug_event
(
&
stack
->
rec
,
TRUE
,
&
stack
->
context
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
ESP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
EIP_sig
(
sigcontext
)
=
(
DWORD
)
KiUserExceptionDispatcher
;
/* clear single-step, direction, and align check flag */
EFL_sig
(
sigcontext
)
&=
~
(
0x100
|
0x400
|
0x40000
);
CS_sig
(
sigcontext
)
=
get_cs
();
DS_sig
(
sigcontext
)
=
get_ds
();
ES_sig
(
sigcontext
)
=
get_ds
();
FS_sig
(
sigcontext
)
=
get_fs
();
GS_sig
(
sigcontext
)
=
get_gs
();
SS_sig
(
sigcontext
)
=
get_ds
();
stack
->
ret_addr
=
(
void
*
)
0xdeadbabe
;
/* KiUserExceptionDispatcher must not return */
stack
->
rec_ptr
=
&
stack
->
rec
;
/* arguments for KiUserExceptionDispatcher */
stack
->
context_ptr
=
&
stack
->
context
;
}
/**********************************************************************
* get_fpu_code
*
* Get the FPU exception code from the FPU status.
*/
static
inline
DWORD
get_fpu_code
(
const
CONTEXT
*
context
)
{
DWORD
status
=
context
->
FloatSave
.
StatusWord
&
~
(
context
->
FloatSave
.
ControlWord
&
0x3f
);
if
(
status
&
0x01
)
/* IE */
{
if
(
status
&
0x40
)
/* SF */
return
EXCEPTION_FLT_STACK_CHECK
;
else
return
EXCEPTION_FLT_INVALID_OPERATION
;
}
if
(
status
&
0x02
)
return
EXCEPTION_FLT_DENORMAL_OPERAND
;
/* DE flag */
if
(
status
&
0x04
)
return
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
/* ZE flag */
if
(
status
&
0x08
)
return
EXCEPTION_FLT_OVERFLOW
;
/* OE flag */
if
(
status
&
0x10
)
return
EXCEPTION_FLT_UNDERFLOW
;
/* UE flag */
if
(
status
&
0x20
)
return
EXCEPTION_FLT_INEXACT_RESULT
;
/* PE flag */
return
EXCEPTION_FLT_INVALID_OPERATION
;
/* generic error */
}
/***********************************************************************
* handle_interrupt
*
* Handle an interrupt.
*/
static
BOOL
handle_interrupt
(
unsigned
int
interrupt
,
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
switch
(
interrupt
)
{
case
0x2d
:
if
(
!
is_wow64
)
{
/* On Wow64, the upper DWORD of Rax contains garbage, and the debug
* service is usually not recognized when called from usermode. */
switch
(
stack
->
context
.
Eax
)
{
case
1
:
/* BREAKPOINT_PRINT */
case
3
:
/* BREAKPOINT_LOAD_SYMBOLS */
case
4
:
/* BREAKPOINT_UNLOAD_SYMBOLS */
case
5
:
/* BREAKPOINT_COMMAND_STRING (>= Win2003) */
EIP_sig
(
sigcontext
)
+=
3
;
return
TRUE
;
}
}
stack
->
context
.
Eip
+=
3
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
stack
->
context
.
Eip
;
stack
->
rec
.
NumberParameters
=
is_wow64
?
1
:
3
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
stack
->
context
.
Eax
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
stack
->
context
.
Ecx
;
stack
->
rec
.
ExceptionInformation
[
2
]
=
stack
->
context
.
Edx
;
setup_raise_exception
(
sigcontext
,
stack
);
return
TRUE
;
default:
return
FALSE
;
}
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
WORD
fs
,
gs
;
struct
stack_layout
*
stack
;
ucontext_t
*
context
=
sigcontext
;
void
*
stack_ptr
=
init_handler
(
sigcontext
,
&
fs
,
&
gs
);
/* check for exceptions on the signal stack caused by write watches */
if
(
get_trap_code
(
context
)
==
TRAP_x86_PAGEFLT
&&
(
char
*
)
stack_ptr
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
stack_ptr
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
&&
!
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
(
get_error_code
(
context
)
>>
1
)
&
0x09
,
TRUE
))
{
return
;
}
/* check for page fault inside the thread stack */
if
(
get_trap_code
(
context
)
==
TRAP_x86_PAGEFLT
)
{
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
siginfo
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception_record
(
context
,
stack_ptr
,
fs
,
gs
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception_record
(
context
,
stack_ptr
,
fs
,
gs
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
get_trap_code
(
context
))
{
case
TRAP_x86_OFLOW
:
/* Overflow exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
TRAP_x86_BOUND
:
/* Bound range exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
TRAP_x86_PRIVINFLT
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_x86_STKFLT
:
/* Stack fault */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
case
TRAP_x86_SEGNPFLT
:
/* Segment not present exception */
case
TRAP_x86_PROTFLT
:
/* General protection fault */
case
TRAP_x86_UNKNOWN
:
/* Unknown fault code */
{
WORD
err
=
get_error_code
(
context
);
if
(
!
err
&&
(
stack
->
rec
.
ExceptionCode
=
is_privileged_instr
(
&
stack
->
context
)))
break
;
if
((
err
&
7
)
==
2
&&
handle_interrupt
(
err
>>
3
,
context
,
stack
))
return
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
/* if error contains a LDT selector, use that as fault address */
if
((
err
&
7
)
==
4
&&
!
ldt_is_system
(
err
|
7
))
stack
->
rec
.
ExceptionInformation
[
1
]
=
err
&
~
7
;
else
{
stack
->
rec
.
ExceptionInformation
[
1
]
=
0xffffffff
;
if
(
check_invalid_gs
(
context
,
&
stack
->
context
))
return
;
}
}
break
;
case
TRAP_x86_PAGEFLT
:
/* Page fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
get_error_code
(
context
)
>>
1
)
&
0x09
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
stack
->
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
(
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
);
if
(
!
stack
->
rec
.
ExceptionCode
)
return
;
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_ACCESS_VIOLATION
&&
stack
->
rec
.
ExceptionInformation
[
0
]
==
EXCEPTION_EXECUTE_FAULT
)
{
ULONG
flags
;
NtQueryInformationProcess
(
GetCurrentProcess
(),
ProcessExecuteFlags
,
&
flags
,
sizeof
(
flags
),
NULL
);
if
(
!
(
flags
&
MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
&&
check_atl_thunk
(
context
,
stack
))
return
;
/* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
if
(
!
(
flags
&
MEM_EXECUTE_OPTION_DISABLE
))
stack
->
rec
.
ExceptionInformation
[
0
]
=
EXCEPTION_READ_FAULT
;
}
break
;
case
TRAP_x86_ALIGNFLT
:
/* Alignment check exception */
/* FIXME: pass through exception handler first? */
if
(
stack
->
context
.
EFlags
&
0x00040000
)
{
EFL_sig
(
context
)
&=
~
0x00040000
;
/* disable AC flag */
return
;
}
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default:
WINE_ERR
(
"Got unexpected trap %d
\n
"
,
get_trap_code
(
context
)
);
/* fall through */
case
TRAP_x86_NMI
:
/* NMI interrupt */
case
TRAP_x86_DNA
:
/* Device not available exception */
case
TRAP_x86_DOUBLEFLT
:
/* Double fault exception */
case
TRAP_x86_TSSFLT
:
/* Invalid TSS exception */
case
TRAP_x86_MCHK
:
/* Machine check exception */
case
TRAP_x86_CACHEFLT
:
/* Cache flush exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done:
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
ucontext_t
*
context
=
sigcontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
get_trap_code
(
context
))
{
case
TRAP_x86_TRCTRAP
:
/* Single-step exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
/* when single stepping can't tell whether this is a hw bp or a
* single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */
if
(
!
(
stack
->
context
.
EFlags
&
0x100
)
||
(
stack
->
context
.
Dr7
&
0xff
))
{
/* (possible) hardware breakpoint, fetch the debug registers */
DWORD
saved_flags
=
stack
->
context
.
ContextFlags
;
stack
->
context
.
ContextFlags
=
CONTEXT_DEBUG_REGISTERS
;
NtGetContextThread
(
GetCurrentThread
(),
&
stack
->
context
);
stack
->
context
.
ContextFlags
|=
saved_flags
;
/* restore flags */
}
stack
->
context
.
EFlags
&=
~
0x100
;
/* clear single-step flag */
break
;
case
TRAP_x86_BPTFLT
:
/* Breakpoint exception */
stack
->
rec
.
ExceptionAddress
=
(
char
*
)
stack
->
rec
.
ExceptionAddress
-
1
;
/* back up over the int3 instruction */
/* fall through */
default:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
NumberParameters
=
is_wow64
?
1
:
3
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
0
;
/* FIXME */
stack
->
rec
.
ExceptionInformation
[
2
]
=
0
;
/* FIXME */
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
ucontext_t
*
context
=
sigcontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
get_trap_code
(
context
))
{
case
TRAP_x86_DIVIDE
:
/* Division by zero exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
case
TRAP_x86_FPOPFLT
:
/* Coprocessor segment overrun */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
case
TRAP_x86_ARITHTRAP
:
/* Floating point exception */
case
TRAP_x86_UNKNOWN
:
/* Unknown fault code */
stack
->
rec
.
ExceptionCode
=
get_fpu_code
(
&
stack
->
context
);
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
stack
->
context
.
FloatSave
.
ErrorOffset
;
break
;
case
TRAP_x86_CACHEFLT
:
/* SIMD exception */
/* TODO:
* Behaviour only tested for divide-by-zero exceptions
* Check for other SIMD exceptions as well */
if
(
siginfo
->
si_code
!=
FPE_FLTDIV
&&
siginfo
->
si_code
!=
FPE_FLTINV
)
FIXME
(
"untested SIMD exception: %#x. Might not work correctly
\n
"
,
siginfo
->
si_code
);
stack
->
rec
.
ExceptionCode
=
STATUS_FLOAT_MULTIPLE_TRAPS
;
stack
->
rec
.
NumberParameters
=
1
;
/* no idea what meaning is actually behind this but that's what native does */
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
break
;
default:
WINE_ERR
(
"Got unexpected trap %d
\n
"
,
get_trap_code
(
context
)
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
WORD
fs
,
gs
;
init_handler
(
sigcontext
,
&
fs
,
&
gs
);
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
WORD
fs
,
gs
;
init_handler
(
sigcontext
,
&
fs
,
&
gs
);
save_context
(
&
context
,
sigcontext
,
fs
,
gs
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_SIGINFO
|
SA_RESTART
;
#ifdef SA_ONSTACK
sig_act
.
sa_flags
|=
SA_ONSTACK
;
#endif
#ifdef __ANDROID__
sig_act
.
sa_flags
|=
SA_RESTORER
;
sig_act
.
sa_restorer
=
rt_sigreturn
;
#endif
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#ifdef SIGBUS
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
#ifdef SIGTRAP
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
return
;
error:
perror
(
"sigaction"
);
exit
(
1
);
}
/*******************************************************************
* RtlUnwind (NTDLL.@)
*/
...
...
dlls/ntdll/signal_powerpc.c
View file @
2333099c
...
...
@@ -32,22 +32,6 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# endif
#endif
#ifdef HAVE_SYS_SIGNAL_H
# include <sys/signal.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
...
...
@@ -59,181 +43,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
# define IAR_sig(context) REG_sig(nip, context)
/* Program counter */
# define MSR_sig(context) REG_sig(msr, context)
/* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
/* Count register */
# define XER_sig(context) REG_sig(xer, context)
/* User's integer exception register */
# define LR_sig(context) REG_sig(link, context)
/* Link register */
# define CR_sig(context) REG_sig(ccr, context)
/* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context) REG_sig(dar, context)
# define DSISR_sig(context) REG_sig(dsisr, context)
# define TRAP_sig(context) REG_sig(trap, context)
#endif
/* linux */
#ifdef __APPLE__
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
# define IAR_sig(context) REG_sig(srr0, context)
/* Program counter */
# define MSR_sig(context) REG_sig(srr1, context)
/* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
# define XER_sig(context) REG_sig(xer, context)
/* Link register */
# define LR_sig(context) REG_sig(lr, context)
/* User's integer exception register */
# define CR_sig(context) REG_sig(cr, context)
/* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context) FLOATREG_sig(fpscr, context)
/* Exception Registers access */
# define DAR_sig(context) EXCEPREG_sig(dar, context)
/* Fault registers for coredump */
# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context) EXCEPREG_sig(exception, context)
/* number of powerpc exception taken */
/* Signal defs : Those are undefined on darwin
SIGBUS
#undef BUS_ADRERR
#undef BUS_OBJERR
SIGILL
#undef ILL_ILLOPN
#undef ILL_ILLTRP
#undef ILL_ILLADR
#undef ILL_COPROC
#undef ILL_PRVREG
#undef ILL_BADSTK
SIGTRAP
#undef TRAP_BRKPT
#undef TRAP_TRACE
SIGFPE
*/
#endif
/* __APPLE__ */
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
/* Save Gpr registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
context
->
Iar
=
IAR_sig
(
sigcontext
);
/* Program Counter */
context
->
Msr
=
MSR_sig
(
sigcontext
);
/* Machine State Register (Supervisor) */
context
->
Ctr
=
CTR_sig
(
sigcontext
);
context
->
Xer
=
XER_sig
(
sigcontext
);
context
->
Lr
=
LR_sig
(
sigcontext
);
context
->
Cr
=
CR_sig
(
sigcontext
);
/* Saving Exception regs */
context
->
Dar
=
DAR_sig
(
sigcontext
);
context
->
Dsisr
=
DSISR_sig
(
sigcontext
);
context
->
Trap
=
TRAP_sig
(
sigcontext
);
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
IAR_sig
(
sigcontext
)
=
context
->
Iar
;
/* Program Counter */
MSR_sig
(
sigcontext
)
=
context
->
Msr
;
/* Machine State Register (Supervisor) */
CTR_sig
(
sigcontext
)
=
context
->
Ctr
;
XER_sig
(
sigcontext
)
=
context
->
Xer
;
LR_sig
(
sigcontext
)
=
context
->
Lr
;
CR_sig
(
sigcontext
)
=
context
->
Cr
;
/* Setting Exception regs */
DAR_sig
(
sigcontext
)
=
context
->
Dar
;
DSISR_sig
(
sigcontext
)
=
context
->
Dsisr
;
TRAP_sig
(
sigcontext
)
=
context
->
Trap
;
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
inline
void
save_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
context
->
Fpscr
=
FPSCR_sig
(
sigcontext
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
FPSCR_sig
(
sigcontext
)
=
context
->
Fpscr
;
}
/***********************************************************************
* RtlCaptureContext (NTDLL.@)
...
...
@@ -265,69 +74,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
/*******************************************************************
* raise_exception
*
* Implementation of NtRaiseException.
*/
static
NTSTATUS
raise_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
{
NTSTATUS
status
;
if
(
first_chance
)
{
DWORD
c
;
TRACE
(
"code=%x flags=%x addr=%p ip=%x tid=%04x
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
,
context
->
Iar
,
GetCurrentThreadId
()
);
for
(
c
=
0
;
c
<
rec
->
NumberParameters
;
c
++
)
TRACE
(
" info[%d]=%08lx
\n
"
,
c
,
rec
->
ExceptionInformation
[
c
]
);
if
(
rec
->
ExceptionCode
==
EXCEPTION_WINE_STUB
)
{
if
(
rec
->
ExceptionInformation
[
1
]
>>
16
)
MESSAGE
(
"wine: Call from %p to unimplemented function %s.%s, aborting
\n
"
,
rec
->
ExceptionAddress
,
(
char
*
)
rec
->
ExceptionInformation
[
0
],
(
char
*
)
rec
->
ExceptionInformation
[
1
]
);
else
MESSAGE
(
"wine: Call from %p to unimplemented function %s.%ld, aborting
\n
"
,
rec
->
ExceptionAddress
,
(
char
*
)
rec
->
ExceptionInformation
[
0
],
rec
->
ExceptionInformation
[
1
]
);
}
else
{
/* FIXME: dump context */
}
status
=
send_debug_event
(
rec
,
TRUE
,
context
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
return
STATUS_SUCCESS
;
if
(
call_vectored_handlers
(
rec
,
context
)
==
EXCEPTION_CONTINUE_EXECUTION
)
return
STATUS_SUCCESS
;
if
((
status
=
call_stack_handlers
(
rec
,
context
))
!=
STATUS_UNHANDLED_EXCEPTION
)
return
status
;
}
/* last chance exception */
status
=
send_debug_event
(
rec
,
FALSE
,
context
);
if
(
status
!=
DBG_CONTINUE
)
{
if
(
rec
->
ExceptionFlags
&
EH_STACK_INVALID
)
ERR
(
"Exception frame is not in stack limits => unable to dispatch exception.
\n
"
);
else
if
(
rec
->
ExceptionCode
==
STATUS_NONCONTINUABLE_EXCEPTION
)
ERR
(
"Process attempted to continue execution after noncontinuable exception.
\n
"
);
else
ERR
(
"Unhandled exception code %x flags %x addr %p
\n
"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionAddress
);
NtTerminateProcess
(
NtCurrentProcess
(),
rec
->
ExceptionCode
);
}
return
STATUS_SUCCESS
;
}
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS
WINAPI
KiUserExceptionDispatcher
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
...
...
@@ -368,328 +114,6 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
switch
(
signal
)
{
case
SIGSEGV
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
SEGV_MAPERR
:
case
SEGV_ACCERR
:
rec
.
NumberParameters
=
2
;
rec
.
ExceptionInformation
[
0
]
=
0
;
/* FIXME ? */
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
rec
.
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
break
;
default:
FIXME
(
"Unhandled SIGSEGV/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
case
SIGBUS
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
BUS_ADRALN
:
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
#ifdef BUS_ADRERR
case
BUS_ADRERR
:
#endif
#ifdef BUS_OBJERR
case
BUS_OBJERR
:
/* FIXME: correct for all cases ? */
rec
.
NumberParameters
=
2
;
rec
.
ExceptionInformation
[
0
]
=
0
;
/* FIXME ? */
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
rec
.
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGBUS/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
case
SIGILL
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
ILL_ILLOPC
:
/* illegal opcode */
#ifdef ILL_ILLOPN
case
ILL_ILLOPN
:
/* illegal operand */
#endif
#ifdef ILL_ILLADR
case
ILL_ILLADR
:
/* illegal addressing mode */
#endif
#ifdef ILL_ILLTRP
case
ILL_ILLTRP
:
/* illegal trap */
#endif
#ifdef ILL_COPROC
case
ILL_COPROC
:
/* coprocessor error */
#endif
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
ILL_PRVOPC
:
/* privileged opcode */
#ifdef ILL_PRVREG
case
ILL_PRVREG
:
/* privileged register */
#endif
rec
.
ExceptionCode
=
EXCEPTION_PRIV_INSTRUCTION
;
break
;
#ifdef ILL_BADSTK
case
ILL_BADSTK
:
/* internal stack error */
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGILL/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
}
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
done:
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
/* FIXME: check if we might need to modify PC */
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef TRAP_BRKPT
case
TRAP_BRKPT
:
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
break
;
#endif
#ifdef TRAP_TRACE
case
TRAP_TRACE
:
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGTRAP/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_fpu
(
&
context
,
sigcontext
);
save_context
(
&
context
,
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
restore_fpu
(
&
context
,
sigcontext
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
raise_exception
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
&
rec
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#ifdef SIGBUS
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
#ifdef SIGTRAP
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
return
;
error:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* RtlUnwind (NTDLL.@)
*/
...
...
@@ -704,12 +128,10 @@ void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecor
void
WINAPI
RtlRaiseException
(
EXCEPTION_RECORD
*
rec
)
{
CONTEXT
context
;
NTSTATUS
status
;
RtlCaptureContext
(
&
context
);
rec
->
ExceptionAddress
=
(
void
*
)
context
.
Iar
;
status
=
raise_exception
(
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
rec
);
RtlRaiseStatus
(
NtRaiseException
(
rec
,
&
context
,
TRUE
));
}
/*************************************************************************
...
...
dlls/ntdll/signal_x86_64.c
View file @
2333099c
...
...
@@ -252,46 +252,6 @@ struct MSVCRT_JUMP_BUFFER
#error You must define the signal context functions for your platform
#endif
enum
i386_trap_code
{
TRAP_x86_UNKNOWN
=
-
1
,
/* Unknown fault (TRAP_sig not defined) */
TRAP_x86_DIVIDE
=
0
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
1
,
/* Single-step exception */
TRAP_x86_NMI
=
2
,
/* NMI interrupt */
TRAP_x86_BPTFLT
=
3
,
/* Breakpoint exception */
TRAP_x86_OFLOW
=
4
,
/* Overflow exception */
TRAP_x86_BOUND
=
5
,
/* Bound range exception */
TRAP_x86_PRIVINFLT
=
6
,
/* Invalid opcode exception */
TRAP_x86_DNA
=
7
,
/* Device not available exception */
TRAP_x86_DOUBLEFLT
=
8
,
/* Double fault exception */
TRAP_x86_FPOPFLT
=
9
,
/* Coprocessor segment overrun */
TRAP_x86_TSSFLT
=
10
,
/* Invalid TSS exception */
TRAP_x86_SEGNPFLT
=
11
,
/* Segment not present exception */
TRAP_x86_STKFLT
=
12
,
/* Stack fault */
TRAP_x86_PROTFLT
=
13
,
/* General protection fault */
TRAP_x86_PAGEFLT
=
14
,
/* Page fault */
TRAP_x86_ARITHTRAP
=
16
,
/* Floating point exception */
TRAP_x86_ALIGNFLT
=
17
,
/* Alignment check exception */
TRAP_x86_MCHK
=
18
,
/* Machine check exception */
TRAP_x86_CACHEFLT
=
19
/* Cache flush exception */
};
static
const
size_t
teb_size
=
0x2000
;
/* we reserve two pages for the TEB */
typedef
void
(
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/* stack layout when calling an exception raise function */
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
ULONG64
rsi
;
ULONG64
rdi
;
ULONG64
rbp
;
ULONG64
rip
;
ULONG64
red_zone
[
16
];
};
struct
amd64_thread_data
{
DWORD_PTR
dr0
;
/* debug registers */
...
...
@@ -311,40 +271,6 @@ static inline struct amd64_thread_data *amd64_thread_data(void)
return
(
struct
amd64_thread_data
*
)
NtCurrentTeb
()
->
SystemReserved2
;
}
static
inline
void
set_sigcontext
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
RAX_sig
(
sigcontext
)
=
context
->
Rax
;
RCX_sig
(
sigcontext
)
=
context
->
Rcx
;
RDX_sig
(
sigcontext
)
=
context
->
Rdx
;
RBX_sig
(
sigcontext
)
=
context
->
Rbx
;
RSP_sig
(
sigcontext
)
=
context
->
Rsp
;
RBP_sig
(
sigcontext
)
=
context
->
Rbp
;
RSI_sig
(
sigcontext
)
=
context
->
Rsi
;
RDI_sig
(
sigcontext
)
=
context
->
Rdi
;
R8_sig
(
sigcontext
)
=
context
->
R8
;
R9_sig
(
sigcontext
)
=
context
->
R9
;
R10_sig
(
sigcontext
)
=
context
->
R10
;
R11_sig
(
sigcontext
)
=
context
->
R11
;
R12_sig
(
sigcontext
)
=
context
->
R12
;
R13_sig
(
sigcontext
)
=
context
->
R13
;
R14_sig
(
sigcontext
)
=
context
->
R14
;
R15_sig
(
sigcontext
)
=
context
->
R15
;
RIP_sig
(
sigcontext
)
=
context
->
Rip
;
CS_sig
(
sigcontext
)
=
context
->
SegCs
;
FS_sig
(
sigcontext
)
=
context
->
SegFs
;
GS_sig
(
sigcontext
)
=
context
->
SegGs
;
EFL_sig
(
sigcontext
)
=
context
->
EFlags
;
#ifdef DS_sig
DS_sig
(
sigcontext
)
=
context
->
SegDs
;
#endif
#ifdef ES_sig
ES_sig
(
sigcontext
)
=
context
->
SegEs
;
#endif
#ifdef SS_sig
SS_sig
(
sigcontext
)
=
context
->
SegSs
;
#endif
}
/***********************************************************************
* Definitions for Win32 unwind tables
...
...
@@ -1489,7 +1415,27 @@ static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, BOOL* got_info, ULONG64 *f
unw_set_reg
(
&
cursor
,
UNW_X86_64_R15
,
context
->
R15
);
}
#else
set_sigcontext
(
context
,
&
unw_context
);
RAX_sig
(
&
unw_context
)
=
context
->
Rax
;
RCX_sig
(
&
unw_context
)
=
context
->
Rcx
;
RDX_sig
(
&
unw_context
)
=
context
->
Rdx
;
RBX_sig
(
&
unw_context
)
=
context
->
Rbx
;
RSP_sig
(
&
unw_context
)
=
context
->
Rsp
;
RBP_sig
(
&
unw_context
)
=
context
->
Rbp
;
RSI_sig
(
&
unw_context
)
=
context
->
Rsi
;
RDI_sig
(
&
unw_context
)
=
context
->
Rdi
;
R8_sig
(
&
unw_context
)
=
context
->
R8
;
R9_sig
(
&
unw_context
)
=
context
->
R9
;
R10_sig
(
&
unw_context
)
=
context
->
R10
;
R11_sig
(
&
unw_context
)
=
context
->
R11
;
R12_sig
(
&
unw_context
)
=
context
->
R12
;
R13_sig
(
&
unw_context
)
=
context
->
R13
;
R14_sig
(
&
unw_context
)
=
context
->
R14
;
R15_sig
(
&
unw_context
)
=
context
->
R15
;
RIP_sig
(
&
unw_context
)
=
context
->
Rip
;
CS_sig
(
&
unw_context
)
=
context
->
SegCs
;
FS_sig
(
&
unw_context
)
=
context
->
SegFs
;
GS_sig
(
&
unw_context
)
=
context
->
SegGs
;
EFL_sig
(
&
unw_context
)
=
context
->
EFlags
;
rc
=
unw_init_local
(
&
cursor
,
&
unw_context
);
#endif
if
(
rc
!=
UNW_ESUCCESS
)
...
...
@@ -1630,103 +1576,6 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
return
STATUS_SUCCESS
;
}
/***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
teb_size
;
}
/***********************************************************************
* is_inside_signal_stack
*
* Check if pointer is inside the signal stack.
*/
static
inline
BOOL
is_inside_signal_stack
(
void
*
ptr
)
{
return
((
char
*
)
ptr
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
ptr
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
);
}
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
context
->
ContextFlags
=
CONTEXT_CONTROL
|
CONTEXT_INTEGER
|
CONTEXT_SEGMENTS
|
CONTEXT_DEBUG_REGISTERS
;
context
->
Rax
=
RAX_sig
(
sigcontext
);
context
->
Rcx
=
RCX_sig
(
sigcontext
);
context
->
Rdx
=
RDX_sig
(
sigcontext
);
context
->
Rbx
=
RBX_sig
(
sigcontext
);
context
->
Rsp
=
RSP_sig
(
sigcontext
);
context
->
Rbp
=
RBP_sig
(
sigcontext
);
context
->
Rsi
=
RSI_sig
(
sigcontext
);
context
->
Rdi
=
RDI_sig
(
sigcontext
);
context
->
R8
=
R8_sig
(
sigcontext
);
context
->
R9
=
R9_sig
(
sigcontext
);
context
->
R10
=
R10_sig
(
sigcontext
);
context
->
R11
=
R11_sig
(
sigcontext
);
context
->
R12
=
R12_sig
(
sigcontext
);
context
->
R13
=
R13_sig
(
sigcontext
);
context
->
R14
=
R14_sig
(
sigcontext
);
context
->
R15
=
R15_sig
(
sigcontext
);
context
->
Rip
=
RIP_sig
(
sigcontext
);
context
->
SegCs
=
CS_sig
(
sigcontext
);
context
->
SegFs
=
FS_sig
(
sigcontext
);
context
->
SegGs
=
GS_sig
(
sigcontext
);
context
->
EFlags
=
EFL_sig
(
sigcontext
);
#ifdef DS_sig
context
->
SegDs
=
DS_sig
(
sigcontext
);
#else
__asm__
(
"movw %%ds,%0"
:
"=m"
(
context
->
SegDs
));
#endif
#ifdef ES_sig
context
->
SegEs
=
ES_sig
(
sigcontext
);
#else
__asm__
(
"movw %%es,%0"
:
"=m"
(
context
->
SegEs
));
#endif
#ifdef SS_sig
context
->
SegSs
=
SS_sig
(
sigcontext
);
#else
__asm__
(
"movw %%ss,%0"
:
"=m"
(
context
->
SegSs
));
#endif
context
->
Dr0
=
amd64_thread_data
()
->
dr0
;
context
->
Dr1
=
amd64_thread_data
()
->
dr1
;
context
->
Dr2
=
amd64_thread_data
()
->
dr2
;
context
->
Dr3
=
amd64_thread_data
()
->
dr3
;
context
->
Dr6
=
amd64_thread_data
()
->
dr6
;
context
->
Dr7
=
amd64_thread_data
()
->
dr7
;
if
(
FPU_sig
(
sigcontext
))
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
u
.
FltSave
=
*
FPU_sig
(
sigcontext
);
context
->
MxCsr
=
context
->
u
.
FltSave
.
MxCsr
;
}
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
amd64_thread_data
()
->
dr0
=
context
->
Dr0
;
amd64_thread_data
()
->
dr1
=
context
->
Dr1
;
amd64_thread_data
()
->
dr2
=
context
->
Dr2
;
amd64_thread_data
()
->
dr3
=
context
->
Dr3
;
amd64_thread_data
()
->
dr6
=
context
->
Dr6
;
amd64_thread_data
()
->
dr7
=
context
->
Dr7
;
set_sigcontext
(
context
,
sigcontext
);
if
(
FPU_sig
(
sigcontext
))
*
FPU_sig
(
sigcontext
)
=
context
->
u
.
FltSave
;
}
/**************************************************************************
* __chkstk (NTDLL.@)
...
...
@@ -2261,523 +2110,6 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte
}
extern
void
CDECL
raise_func_trampoline
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline
,
__ASM_CFI
(
".cfi_signal_frame
\n\t
"
)
__ASM_CFI
(
".cfi_def_cfa %rbp,160
\n\t
"
)
/* red zone + rip + rbp + rdi + rsi */
__ASM_CFI
(
".cfi_rel_offset %rip,24
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rbp,16
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rdi,8
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rsi,0
\n\t
"
)
"call *%r8
\n\t
"
"int $3"
)
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
struct
stack_layout
*
stack
;
DWORD
exception_code
=
0
;
stack
=
(
struct
stack_layout
*
)(
RSP_sig
(
sigcontext
)
&
~
15
);
/* stack sanity checks */
if
(
is_inside_signal_stack
(
stack
))
{
ERR
(
"nested exception on signal stack in thread %04x eip %016lx esp %016lx stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
if
(
stack
-
1
>
stack
||
/* check for overflow in subtraction */
(
char
*
)
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
(
char
*
)
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
{
WARN
(
"exception outside of stack limits in thread %04x eip %016lx esp %016lx stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
(
char
*
)(
stack
-
1
);
ERR
(
"stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
)
{
/* stack access below stack limit, may be recoverable */
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
stack
-
1
))
{
case
0
:
/* not handled */
{
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
-
(
char
*
)(
stack
-
1
);
ERR
(
"stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
unix_funcs
->
abort_thread
(
1
);
}
case
-
1
:
/* overflow */
exception_code
=
EXCEPTION_STACK_OVERFLOW
;
break
;
}
}
stack
--
;
/* push the stack_layout structure */
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED
(
stack
,
sizeof
(
*
stack
));
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE
(
stack
,
sizeof
(
*
stack
));
#endif
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
RIP_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
ULONG64
*
rsp_ptr
;
NTSTATUS
status
;
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_SINGLE_STEP
)
{
/* when single stepping can't tell whether this is a hw bp or a
* single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */
if
(
!
(
stack
->
context
.
EFlags
&
0x100
)
||
(
stack
->
context
.
Dr7
&
0xff
))
{
/* (possible) hardware breakpoint, fetch the debug registers */
DWORD
saved_flags
=
stack
->
context
.
ContextFlags
;
stack
->
context
.
ContextFlags
=
CONTEXT_DEBUG_REGISTERS
;
NtGetContextThread
(
GetCurrentThread
(),
&
stack
->
context
);
stack
->
context
.
ContextFlags
|=
saved_flags
;
/* restore flags */
}
stack
->
context
.
EFlags
&=
~
0x100
;
/* clear single-step flag */
}
status
=
send_debug_event
(
&
stack
->
rec
,
TRUE
,
&
stack
->
context
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
/* store return address and %rbp without aligning, so that the offset is fixed */
rsp_ptr
=
(
ULONG64
*
)
RSP_sig
(
sigcontext
)
-
16
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rip
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rbp
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rdi
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rsi
;
/* now modify the sigcontext to return to the raise function */
RIP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
raise_func_trampoline
;
RCX_sig
(
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
rec
;
RDX_sig
(
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
context
;
R8_sig
(
sigcontext
)
=
(
ULONG_PTR
)
KiUserExceptionDispatcher
;
RBP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
rsp_ptr
;
RSP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
stack
;
/* clear single-step, direction, and align check flag */
EFL_sig
(
sigcontext
)
&=
~
(
0x100
|
0x400
|
0x40000
);
}
/***********************************************************************
* is_privileged_instr
*
* Check if the fault location is a privileged instruction.
*/
static
inline
DWORD
is_privileged_instr
(
CONTEXT
*
context
)
{
BYTE
instr
[
16
];
unsigned
int
i
,
prefix_count
=
0
;
unsigned
int
len
=
unix_funcs
->
virtual_uninterrupted_read_memory
(
(
BYTE
*
)
context
->
Rip
,
instr
,
sizeof
(
instr
)
);
for
(
i
=
0
;
i
<
len
;
i
++
)
switch
(
instr
[
i
])
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x40
:
/* rex */
case
0x41
:
/* rex */
case
0x42
:
/* rex */
case
0x43
:
/* rex */
case
0x44
:
/* rex */
case
0x45
:
/* rex */
case
0x46
:
/* rex */
case
0x47
:
/* rex */
case
0x48
:
/* rex */
case
0x49
:
/* rex */
case
0x4a
:
/* rex */
case
0x4b
:
/* rex */
case
0x4c
:
/* rex */
case
0x4d
:
/* rex */
case
0x4e
:
/* rex */
case
0x4f
:
/* rex */
case
0x64
:
/* %fs: */
case
0x65
:
/* %gs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
EXCEPTION_ILLEGAL_INSTRUCTION
;
continue
;
case
0x0f
:
/* extended instruction */
if
(
i
==
len
-
1
)
return
0
;
switch
(
instr
[
i
+
1
])
{
case
0x06
:
/* clts */
case
0x08
:
/* invd */
case
0x09
:
/* wbinvd */
case
0x20
:
/* mov crX, reg */
case
0x21
:
/* mov drX, reg */
case
0x22
:
/* mov reg, crX */
case
0x23
:
/* mov reg drX */
return
EXCEPTION_PRIV_INSTRUCTION
;
}
return
0
;
case
0x6c
:
/* insb (%dx) */
case
0x6d
:
/* insl (%dx) */
case
0x6e
:
/* outsb (%dx) */
case
0x6f
:
/* outsl (%dx) */
case
0xcd
:
/* int $xx */
case
0xe4
:
/* inb al,XX */
case
0xe5
:
/* in (e)ax,XX */
case
0xe6
:
/* outb XX,al */
case
0xe7
:
/* out XX,(e)ax */
case
0xec
:
/* inb (%dx),%al */
case
0xed
:
/* inl (%dx),%eax */
case
0xee
:
/* outb %al,(%dx) */
case
0xef
:
/* outl %eax,(%dx) */
case
0xf4
:
/* hlt */
case
0xfa
:
/* cli */
case
0xfb
:
/* sti */
return
EXCEPTION_PRIV_INSTRUCTION
;
default
:
return
0
;
}
return
0
;
}
/***********************************************************************
* handle_interrupt
*
* Handle an interrupt.
*/
static
inline
BOOL
handle_interrupt
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
switch
(
ERROR_sig
(
sigcontext
)
>>
3
)
{
case
0x2c
:
stack
->
rec
.
ExceptionCode
=
STATUS_ASSERTION_FAILURE
;
break
;
case
0x2d
:
switch
(
stack
->
context
.
Rax
)
{
case
1
:
/* BREAKPOINT_PRINT */
case
3
:
/* BREAKPOINT_LOAD_SYMBOLS */
case
4
:
/* BREAKPOINT_UNLOAD_SYMBOLS */
case
5
:
/* BREAKPOINT_COMMAND_STRING (>= Win2003) */
RIP_sig
(
sigcontext
)
+=
3
;
return
TRUE
;
}
stack
->
context
.
Rip
+=
3
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
stack
->
context
.
Rip
;
stack
->
rec
.
NumberParameters
=
1
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
stack
->
context
.
Rax
;
break
;
default
:
return
FALSE
;
}
setup_raise_exception
(
sigcontext
,
stack
);
return
TRUE
;
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
;
ucontext_t
*
ucontext
=
sigcontext
;
stack
=
(
struct
stack_layout
*
)(
RSP_sig
(
ucontext
)
&
~
15
);
/* check for exceptions on the signal stack caused by write watches */
if
(
TRAP_sig
(
ucontext
)
==
TRAP_x86_PAGEFLT
&&
is_inside_signal_stack
(
stack
)
&&
!
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
(
ERROR_sig
(
ucontext
)
>>
1
)
&
0x09
,
TRUE
))
{
return
;
}
/* check for page fault inside the thread stack */
if
(
TRAP_sig
(
ucontext
)
==
TRAP_x86_PAGEFLT
)
{
switch
(
unix_funcs
->
virtual_handle_stack_fault
(
siginfo
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception
(
sigcontext
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
TRAP_sig
(
ucontext
))
{
case
TRAP_x86_OFLOW
:
/* Overflow exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
TRAP_x86_BOUND
:
/* Bound range exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
TRAP_x86_PRIVINFLT
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_x86_STKFLT
:
/* Stack fault */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
case
TRAP_x86_SEGNPFLT
:
/* Segment not present exception */
case
TRAP_x86_PROTFLT
:
/* General protection fault */
case
TRAP_x86_UNKNOWN
:
/* Unknown fault code */
{
WORD
err
=
ERROR_sig
(
ucontext
);
if
(
!
err
&&
(
stack
->
rec
.
ExceptionCode
=
is_privileged_instr
(
&
stack
->
context
)))
break
;
if
((
err
&
7
)
==
2
&&
handle_interrupt
(
ucontext
,
stack
))
return
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
0xffffffffffffffff
;
}
break
;
case
TRAP_x86_PAGEFLT
:
/* Page fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
ERROR_sig
(
ucontext
)
>>
1
)
&
0x09
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
stack
->
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
((
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
)))
return
;
break
;
case
TRAP_x86_ALIGNFLT
:
/* Alignment check exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default
:
ERR
(
"Got unexpected trap %ld
\n
"
,
(
ULONG_PTR
)
TRAP_sig
(
ucontext
)
);
/* fall through */
case
TRAP_x86_NMI
:
/* NMI interrupt */
case
TRAP_x86_DNA
:
/* Device not available exception */
case
TRAP_x86_DOUBLEFLT
:
/* Double fault exception */
case
TRAP_x86_TSSFLT
:
/* Invalid TSS exception */
case
TRAP_x86_MCHK
:
/* Machine check exception */
case
TRAP_x86_CACHEFLT
:
/* Cache flush exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done
:
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
)
{
case
TRAP_TRACE
:
/* Single-step exception */
case
4
/* TRAP_HWBKPT */
:
/* Hardware breakpoint exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
/* Breakpoint exception */
#ifdef SI_KERNEL
case
SI_KERNEL
:
#endif
/* Check if this is actually icebp instruction */
if
(((
unsigned
char
*
)
stack
->
rec
.
ExceptionAddress
)[
-
1
]
==
0xF1
)
{
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
}
stack
->
rec
.
ExceptionAddress
=
(
char
*
)
stack
->
rec
.
ExceptionAddress
-
1
;
/* back up over the int3 instruction */
/* fall through */
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
NumberParameters
=
1
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
)
{
case
FPE_FLTSUB
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
FPE_INTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
case
FPE_INTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
FPE_FLTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
case
FPE_FLTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
case
FPE_FLTUND
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
case
FPE_FLTRES
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
case
FPE_FLTINV
:
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
ucontext
)
{
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
ucontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
ucontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
ucontext
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
|
SA_ONSTACK
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#ifdef SIGBUS
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
#ifdef SIGTRAP
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
#endif
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
static
ULONG64
get_int_reg
(
CONTEXT
*
context
,
int
reg
)
{
return
*
(
&
context
->
Rax
+
reg
);
...
...
@@ -3325,14 +2657,6 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
unwind_done
:
if
(
!
dispatch
.
EstablisherFrame
)
break
;
if
(
is_inside_signal_stack
(
(
void
*
)
dispatch
.
EstablisherFrame
))
{
TRACE
(
"frame %lx is inside signal stack (%p-%p)
\n
"
,
dispatch
.
EstablisherFrame
,
get_signal_stack
(),
(
char
*
)
get_signal_stack
()
+
signal_stack_size
);
*
context
=
new_context
;
continue
;
}
if
((
dispatch
.
EstablisherFrame
&
7
)
||
dispatch
.
EstablisherFrame
<
(
ULONG64
)
NtCurrentTeb
()
->
Tib
.
StackLimit
||
dispatch
.
EstablisherFrame
>
(
ULONG64
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
...
...
dlls/ntdll/thread.c
View file @
2333099c
...
...
@@ -39,7 +39,6 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "winternl.h"
#include "wine/library.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
...
...
@@ -51,8 +50,6 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
struct
_KUSER_SHARED_DATA
*
user_shared_data
=
(
void
*
)
0x7ffe0000
;
void
(
WINAPI
*
kernel32_start_process
)(
LPTHREAD_START_ROUTINE
,
void
*
)
=
NULL
;
static
PEB
*
peb
;
static
PEB_LDR_DATA
ldr
;
static
RTL_BITMAP
tls_bitmap
;
...
...
@@ -183,11 +180,7 @@ int __cdecl __wine_dbg_output( const char *str )
*/
TEB
*
thread_init
(
SIZE_T
*
info_size
,
BOOL
*
suspend
)
{
TEB
*
teb
;
virtual_init
();
teb
=
unix_funcs
->
init_threading
(
&
nb_threads
,
&
__wine_ldt_copy
,
info_size
,
suspend
,
&
server_cpus
,
TEB
*
teb
=
unix_funcs
->
init_threading
(
&
nb_threads
,
&
__wine_ldt_copy
,
info_size
,
suspend
,
&
server_cpus
,
&
is_wow64
,
&
server_start_time
);
peb
=
teb
->
Peb
;
...
...
@@ -222,7 +215,6 @@ TEB *thread_init( SIZE_T *info_size, BOOL *suspend )
unix_funcs
->
get_paths
(
&
build_dir
,
&
data_dir
,
&
config_dir
);
fill_cpu_info
();
server_init_process
();
return
teb
;
}
...
...
dlls/ntdll/unix/loader.c
View file @
2333099c
...
...
@@ -1052,22 +1052,16 @@ static struct unix_funcs unix_funcs =
virtual_get_system_info
,
virtual_create_builtin_view
,
virtual_alloc_thread_stack
,
virtual_handle_fault
,
virtual_locked_server_call
,
virtual_locked_read
,
virtual_locked_pread
,
virtual_locked_recvmsg
,
virtual_is_valid_code_address
,
virtual_handle_stack_fault
,
virtual_check_buffer_for_read
,
virtual_check_buffer_for_write
,
virtual_uninterrupted_read_memory
,
virtual_uninterrupted_write_memory
,
virtual_set_force_exec
,
virtual_release_address_space
,
virtual_set_large_address_space
,
init_threading
,
start_process
,
abort_thread
,
exit_thread
,
exit_process
,
...
...
dlls/ntdll/unix/server.c
View file @
2333099c
...
...
@@ -1473,11 +1473,42 @@ void server_init_process(void)
/***********************************************************************
* server_init_process_done
*/
void
CDECL
server_init_process_done
(
void
)
void
CDECL
server_init_process_done
(
void
*
relay
)
{
#ifdef __i386__
extern
struct
ldt_copy
__wine_ldt_copy
;
#endif
PEB
*
peb
=
NtCurrentTeb
()
->
Peb
;
IMAGE_NT_HEADERS
*
nt
=
RtlImageNtHeader
(
peb
->
ImageBaseAddress
);
void
*
entry
=
(
char
*
)
peb
->
ImageBaseAddress
+
nt
->
OptionalHeader
.
AddressOfEntryPoint
;
NTSTATUS
status
;
int
suspend
;
#ifdef __APPLE__
send_server_task_port
();
#endif
/* Install signal handlers; this cannot be done earlier, since we cannot
* send exceptions to the debugger before the create process event that
* is sent by init_process_done */
signal_init_process
();
/* Signal the parent process to continue */
SERVER_START_REQ
(
init_process_done
)
{
req
->
module
=
wine_server_client_ptr
(
peb
->
ImageBaseAddress
);
#ifdef __i386__
req
->
ldt_copy
=
wine_server_client_ptr
(
&
__wine_ldt_copy
);
#endif
req
->
entry
=
wine_server_client_ptr
(
entry
);
req
->
gui
=
(
nt
->
OptionalHeader
.
Subsystem
!=
IMAGE_SUBSYSTEM_WINDOWS_CUI
);
status
=
wine_server_call
(
req
);
suspend
=
reply
->
suspend
;
}
SERVER_END_REQ
;
assert
(
!
status
);
signal_start_thread
(
entry
,
peb
,
suspend
,
relay
,
NtCurrentTeb
()
);
}
...
...
dlls/ntdll/unix/signal_arm.c
View file @
2333099c
...
...
@@ -66,10 +66,178 @@
#include "unix_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
static
pthread_key_t
teb_key
;
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
#if defined(__ANDROID__) && !defined(HAVE_SYS_UCONTEXT_H)
typedef
struct
ucontext
{
unsigned
long
uc_flags
;
struct
ucontext
*
uc_link
;
stack_t
uc_stack
;
struct
sigcontext
uc_mcontext
;
sigset_t
uc_sigmask
;
unsigned
long
uc_regspace
[
128
]
__attribute__
((
__aligned__
(
8
)));
}
ucontext_t
;
#endif
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name)
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.arm_r##reg_num)
/* Special Registers access */
# define SP_sig(context) REG_sig(arm_sp, context)
/* Stack pointer */
# define LR_sig(context) REG_sig(arm_lr, context)
/* Link register */
# define PC_sig(context) REG_sig(arm_pc, context)
/* Program counter */
# define CPSR_sig(context) REG_sig(arm_cpsr, context)
/* Current State Register */
# define IP_sig(context) REG_sig(arm_ip, context)
/* Intra-Procedure-call scratch register */
# define FP_sig(context) REG_sig(arm_fp, context)
/* Frame pointer */
/* Exceptions */
# define ERROR_sig(context) REG_sig(error_code, context)
# define TRAP_sig(context) REG_sig(trap_no, context)
#elif defined(__FreeBSD__)
/* All Registers access - only for local access */
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.__gregs[reg_num])
/* Special Registers access */
# define SP_sig(context) REGn_sig(_REG_SP, context)
/* Stack pointer */
# define LR_sig(context) REGn_sig(_REG_LR, context)
/* Link register */
# define PC_sig(context) REGn_sig(_REG_PC, context)
/* Program counter */
# define CPSR_sig(context) REGn_sig(_REG_CPSR, context)
/* Current State Register */
# define IP_sig(context) REGn_sig(_REG_R12, context)
/* Intra-Procedure-call scratch register */
# define FP_sig(context) REGn_sig(_REG_FP, context)
/* Frame pointer */
#endif
/* linux */
enum
arm_trap_code
{
TRAP_ARM_UNKNOWN
=
-
1
,
/* Unknown fault (TRAP_sig not defined) */
TRAP_ARM_PRIVINFLT
=
6
,
/* Invalid opcode exception */
TRAP_ARM_PAGEFLT
=
14
,
/* Page fault */
TRAP_ARM_ALIGNFLT
=
17
,
/* Alignment check exception */
};
typedef
void
(
WINAPI
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/***********************************************************************
* get_trap_code
*
* Get the trap code for a signal.
*/
static
inline
enum
arm_trap_code
get_trap_code
(
int
signal
,
const
ucontext_t
*
sigcontext
)
{
#ifdef TRAP_sig
enum
arm_trap_code
trap
=
TRAP_sig
(
sigcontext
);
if
(
trap
)
return
trap
;
#endif
switch
(
signal
)
{
case
SIGILL
:
return
TRAP_ARM_PRIVINFLT
;
case
SIGSEGV
:
return
TRAP_ARM_PAGEFLT
;
case
SIGBUS
:
return
TRAP_ARM_ALIGNFLT
;
default:
return
TRAP_ARM_UNKNOWN
;
}
}
/***********************************************************************
* get_error_code
*
* Get the error code for a signal.
*/
static
inline
WORD
get_error_code
(
const
ucontext_t
*
sigcontext
)
{
#ifdef ERROR_sig
return
ERROR_sig
(
sigcontext
);
#else
return
0
;
#endif
}
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->R##x = REGn_sig(x,sigcontext)
/* Save normal registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
#undef C
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
Sp
=
SP_sig
(
sigcontext
);
/* Stack pointer */
context
->
Lr
=
LR_sig
(
sigcontext
);
/* Link register */
context
->
Pc
=
PC_sig
(
sigcontext
);
/* Program Counter */
context
->
Cpsr
=
CPSR_sig
(
sigcontext
);
/* Current State Register */
context
->
R11
=
FP_sig
(
sigcontext
);
/* Frame pointer */
context
->
R12
=
IP_sig
(
sigcontext
);
/* Intra-Procedure-call scratch register */
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
#define C(x) REGn_sig(x,sigcontext) = context->R##x
/* Restore normal registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
#undef C
SP_sig
(
sigcontext
)
=
context
->
Sp
;
/* Stack pointer */
LR_sig
(
sigcontext
)
=
context
->
Lr
;
/* Link register */
PC_sig
(
sigcontext
)
=
context
->
Pc
;
/* Program Counter */
CPSR_sig
(
sigcontext
)
=
context
->
Cpsr
;
/* Current State Register */
FP_sig
(
sigcontext
)
=
context
->
R11
;
/* Frame pointer */
IP_sig
(
sigcontext
)
=
context
->
R12
;
/* Intra-Procedure-call scratch register */
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
inline
void
save_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"not implemented
\n
"
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"not implemented
\n
"
);
}
/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
...
...
@@ -305,6 +473,311 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
}
extern
void
raise_func_trampoline_thumb
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline_thumb
,
".thumb
\n\t
"
"blx r2
\n\t
"
"bkpt"
)
extern
void
raise_func_trampoline_arm
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline_arm
,
".arm
\n\t
"
"blx r2
\n\t
"
"bkpt"
)
/***********************************************************************
* setup_exception_record
*
* Setup the exception record and context on the thread stack.
*/
static
EXCEPTION_RECORD
*
setup_exception
(
ucontext_t
*
sigcontext
,
raise_func
func
)
{
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
}
*
stack
;
DWORD
exception_code
=
0
;
stack
=
(
struct
stack_layout
*
)(
SP_sig
(
sigcontext
)
&
~
3
);
stack
--
;
/* push the stack_layout structure */
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
PC_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
/* now modify the sigcontext to return to the raise function */
SP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
if
(
CPSR_sig
(
sigcontext
)
&
0x20
)
PC_sig
(
sigcontext
)
=
(
DWORD
)
raise_func_trampoline_thumb
;
else
PC_sig
(
sigcontext
)
=
(
DWORD
)
raise_func_trampoline_arm
;
REGn_sig
(
0
,
sigcontext
)
=
(
DWORD
)
&
stack
->
rec
;
/* first arg for raise_func */
REGn_sig
(
1
,
sigcontext
)
=
(
DWORD
)
&
stack
->
context
;
/* second arg for raise_func */
REGn_sig
(
2
,
sigcontext
)
=
(
DWORD
)
func
;
/* the raise_func as third arg for the trampoline */
return
&
stack
->
rec
;
}
/**********************************************************************
* raise_segv_exception
*/
static
void
WINAPI
raise_segv_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
NTSTATUS
status
;
switch
(
rec
->
ExceptionCode
)
{
case
EXCEPTION_ACCESS_VIOLATION
:
if
(
rec
->
NumberParameters
==
2
)
{
if
(
!
(
rec
->
ExceptionCode
=
virtual_handle_fault
(
(
void
*
)
rec
->
ExceptionInformation
[
1
],
rec
->
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
}
break
;
}
status
=
NtRaiseException
(
rec
,
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
done
:
set_cpu_context
(
context
);
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
EXCEPTION_RECORD
*
rec
;
ucontext_t
*
context
=
ucontext
;
/* check for page fault inside the thread stack */
if
(
get_trap_code
(
signal
,
context
)
==
TRAP_ARM_PAGEFLT
)
{
switch
(
virtual_handle_stack_fault
(
info
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
rec
=
setup_exception
(
context
,
raise_segv_exception
);
rec
->
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
return
;
}
}
rec
=
setup_exception
(
context
,
raise_segv_exception
);
if
(
rec
->
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
return
;
switch
(
get_trap_code
(
signal
,
context
))
{
case
TRAP_ARM_PRIVINFLT
:
/* Invalid opcode exception */
rec
->
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_ARM_PAGEFLT
:
/* Page fault */
rec
->
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
rec
->
NumberParameters
=
2
;
rec
->
ExceptionInformation
[
0
]
=
(
get_error_code
(
context
)
&
0x800
)
!=
0
;
rec
->
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
info
->
si_addr
;
break
;
case
TRAP_ARM_ALIGNFLT
:
/* Alignment check exception */
rec
->
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
case
TRAP_ARM_UNKNOWN
:
/* Unknown fault code */
rec
->
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
rec
->
NumberParameters
=
2
;
rec
->
ExceptionInformation
[
0
]
=
0
;
rec
->
ExceptionInformation
[
1
]
=
0xffffffff
;
break
;
default
:
ERR
(
"Got unexpected trap %d
\n
"
,
get_trap_code
(
signal
,
context
));
rec
->
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
switch
(
info
->
si_code
)
{
case
TRAP_TRACE
:
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
default
:
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
break
;
}
save_context
(
&
context
,
ucontext
);
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
ucontext
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_fpu
(
&
context
,
sigcontext
);
save_context
(
&
context
,
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
restore_fpu
(
&
context
,
sigcontext
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* get_thread_ldt_entry
*/
...
...
@@ -363,6 +836,40 @@ void signal_init_thread( TEB *teb )
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* init_thread_context
*/
...
...
@@ -397,6 +904,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
ctx
=
(
CONTEXT
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
1
;
init_thread_context
(
ctx
,
entry
,
arg
,
relay
);
}
pthread_sigmask
(
SIG_UNBLOCK
,
&
server_block_set
,
NULL
);
ctx
->
ContextFlags
=
CONTEXT_FULL
;
LdrInitializeThunk
(
ctx
,
(
void
**
)
&
ctx
->
R0
,
0
,
0
);
return
ctx
;
...
...
dlls/ntdll/unix/signal_arm64.c
View file @
2333099c
...
...
@@ -69,10 +69,63 @@
#include "unix_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name)
# define REGn_sig(reg_num, context) ((context)->uc_mcontext.regs[reg_num])
/* Special Registers access */
# define SP_sig(context) REG_sig(sp, context)
/* Stack pointer */
# define PC_sig(context) REG_sig(pc, context)
/* Program counter */
# define PSTATE_sig(context) REG_sig(pstate, context)
/* Current State Register */
# define FP_sig(context) REGn_sig(29, context)
/* Frame pointer */
# define LR_sig(context) REGn_sig(30, context)
/* Link Register */
static
struct
_aarch64_ctx
*
get_extended_sigcontext
(
ucontext_t
*
sigcontext
,
unsigned
int
magic
)
{
struct
_aarch64_ctx
*
ctx
=
(
struct
_aarch64_ctx
*
)
sigcontext
->
uc_mcontext
.
__reserved
;
while
((
char
*
)
ctx
<
(
char
*
)(
&
sigcontext
->
uc_mcontext
+
1
)
&&
ctx
->
magic
&&
ctx
->
size
)
{
if
(
ctx
->
magic
==
magic
)
return
ctx
;
ctx
=
(
struct
_aarch64_ctx
*
)((
char
*
)
ctx
+
ctx
->
size
);
}
return
NULL
;
}
static
struct
fpsimd_context
*
get_fpsimd_context
(
ucontext_t
*
sigcontext
)
{
return
(
struct
fpsimd_context
*
)
get_extended_sigcontext
(
sigcontext
,
FPSIMD_MAGIC
);
}
static
DWORD64
get_fault_esr
(
ucontext_t
*
sigcontext
)
{
struct
esr_context
*
esr
=
(
struct
esr_context
*
)
get_extended_sigcontext
(
sigcontext
,
ESR_MAGIC
);
if
(
esr
)
return
esr
->
esr
;
return
0
;
}
#endif
/* linux */
static
pthread_key_t
teb_key
;
static
const
size_t
teb_size
=
0x2000
;
/* we reserve two pages for the TEB */
typedef
void
(
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/* stack layout when calling an exception raise function */
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
void
*
redzone
[
2
];
};
struct
arm64_thread_data
{
void
*
exit_frame
;
/* exit frame pointer */
...
...
@@ -89,6 +142,76 @@ static inline struct arm64_thread_data *arm64_thread_data(void)
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
DWORD
i
;
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
u
.
s
.
Fp
=
FP_sig
(
sigcontext
);
/* Frame pointer */
context
->
u
.
s
.
Lr
=
LR_sig
(
sigcontext
);
/* Link register */
context
->
Sp
=
SP_sig
(
sigcontext
);
/* Stack pointer */
context
->
Pc
=
PC_sig
(
sigcontext
);
/* Program Counter */
context
->
Cpsr
=
PSTATE_sig
(
sigcontext
);
/* Current State Register */
for
(
i
=
0
;
i
<=
28
;
i
++
)
context
->
u
.
X
[
i
]
=
REGn_sig
(
i
,
sigcontext
);
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
DWORD
i
;
FP_sig
(
sigcontext
)
=
context
->
u
.
s
.
Fp
;
/* Frame pointer */
LR_sig
(
sigcontext
)
=
context
->
u
.
s
.
Lr
;
/* Link register */
SP_sig
(
sigcontext
)
=
context
->
Sp
;
/* Stack pointer */
PC_sig
(
sigcontext
)
=
context
->
Pc
;
/* Program Counter */
PSTATE_sig
(
sigcontext
)
=
context
->
Cpsr
;
/* Current State Register */
for
(
i
=
0
;
i
<=
28
;
i
++
)
REGn_sig
(
i
,
sigcontext
)
=
context
->
u
.
X
[
i
];
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
void
save_fpu
(
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
struct
fpsimd_context
*
fp
=
get_fpsimd_context
(
sigcontext
);
if
(
!
fp
)
return
;
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
Fpcr
=
fp
->
fpcr
;
context
->
Fpsr
=
fp
->
fpsr
;
memcpy
(
context
->
V
,
fp
->
vregs
,
sizeof
(
context
->
V
)
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
void
restore_fpu
(
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
struct
fpsimd_context
*
fp
=
get_fpsimd_context
(
sigcontext
);
if
(
!
fp
)
return
;
fp
->
fpcr
=
context
->
Fpcr
;
fp
->
fpsr
=
context
->
Fpsr
;
memcpy
(
fp
->
vregs
,
context
->
V
,
sizeof
(
fp
->
vregs
)
);
}
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
...
...
@@ -297,6 +420,278 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
}
/***********************************************************************
* setup_exception
*
* Setup the exception record and context on the thread stack.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
struct
stack_layout
*
stack
;
DWORD
exception_code
=
0
;
/* push the stack_layout structure */
stack
=
(
struct
stack_layout
*
)((
SP_sig
(
sigcontext
)
-
sizeof
(
*
stack
))
&
~
15
);
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
PC_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
save_fpu
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
extern
void
raise_func_trampoline
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
,
void
*
sp
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline
,
__ASM_CFI
(
".cfi_signal_frame
\n\t
"
)
"stp x29, x30, [sp, #-0x20]!
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_offset 32
\n\t
"
)
__ASM_CFI
(
".cfi_offset 29, -32
\n\t
"
)
__ASM_CFI
(
".cfi_offset 30, -24
\n\t
"
)
"mov x29, sp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register 29
\n\t
"
)
"str x3, [sp, 0x10]
\n\t
"
__ASM_CFI
(
".cfi_remember_state
\n\t
"
)
__ASM_CFI
(
".cfi_escape 0x0f,0x03,0x8d,0x10,0x06
\n\t
"
)
/* CFA */
__ASM_CFI
(
".cfi_escape 0x10,0x1d,0x02,0x8d,0x00
\n\t
"
)
/* x29 */
__ASM_CFI
(
".cfi_escape 0x10,0x1e,0x02,0x8d,0x08
\n\t
"
)
/* x30 */
"blr x2
\n\t
"
__ASM_CFI
(
".cfi_restore_state
\n\t
"
)
"brk #1"
)
/***********************************************************************
* setup_raise_exception
*
* Modify the signal context to call the exception raise function.
*/
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
NTSTATUS
status
=
send_debug_event
(
&
stack
->
rec
,
&
stack
->
context
,
TRUE
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
REGn_sig
(
3
,
sigcontext
)
=
SP_sig
(
sigcontext
);
/* original stack pointer, fourth arg for raise_func_trampoline */
SP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
stack
;
LR_sig
(
sigcontext
)
=
PC_sig
(
sigcontext
);
PC_sig
(
sigcontext
)
=
(
ULONG_PTR
)
raise_func_trampoline
;
/* raise_generic_exception; */
REGn_sig
(
0
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
rec
;
/* first arg for raise_generic_exception */
REGn_sig
(
1
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
context
;
/* second arg for raise_generic_exception */
REGn_sig
(
2
,
sigcontext
)
=
(
ULONG_PTR
)
KiUserExceptionDispatcher
;
/* third arg for raise_func_trampoline */
REGn_sig
(
18
,
sigcontext
)
=
(
ULONG_PTR
)
NtCurrentTeb
();
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
struct
stack_layout
*
stack
;
ucontext_t
*
context
=
ucontext
;
/* check for page fault inside the thread stack */
if
(
signal
==
SIGSEGV
)
{
switch
(
virtual_handle_stack_fault
(
info
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception
(
context
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception
(
context
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
signal
)
{
case
SIGILL
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
SIGSEGV
:
/* Segmentation fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
get_fault_esr
(
context
)
&
0x40
)
!=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
info
->
si_addr
;
if
(
!
(
stack
->
rec
.
ExceptionCode
=
virtual_handle_fault
(
(
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
)))
return
;
break
;
case
SIGBUS
:
/* Alignment check exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default
:
ERR
(
"Got unexpected signal %i
\n
"
,
signal
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done
:
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
ucontext_t
*
context
=
ucontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
info
->
si_code
)
{
case
TRAP_TRACE
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
context
.
Pc
+=
4
;
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* usr2_handler
*
* Handler for SIGUSR2, used to set a thread context.
*/
static
void
usr2_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
*
context
=
InterlockedExchangePointer
(
(
void
**
)
&
arm64_thread_data
()
->
context
,
NULL
);
if
(
!
context
)
return
;
if
((
context
->
ContextFlags
&
~
CONTEXT_ARM64
)
&
CONTEXT_FLOATING_POINT
)
restore_fpu
(
context
,
sigcontext
);
restore_context
(
context
,
sigcontext
);
}
/**********************************************************************
* get_thread_ldt_entry
*/
...
...
@@ -361,6 +756,41 @@ void signal_init_thread( TEB *teb )
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_SIGINFO
|
SA_RESTART
|
SA_ONSTACK
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr2_handler
;
if
(
sigaction
(
SIGUSR2
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* init_thread_context
*/
...
...
@@ -396,6 +826,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
ctx
=
(
CONTEXT
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
1
;
init_thread_context
(
ctx
,
entry
,
arg
,
relay
);
}
pthread_sigmask
(
SIG_UNBLOCK
,
&
server_block_set
,
NULL
);
ctx
->
ContextFlags
=
CONTEXT_FULL
;
LdrInitializeThunk
(
ctx
,
(
void
**
)
&
ctx
->
u
.
s
.
X0
,
0
,
0
);
return
ctx
;
...
...
dlls/ntdll/unix/signal_i386.c
View file @
2333099c
...
...
@@ -63,6 +63,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
#undef ERR
/* Solaris needs to define this */
/* not defined for x86, so copy the x86_64 definition */
typedef
struct
DECLSPEC_ALIGN
(
16
)
_M128A
{
...
...
@@ -96,6 +98,89 @@ typedef struct
#ifdef __linux__
#ifndef HAVE_SYS_UCONTEXT_H
enum
{
REG_GS
,
REG_FS
,
REG_ES
,
REG_DS
,
REG_EDI
,
REG_ESI
,
REG_EBP
,
REG_ESP
,
REG_EBX
,
REG_EDX
,
REG_ECX
,
REG_EAX
,
REG_TRAPNO
,
REG_ERR
,
REG_EIP
,
REG_CS
,
REG_EFL
,
REG_UESP
,
REG_SS
,
NGREG
};
typedef
int
greg_t
;
typedef
greg_t
gregset_t
[
NGREG
];
struct
_libc_fpreg
{
unsigned
short
significand
[
4
];
unsigned
short
exponent
;
};
struct
_libc_fpstate
{
unsigned
long
cw
;
unsigned
long
sw
;
unsigned
long
tag
;
unsigned
long
ipoff
;
unsigned
long
cssel
;
unsigned
long
dataoff
;
unsigned
long
datasel
;
struct
_libc_fpreg
_st
[
8
];
unsigned
long
status
;
};
typedef
struct
_libc_fpstate
*
fpregset_t
;
typedef
struct
{
gregset_t
gregs
;
fpregset_t
fpregs
;
unsigned
long
oldmask
;
unsigned
long
cr2
;
}
mcontext_t
;
typedef
struct
ucontext
{
unsigned
long
uc_flags
;
struct
ucontext
*
uc_link
;
stack_t
uc_stack
;
mcontext_t
uc_mcontext
;
sigset_t
uc_sigmask
;
}
ucontext_t
;
#endif
/* HAVE_SYS_UCONTEXT_H */
#define EAX_sig(context) ((context)->uc_mcontext.gregs[REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[REG_EBP])
#define ESP_sig(context) ((context)->uc_mcontext.gregs[REG_ESP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((FLOATING_SAVE_AREA*)((context)->uc_mcontext.fpregs))
#define FPUX_sig(context) (FPU_sig(context) && !((context)->uc_mcontext.fpregs->status >> 16) ? (XMM_SAVE_AREA32 *)(FPU_sig(context) + 1) : NULL)
#ifdef __ANDROID__
/* custom signal restorer since we may have unmapped the one in vdso, and bionic doesn't check for that */
void
rt_sigreturn
(
void
);
__ASM_GLOBAL_FUNC
(
rt_sigreturn
,
"movl $173,%eax
\n\t
"
/* NR_rt_sigreturn */
"int $0x80"
);
#endif
struct
modify_ldt_s
{
unsigned
int
entry_number
;
...
...
@@ -120,49 +205,287 @@ static inline int set_thread_area( struct modify_ldt_s *ptr )
return
syscall
(
243
/* SYS_set_thread_area */
,
ptr
);
}
#elif defined (__BSDI__)
#include <machine/frame.h>
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <machine/trap.h>
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->uc_mcontext.mc_eax)
#define EBX_sig(context) ((context)->uc_mcontext.mc_ebx)
#define ECX_sig(context) ((context)->uc_mcontext.mc_ecx)
#define EDX_sig(context) ((context)->uc_mcontext.mc_edx)
#define ESI_sig(context) ((context)->uc_mcontext.mc_esi)
#define EDI_sig(context) ((context)->uc_mcontext.mc_edi)
#define EBP_sig(context) ((context)->uc_mcontext.mc_ebp)
#define CS_sig(context) ((context)->uc_mcontext.mc_cs)
#define DS_sig(context) ((context)->uc_mcontext.mc_ds)
#define ES_sig(context) ((context)->uc_mcontext.mc_es)
#define FS_sig(context) ((context)->uc_mcontext.mc_fs)
#define GS_sig(context) ((context)->uc_mcontext.mc_gs)
#define SS_sig(context) ((context)->uc_mcontext.mc_ss)
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
#define EFL_sig(context) ((context)->uc_mcontext.mc_eflags)
#define EIP_sig(context) ((context)->uc_mcontext.mc_eip)
#define ESP_sig(context) ((context)->uc_mcontext.mc_esp)
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#elif defined (__OpenBSD__)
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->sc_eax)
#define EBX_sig(context) ((context)->sc_ebx)
#define ECX_sig(context) ((context)->sc_ecx)
#define EDX_sig(context) ((context)->sc_edx)
#define ESI_sig(context) ((context)->sc_esi)
#define EDI_sig(context) ((context)->sc_edi)
#define EBP_sig(context) ((context)->sc_ebp)
#define CS_sig(context) ((context)->sc_cs)
#define DS_sig(context) ((context)->sc_ds)
#define ES_sig(context) ((context)->sc_es)
#define FS_sig(context) ((context)->sc_fs)
#define GS_sig(context) ((context)->sc_gs)
#define SS_sig(context) ((context)->sc_ss)
#define TRAP_sig(context) ((context)->sc_trapno)
#define ERROR_sig(context) ((context)->sc_err)
#define EFL_sig(context) ((context)->sc_eflags)
#define EIP_sig(context) ((context)->sc_eip)
#define ESP_sig(context) ((context)->sc_esp)
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#define T_MCHK T_MACHK
#define T_XMMFLT T_XFTRAP
#elif defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
#if defined(_SCO_DS) || defined(__sun)
#include <sys/regset.h>
#endif
#ifdef _SCO_DS
#define gregs regs
#endif
#define EAX_sig(context) ((context)->uc_mcontext.gregs[EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[EBP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[EIP])
#ifdef UESP
#define ESP_sig(context) ((context)->uc_mcontext.gregs[UESP])
#elif defined(R_ESP)
#define ESP_sig(context) ((context)->uc_mcontext.gregs[R_ESP])
#else
#define ESP_sig(context) ((context)->uc_mcontext.gregs[ESP])
#endif
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[ERR])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[TRAPNO])
#define FPU_sig(context) NULL
/* FIXME */
#define FPUX_sig(context) NULL
/* FIXME */
#elif defined (__APPLE__)
#include <i386/user_ldt.h>
/* work around silly renaming of struct members in OS X 10.5 */
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
#define EAX_sig(context) ((context)->uc_mcontext->__ss.__eax)
#define EBX_sig(context) ((context)->uc_mcontext->__ss.__ebx)
#define ECX_sig(context) ((context)->uc_mcontext->__ss.__ecx)
#define EDX_sig(context) ((context)->uc_mcontext->__ss.__edx)
#define ESI_sig(context) ((context)->uc_mcontext->__ss.__esi)
#define EDI_sig(context) ((context)->uc_mcontext->__ss.__edi)
#define EBP_sig(context) ((context)->uc_mcontext->__ss.__ebp)
#define CS_sig(context) ((context)->uc_mcontext->__ss.__cs)
#define DS_sig(context) ((context)->uc_mcontext->__ss.__ds)
#define ES_sig(context) ((context)->uc_mcontext->__ss.__es)
#define FS_sig(context) ((context)->uc_mcontext->__ss.__fs)
#define GS_sig(context) ((context)->uc_mcontext->__ss.__gs)
#define SS_sig(context) ((context)->uc_mcontext->__ss.__ss)
#define EFL_sig(context) ((context)->uc_mcontext->__ss.__eflags)
#define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__eip))
#define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__esp))
#define TRAP_sig(context) ((context)->uc_mcontext->__es.__trapno)
#define ERROR_sig(context) ((context)->uc_mcontext->__es.__err)
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
#else
#define EAX_sig(context) ((context)->uc_mcontext->ss.eax)
#define EBX_sig(context) ((context)->uc_mcontext->ss.ebx)
#define ECX_sig(context) ((context)->uc_mcontext->ss.ecx)
#define EDX_sig(context) ((context)->uc_mcontext->ss.edx)
#define ESI_sig(context) ((context)->uc_mcontext->ss.esi)
#define EDI_sig(context) ((context)->uc_mcontext->ss.edi)
#define EBP_sig(context) ((context)->uc_mcontext->ss.ebp)
#define CS_sig(context) ((context)->uc_mcontext->ss.cs)
#define DS_sig(context) ((context)->uc_mcontext->ss.ds)
#define ES_sig(context) ((context)->uc_mcontext->ss.es)
#define FS_sig(context) ((context)->uc_mcontext->ss.fs)
#define GS_sig(context) ((context)->uc_mcontext->ss.gs)
#define SS_sig(context) ((context)->uc_mcontext->ss.ss)
#define EFL_sig(context) ((context)->uc_mcontext->ss.eflags)
#define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
#define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.esp))
#define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
#define ERROR_sig(context) ((context)->uc_mcontext->es.err)
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->fs.fpu_fcw)
#endif
#elif defined(__NetBSD__)
#include <machine/segments.h>
#include <machine/sysarch.h>
#define EAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.__gregs[_REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.__gregs[_REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EBP])
#define ESP_sig(context) _UC_MACHINE_SP(context)
#define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_EFL])
#define EIP_sig(context) _UC_MACHINE_PC(context)
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define FPU_sig(context) NULL
#define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&((context)->uc_mcontext.__fpregs))
#define T_MCHK T_MCA
#define T_XMMFLT T_XMM
#elif defined(__GNU__)
#include <mach/i386/mach_i386.h>
#include <mach/mach_traps.h>
#define EAX_sig(context) ((context)->uc_mcontext.gregs[REG_EAX])
#define EBX_sig(context) ((context)->uc_mcontext.gregs[REG_EBX])
#define ECX_sig(context) ((context)->uc_mcontext.gregs[REG_ECX])
#define EDX_sig(context) ((context)->uc_mcontext.gregs[REG_EDX])
#define ESI_sig(context) ((context)->uc_mcontext.gregs[REG_ESI])
#define EDI_sig(context) ((context)->uc_mcontext.gregs[REG_EDI])
#define EBP_sig(context) ((context)->uc_mcontext.gregs[REG_EBP])
#define ESP_sig(context) ((context)->uc_mcontext.gregs[REG_ESP])
#define CS_sig(context) ((context)->uc_mcontext.gregs[REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.gregs[REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.gregs[REG_ES])
#define SS_sig(context) ((context)->uc_mcontext.gregs[REG_SS])
#define FS_sig(context) ((context)->uc_mcontext.gregs[REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.gregs[REG_GS])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
#define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((FLOATING_SAVE_AREA *)&(context)->uc_mcontext.fpregs.fp_reg_set.fpchip_state)
#define FPUX_sig(context) NULL
#else
#error You must define the signal context functions for your platform
#endif
/* linux */
/* stack layout when calling an exception raise function */
struct
stack_layout
{
void
*
ret_addr
;
/* return address from raise_generic_exception */
EXCEPTION_RECORD
*
rec_ptr
;
/* first arg for raise_generic_exception */
CONTEXT
*
context_ptr
;
/* second arg for raise_generic_exception */
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
DWORD
ebp
;
DWORD
eip
;
};
static
const
size_t
teb_size
=
4096
;
/* we reserve one page for the TEB */
static
ULONG
first_ldt_entry
=
32
;
enum
i386_trap_code
{
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
TRAP_x86_DIVIDE
=
T_DIVIDE
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
T_TRCTRAP
,
/* Single-step exception */
TRAP_x86_NMI
=
T_NMI
,
/* NMI interrupt */
TRAP_x86_BPTFLT
=
T_BPTFLT
,
/* Breakpoint exception */
TRAP_x86_OFLOW
=
T_OFLOW
,
/* Overflow exception */
TRAP_x86_BOUND
=
T_BOUND
,
/* Bound range exception */
TRAP_x86_PRIVINFLT
=
T_PRIVINFLT
,
/* Invalid opcode exception */
TRAP_x86_DNA
=
T_DNA
,
/* Device not available exception */
TRAP_x86_DOUBLEFLT
=
T_DOUBLEFLT
,
/* Double fault exception */
TRAP_x86_FPOPFLT
=
T_FPOPFLT
,
/* Coprocessor segment overrun */
TRAP_x86_TSSFLT
=
T_TSSFLT
,
/* Invalid TSS exception */
TRAP_x86_SEGNPFLT
=
T_SEGNPFLT
,
/* Segment not present exception */
TRAP_x86_STKFLT
=
T_STKFLT
,
/* Stack fault */
TRAP_x86_PROTFLT
=
T_PROTFLT
,
/* General protection fault */
TRAP_x86_PAGEFLT
=
T_PAGEFLT
,
/* Page fault */
TRAP_x86_ARITHTRAP
=
T_ARITHTRAP
,
/* Floating point exception */
TRAP_x86_ALIGNFLT
=
T_ALIGNFLT
,
/* Alignment check exception */
TRAP_x86_MCHK
=
T_MCHK
,
/* Machine check exception */
TRAP_x86_CACHEFLT
=
T_XMMFLT
/* Cache flush exception */
#else
TRAP_x86_DIVIDE
=
0
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
1
,
/* Single-step exception */
TRAP_x86_NMI
=
2
,
/* NMI interrupt */
TRAP_x86_BPTFLT
=
3
,
/* Breakpoint exception */
TRAP_x86_OFLOW
=
4
,
/* Overflow exception */
TRAP_x86_BOUND
=
5
,
/* Bound range exception */
TRAP_x86_PRIVINFLT
=
6
,
/* Invalid opcode exception */
TRAP_x86_DNA
=
7
,
/* Device not available exception */
TRAP_x86_DOUBLEFLT
=
8
,
/* Double fault exception */
TRAP_x86_FPOPFLT
=
9
,
/* Coprocessor segment overrun */
TRAP_x86_TSSFLT
=
10
,
/* Invalid TSS exception */
TRAP_x86_SEGNPFLT
=
11
,
/* Segment not present exception */
TRAP_x86_STKFLT
=
12
,
/* Stack fault */
TRAP_x86_PROTFLT
=
13
,
/* General protection fault */
TRAP_x86_PAGEFLT
=
14
,
/* Page fault */
TRAP_x86_ARITHTRAP
=
16
,
/* Floating point exception */
TRAP_x86_ALIGNFLT
=
17
,
/* Alignment check exception */
TRAP_x86_MCHK
=
18
,
/* Machine check exception */
TRAP_x86_CACHEFLT
=
19
/* SIMD exception (via SIGFPE) if CPU is SSE capable
otherwise Cache flush exception (via SIGSEV) */
#endif
};
struct
x86_thread_data
{
DWORD
fs
;
/* 1d4 TEB selector */
...
...
@@ -190,6 +513,7 @@ static inline WORD get_ds(void) { WORD res; __asm__( "movw %%ds,%0" : "=r" (res)
static
inline
WORD
get_fs
(
void
)
{
WORD
res
;
__asm__
(
"movw %%fs,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
WORD
get_gs
(
void
)
{
WORD
res
;
__asm__
(
"movw %%gs,%0"
:
"=r"
(
res
)
);
return
res
;
}
static
inline
void
set_fs
(
WORD
val
)
{
__asm__
(
"mov %0,%%fs"
::
"r"
(
val
));
}
static
inline
void
set_gs
(
WORD
val
)
{
__asm__
(
"mov %0,%%gs"
::
"r"
(
val
));
}
/***********************************************************************
...
...
@@ -202,6 +526,132 @@ static inline int is_gdt_sel( WORD sel )
/***********************************************************************
* ldt_is_system
*/
static
inline
int
ldt_is_system
(
WORD
sel
)
{
return
is_gdt_sel
(
sel
)
||
((
sel
>>
3
)
<
first_ldt_entry
);
}
/***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
4096
;
}
/***********************************************************************
* get_current_teb
*
* Get the current teb based on the stack pointer.
*/
static
inline
TEB
*
get_current_teb
(
void
)
{
unsigned
long
esp
;
__asm__
(
"movl %%esp,%0"
:
"=g"
(
esp
)
);
return
(
TEB
*
)(
esp
&
~
signal_stack_mask
);
}
#ifdef __sun
/* We have to workaround two Solaris breakages:
* - Solaris doesn't restore %ds and %es before calling the signal handler so exceptions in 16-bit
* code crash badly.
* - Solaris inserts a libc trampoline to call our handler, but the trampoline expects that registers
* are setup correctly. So we need to insert our own trampoline below the libc trampoline to set %gs.
*/
extern
int
sigaction_syscall
(
int
sig
,
const
struct
sigaction
*
new
,
struct
sigaction
*
old
);
__ASM_GLOBAL_FUNC
(
sigaction_syscall
,
"movl $0x62,%eax
\n\t
"
"int $0x91
\n\t
"
"ret"
)
/* assume the same libc handler is used for all signals */
static
void
(
*
libc_sigacthandler
)(
int
signal
,
siginfo_t
*
siginfo
,
void
*
context
);
static
void
wine_sigacthandler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
x86_thread_data
*
thread_data
;
__asm__
__volatile__
(
"mov %ss,%ax; mov %ax,%ds; mov %ax,%es"
);
thread_data
=
(
struct
x86_thread_data
*
)
get_current_teb
()
->
SystemReserved2
;
set_fs
(
thread_data
->
fs
);
set_gs
(
thread_data
->
gs
);
libc_sigacthandler
(
signal
,
siginfo
,
sigcontext
);
}
static
int
solaris_sigaction
(
int
sig
,
const
struct
sigaction
*
new
,
struct
sigaction
*
old
)
{
struct
sigaction
real_act
;
if
(
sigaction
(
sig
,
new
,
old
)
==
-
1
)
return
-
1
;
/* retrieve the real handler and flags with a direct syscall */
sigaction_syscall
(
sig
,
NULL
,
&
real_act
);
libc_sigacthandler
=
real_act
.
sa_sigaction
;
real_act
.
sa_sigaction
=
wine_sigacthandler
;
sigaction_syscall
(
sig
,
&
real_act
,
NULL
);
return
0
;
}
#define sigaction(sig,new,old) solaris_sigaction(sig,new,old)
#endif
extern
void
clear_alignment_flag
(
void
);
__ASM_GLOBAL_FUNC
(
clear_alignment_flag
,
"pushfl
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
"andl $~0x40000,(%esp)
\n\t
"
"popfl
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset -4
\n\t
"
)
"ret"
)
/***********************************************************************
* init_handler
*
* Handler initialization when the full context is not needed.
* Return the stack pointer to use for pushing the exception data.
*/
static
inline
void
*
init_handler
(
const
ucontext_t
*
sigcontext
)
{
TEB
*
teb
=
get_current_teb
();
clear_alignment_flag
();
#ifndef __sun
/* see above for Solaris handling */
{
struct
x86_thread_data
*
thread_data
=
(
struct
x86_thread_data
*
)
teb
->
SystemReserved2
;
set_fs
(
thread_data
->
fs
);
set_gs
(
thread_data
->
gs
);
}
#endif
if
(
!
ldt_is_system
(
CS_sig
(
sigcontext
))
||
!
ldt_is_system
(
SS_sig
(
sigcontext
)))
/* 16-bit mode */
{
/*
* Win16 or DOS protected mode. Note that during switch
* from 16-bit mode to linear mode, CS may be set to system
* segment before FS is restored. Fortunately, in this case
* SS is still non-system segment. This is why both CS and SS
* are checked.
*/
return
teb
->
WOW32Reserved
;
}
return
(
void
*
)(
ESP_sig
(
sigcontext
)
&
~
3
);
}
/***********************************************************************
* save_fpu
*
* Save the thread FPU context.
...
...
@@ -281,6 +731,141 @@ static inline void restore_fpux( const CONTEXT *context )
/***********************************************************************
* fpux_to_fpu
*
* Build a standard FPU context from an extended one.
*/
static
void
fpux_to_fpu
(
FLOATING_SAVE_AREA
*
fpu
,
const
XMM_SAVE_AREA32
*
fpux
)
{
unsigned
int
i
,
tag
,
stack_top
;
fpu
->
ControlWord
=
fpux
->
ControlWord
|
0xffff0000
;
fpu
->
StatusWord
=
fpux
->
StatusWord
|
0xffff0000
;
fpu
->
ErrorOffset
=
fpux
->
ErrorOffset
;
fpu
->
ErrorSelector
=
fpux
->
ErrorSelector
|
(
fpux
->
ErrorOpcode
<<
16
);
fpu
->
DataOffset
=
fpux
->
DataOffset
;
fpu
->
DataSelector
=
fpux
->
DataSelector
;
fpu
->
Cr0NpxState
=
fpux
->
StatusWord
|
0xffff0000
;
stack_top
=
(
fpux
->
StatusWord
>>
11
)
&
7
;
fpu
->
TagWord
=
0xffff0000
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
memcpy
(
&
fpu
->
RegisterArea
[
10
*
i
],
&
fpux
->
FloatRegisters
[
i
],
10
);
if
(
!
(
fpux
->
TagWord
&
(
1
<<
i
)))
tag
=
3
;
/* empty */
else
{
const
M128A
*
reg
=
&
fpux
->
FloatRegisters
[(
i
-
stack_top
)
&
7
];
if
((
reg
->
High
&
0x7fff
)
==
0x7fff
)
/* exponent all ones */
{
tag
=
2
;
/* special */
}
else
if
(
!
(
reg
->
High
&
0x7fff
))
/* exponent all zeroes */
{
if
(
reg
->
Low
)
tag
=
2
;
/* special */
else
tag
=
1
;
/* zero */
}
else
{
if
(
reg
->
Low
>>
63
)
tag
=
0
;
/* valid */
else
tag
=
2
;
/* special */
}
}
fpu
->
TagWord
|=
tag
<<
(
2
*
i
);
}
}
/***********************************************************************
* save_context
*
* Build a context structure from the signal info.
*/
static
inline
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FLOATING_SAVE_AREA
*
fpu
=
FPU_sig
(
sigcontext
);
XMM_SAVE_AREA32
*
fpux
=
FPUX_sig
(
sigcontext
);
memset
(
context
,
0
,
sizeof
(
*
context
));
context
->
ContextFlags
=
CONTEXT_FULL
|
CONTEXT_DEBUG_REGISTERS
;
context
->
Eax
=
EAX_sig
(
sigcontext
);
context
->
Ebx
=
EBX_sig
(
sigcontext
);
context
->
Ecx
=
ECX_sig
(
sigcontext
);
context
->
Edx
=
EDX_sig
(
sigcontext
);
context
->
Esi
=
ESI_sig
(
sigcontext
);
context
->
Edi
=
EDI_sig
(
sigcontext
);
context
->
Ebp
=
EBP_sig
(
sigcontext
);
context
->
EFlags
=
EFL_sig
(
sigcontext
);
context
->
Eip
=
EIP_sig
(
sigcontext
);
context
->
Esp
=
ESP_sig
(
sigcontext
);
context
->
SegCs
=
LOWORD
(
CS_sig
(
sigcontext
));
context
->
SegDs
=
LOWORD
(
DS_sig
(
sigcontext
));
context
->
SegEs
=
LOWORD
(
ES_sig
(
sigcontext
));
context
->
SegFs
=
LOWORD
(
FS_sig
(
sigcontext
));
context
->
SegGs
=
LOWORD
(
GS_sig
(
sigcontext
));
context
->
SegSs
=
LOWORD
(
SS_sig
(
sigcontext
));
context
->
Dr0
=
x86_thread_data
()
->
dr0
;
context
->
Dr1
=
x86_thread_data
()
->
dr1
;
context
->
Dr2
=
x86_thread_data
()
->
dr2
;
context
->
Dr3
=
x86_thread_data
()
->
dr3
;
context
->
Dr6
=
x86_thread_data
()
->
dr6
;
context
->
Dr7
=
x86_thread_data
()
->
dr7
;
if
(
fpu
)
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
FloatSave
=
*
fpu
;
}
if
(
fpux
)
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
|
CONTEXT_EXTENDED_REGISTERS
;
memcpy
(
context
->
ExtendedRegisters
,
fpux
,
sizeof
(
*
fpux
)
);
if
(
!
fpu
)
fpux_to_fpu
(
&
context
->
FloatSave
,
fpux
);
}
if
(
!
fpu
&&
!
fpux
)
save_fpu
(
context
);
}
/***********************************************************************
* restore_context
*
* Restore the signal info from the context.
*/
static
inline
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
FLOATING_SAVE_AREA
*
fpu
=
FPU_sig
(
sigcontext
);
XMM_SAVE_AREA32
*
fpux
=
FPUX_sig
(
sigcontext
);
x86_thread_data
()
->
dr0
=
context
->
Dr0
;
x86_thread_data
()
->
dr1
=
context
->
Dr1
;
x86_thread_data
()
->
dr2
=
context
->
Dr2
;
x86_thread_data
()
->
dr3
=
context
->
Dr3
;
x86_thread_data
()
->
dr6
=
context
->
Dr6
;
x86_thread_data
()
->
dr7
=
context
->
Dr7
;
EAX_sig
(
sigcontext
)
=
context
->
Eax
;
EBX_sig
(
sigcontext
)
=
context
->
Ebx
;
ECX_sig
(
sigcontext
)
=
context
->
Ecx
;
EDX_sig
(
sigcontext
)
=
context
->
Edx
;
ESI_sig
(
sigcontext
)
=
context
->
Esi
;
EDI_sig
(
sigcontext
)
=
context
->
Edi
;
EBP_sig
(
sigcontext
)
=
context
->
Ebp
;
EFL_sig
(
sigcontext
)
=
context
->
EFlags
;
EIP_sig
(
sigcontext
)
=
context
->
Eip
;
ESP_sig
(
sigcontext
)
=
context
->
Esp
;
CS_sig
(
sigcontext
)
=
context
->
SegCs
;
DS_sig
(
sigcontext
)
=
context
->
SegDs
;
ES_sig
(
sigcontext
)
=
context
->
SegEs
;
FS_sig
(
sigcontext
)
=
context
->
SegFs
;
GS_sig
(
sigcontext
)
=
context
->
SegGs
;
SS_sig
(
sigcontext
)
=
context
->
SegSs
;
if
(
fpu
)
*
fpu
=
context
->
FloatSave
;
if
(
fpux
)
memcpy
(
fpux
,
context
->
ExtendedRegisters
,
sizeof
(
*
fpux
)
);
if
(
!
fpu
&&
!
fpux
)
restore_fpu
(
context
);
}
/***********************************************************************
* set_full_cpu_context
*
* Set the new CPU context.
...
...
@@ -641,6 +1226,683 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
/***********************************************************************
* is_privileged_instr
*
* Check if the fault location is a privileged instruction.
* Based on the instruction emulation code in dlls/kernel/instr.c.
*/
static
inline
DWORD
is_privileged_instr
(
CONTEXT
*
context
)
{
BYTE
instr
[
16
];
unsigned
int
i
,
len
,
prefix_count
=
0
;
if
(
!
ldt_is_system
(
context
->
SegCs
))
return
0
;
len
=
virtual_uninterrupted_read_memory
(
(
BYTE
*
)
context
->
Eip
,
instr
,
sizeof
(
instr
)
);
for
(
i
=
0
;
i
<
len
;
i
++
)
switch
(
instr
[
i
])
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x64
:
/* %fs: */
case
0x65
:
/* %gs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
EXCEPTION_ILLEGAL_INSTRUCTION
;
continue
;
case
0x0f
:
/* extended instruction */
if
(
i
==
len
-
1
)
return
0
;
switch
(
instr
[
i
+
1
])
{
case
0x20
:
/* mov crX, reg */
case
0x21
:
/* mov drX, reg */
case
0x22
:
/* mov reg, crX */
case
0x23
:
/* mov reg drX */
return
EXCEPTION_PRIV_INSTRUCTION
;
}
return
0
;
case
0x6c
:
/* insb (%dx) */
case
0x6d
:
/* insl (%dx) */
case
0x6e
:
/* outsb (%dx) */
case
0x6f
:
/* outsl (%dx) */
case
0xcd
:
/* int $xx */
case
0xe4
:
/* inb al,XX */
case
0xe5
:
/* in (e)ax,XX */
case
0xe6
:
/* outb XX,al */
case
0xe7
:
/* out XX,(e)ax */
case
0xec
:
/* inb (%dx),%al */
case
0xed
:
/* inl (%dx),%eax */
case
0xee
:
/* outb %al,(%dx) */
case
0xef
:
/* outl %eax,(%dx) */
case
0xf4
:
/* hlt */
case
0xfa
:
/* cli */
case
0xfb
:
/* sti */
return
EXCEPTION_PRIV_INSTRUCTION
;
default
:
return
0
;
}
return
0
;
}
/***********************************************************************
* check_invalid_gs
*
* Check for fault caused by invalid %gs value (some copy protection schemes mess with it).
*/
static
inline
BOOL
check_invalid_gs
(
ucontext_t
*
sigcontext
,
CONTEXT
*
context
)
{
unsigned
int
prefix_count
=
0
;
const
BYTE
*
instr
=
(
BYTE
*
)
context
->
Eip
;
WORD
system_gs
=
x86_thread_data
()
->
gs
;
if
(
context
->
SegGs
==
system_gs
)
return
FALSE
;
if
(
!
ldt_is_system
(
context
->
SegCs
))
return
FALSE
;
/* only handle faults in system libraries */
if
(
virtual_is_valid_code_address
(
instr
,
1
))
return
FALSE
;
for
(;;)
switch
(
*
instr
)
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x64
:
/* %fs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
FALSE
;
instr
++
;
continue
;
case
0x65
:
/* %gs: */
TRACE
(
"%04x/%04x at %p, fixing up
\n
"
,
context
->
SegGs
,
system_gs
,
instr
);
GS_sig
(
sigcontext
)
=
system_gs
;
return
TRUE
;
default
:
return
FALSE
;
}
}
#include "pshpack1.h"
union
atl_thunk
{
struct
{
DWORD
movl
;
/* movl this,4(%esp) */
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t1
;
struct
{
BYTE
movl
;
/* movl this,ecx */
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t2
;
struct
{
BYTE
movl1
;
/* movl this,edx */
DWORD
this
;
BYTE
movl2
;
/* movl func,ecx */
DWORD
func
;
WORD
jmp
;
/* jmp ecx */
}
t3
;
struct
{
BYTE
movl1
;
/* movl this,ecx */
DWORD
this
;
BYTE
movl2
;
/* movl func,eax */
DWORD
func
;
WORD
jmp
;
/* jmp eax */
}
t4
;
struct
{
DWORD
inst1
;
/* pop ecx
* pop eax
* push ecx
* jmp 4(%eax) */
WORD
inst2
;
}
t5
;
};
#include "poppack.h"
/**********************************************************************
* check_atl_thunk
*
* Check if code destination is an ATL thunk, and emulate it if so.
*/
static
BOOL
check_atl_thunk
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
const
union
atl_thunk
*
thunk
=
(
const
union
atl_thunk
*
)
stack
->
rec
.
ExceptionInformation
[
1
];
union
atl_thunk
thunk_copy
;
SIZE_T
thunk_len
;
thunk_len
=
virtual_uninterrupted_read_memory
(
thunk
,
&
thunk_copy
,
sizeof
(
*
thunk
)
);
if
(
!
thunk_len
)
return
FALSE
;
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t1
)
&&
thunk_copy
.
t1
.
movl
==
0x042444c7
&&
thunk_copy
.
t1
.
jmp
==
0xe9
)
{
if
(
!
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
+
1
,
&
thunk_copy
.
t1
.
this
,
sizeof
(
DWORD
)
))
{
EIP_sig
(
sigcontext
)
=
(
DWORD_PTR
)(
&
thunk
->
t1
.
func
+
1
)
+
thunk_copy
.
t1
.
func
;
TRACE
(
"emulating ATL thunk type 1 at %p, func=%08x arg=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
thunk_copy
.
t1
.
this
);
return
TRUE
;
}
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t2
)
&&
thunk_copy
.
t2
.
movl
==
0xb9
&&
thunk_copy
.
t2
.
jmp
==
0xe9
)
{
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t2
.
this
;
EIP_sig
(
sigcontext
)
=
(
DWORD_PTR
)(
&
thunk
->
t2
.
func
+
1
)
+
thunk_copy
.
t2
.
func
;
TRACE
(
"emulating ATL thunk type 2 at %p, func=%08x ecx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
ECX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t3
)
&&
thunk_copy
.
t3
.
movl1
==
0xba
&&
thunk_copy
.
t3
.
movl2
==
0xb9
&&
thunk_copy
.
t3
.
jmp
==
0xe1ff
)
{
EDX_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
this
;
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
func
;
EIP_sig
(
sigcontext
)
=
thunk_copy
.
t3
.
func
;
TRACE
(
"emulating ATL thunk type 3 at %p, func=%08x ecx=%08x edx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
ECX_sig
(
sigcontext
),
EDX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t4
)
&&
thunk_copy
.
t4
.
movl1
==
0xb9
&&
thunk_copy
.
t4
.
movl2
==
0xb8
&&
thunk_copy
.
t4
.
jmp
==
0xe0ff
)
{
ECX_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
this
;
EAX_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
func
;
EIP_sig
(
sigcontext
)
=
thunk_copy
.
t4
.
func
;
TRACE
(
"emulating ATL thunk type 4 at %p, func=%08x eax=%08x ecx=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
EAX_sig
(
sigcontext
),
ECX_sig
(
sigcontext
)
);
return
TRUE
;
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t5
)
&&
thunk_copy
.
t5
.
inst1
==
0xff515859
&&
thunk_copy
.
t5
.
inst2
==
0x0460
)
{
DWORD
func
,
sp
[
2
];
if
(
virtual_uninterrupted_read_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
,
sp
,
sizeof
(
sp
)
)
==
sizeof
(
sp
)
&&
virtual_uninterrupted_read_memory
(
(
DWORD
*
)
sp
[
1
]
+
1
,
&
func
,
sizeof
(
DWORD
)
)
==
sizeof
(
DWORD
)
&&
!
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
stack
->
context
.
Esp
+
1
,
&
sp
[
0
],
sizeof
(
sp
[
0
])
))
{
ECX_sig
(
sigcontext
)
=
sp
[
0
];
EAX_sig
(
sigcontext
)
=
sp
[
1
];
ESP_sig
(
sigcontext
)
+=
sizeof
(
DWORD
);
EIP_sig
(
sigcontext
)
=
func
;
TRACE
(
"emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08x esp=%08x
\n
"
,
thunk
,
EIP_sig
(
sigcontext
),
EAX_sig
(
sigcontext
),
ECX_sig
(
sigcontext
),
ESP_sig
(
sigcontext
)
);
return
TRUE
;
}
}
return
FALSE
;
}
/***********************************************************************
* setup_exception_record
*
* Setup the exception record and context on the thread stack.
*/
static
struct
stack_layout
*
setup_exception_record
(
ucontext_t
*
sigcontext
,
void
*
stack_ptr
)
{
struct
stack_layout
*
stack
=
stack_ptr
;
DWORD
exception_code
=
0
;
/* stack sanity checks */
if
((
char
*
)
stack
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
stack
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
)
{
WINE_ERR
(
"nested exception on signal stack in thread %04x eip %08x esp %08x stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
if
(
stack
-
1
>
stack
||
/* check for overflow in subtraction */
(
char
*
)
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
(
char
*
)
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
{
WARN
(
"exception outside of stack limits in thread %04x eip %08x esp %08x stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
(
char
*
)(
stack
-
1
);
WINE_ERR
(
"stack overflow %u bytes in thread %04x eip %08x esp %08x stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
)
{
/* stack access below stack limit, may be recoverable */
switch
(
virtual_handle_stack_fault
(
stack
-
1
))
{
case
0
:
/* not handled */
{
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
-
(
char
*
)(
stack
-
1
);
WINE_ERR
(
"stack overflow %u bytes in thread %04x eip %08x esp %08x stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
unsigned
int
)
EIP_sig
(
sigcontext
),
(
unsigned
int
)
ESP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
case
-
1
:
/* overflow */
exception_code
=
EXCEPTION_STACK_OVERFLOW
;
break
;
}
}
stack
--
;
/* push the stack_layout structure */
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED
(
stack
,
sizeof
(
*
stack
));
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE
(
stack
,
sizeof
(
*
stack
));
#endif
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
EIP_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
void
*
stack
=
init_handler
(
sigcontext
);
return
setup_exception_record
(
sigcontext
,
stack
);
}
/***********************************************************************
* setup_raise_exception
*
* Change context to setup a call to a raise exception function.
*/
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
NTSTATUS
status
=
send_debug_event
(
&
stack
->
rec
,
&
stack
->
context
,
TRUE
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
ESP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
EIP_sig
(
sigcontext
)
=
(
DWORD
)
KiUserExceptionDispatcher
;
/* clear single-step, direction, and align check flag */
EFL_sig
(
sigcontext
)
&=
~
(
0x100
|
0x400
|
0x40000
);
CS_sig
(
sigcontext
)
=
get_cs
();
DS_sig
(
sigcontext
)
=
get_ds
();
ES_sig
(
sigcontext
)
=
get_ds
();
FS_sig
(
sigcontext
)
=
get_fs
();
GS_sig
(
sigcontext
)
=
get_gs
();
SS_sig
(
sigcontext
)
=
get_ds
();
stack
->
ret_addr
=
(
void
*
)
0xdeadbabe
;
/* KiUserExceptionDispatcher must not return */
stack
->
rec_ptr
=
&
stack
->
rec
;
/* arguments for KiUserExceptionDispatcher */
stack
->
context_ptr
=
&
stack
->
context
;
}
/**********************************************************************
* get_fpu_code
*
* Get the FPU exception code from the FPU status.
*/
static
inline
DWORD
get_fpu_code
(
const
CONTEXT
*
context
)
{
DWORD
status
=
context
->
FloatSave
.
StatusWord
&
~
(
context
->
FloatSave
.
ControlWord
&
0x3f
);
if
(
status
&
0x01
)
/* IE */
{
if
(
status
&
0x40
)
/* SF */
return
EXCEPTION_FLT_STACK_CHECK
;
else
return
EXCEPTION_FLT_INVALID_OPERATION
;
}
if
(
status
&
0x02
)
return
EXCEPTION_FLT_DENORMAL_OPERAND
;
/* DE flag */
if
(
status
&
0x04
)
return
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
/* ZE flag */
if
(
status
&
0x08
)
return
EXCEPTION_FLT_OVERFLOW
;
/* OE flag */
if
(
status
&
0x10
)
return
EXCEPTION_FLT_UNDERFLOW
;
/* UE flag */
if
(
status
&
0x20
)
return
EXCEPTION_FLT_INEXACT_RESULT
;
/* PE flag */
return
EXCEPTION_FLT_INVALID_OPERATION
;
/* generic error */
}
/***********************************************************************
* handle_interrupt
*
* Handle an interrupt.
*/
static
BOOL
handle_interrupt
(
unsigned
int
interrupt
,
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
switch
(
interrupt
)
{
case
0x2d
:
if
(
!
is_wow64
)
{
/* On Wow64, the upper DWORD of Rax contains garbage, and the debug
* service is usually not recognized when called from usermode. */
switch
(
stack
->
context
.
Eax
)
{
case
1
:
/* BREAKPOINT_PRINT */
case
3
:
/* BREAKPOINT_LOAD_SYMBOLS */
case
4
:
/* BREAKPOINT_UNLOAD_SYMBOLS */
case
5
:
/* BREAKPOINT_COMMAND_STRING (>= Win2003) */
EIP_sig
(
sigcontext
)
+=
3
;
return
TRUE
;
}
}
stack
->
context
.
Eip
+=
3
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
stack
->
context
.
Eip
;
stack
->
rec
.
NumberParameters
=
is_wow64
?
1
:
3
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
stack
->
context
.
Eax
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
stack
->
context
.
Ecx
;
stack
->
rec
.
ExceptionInformation
[
2
]
=
stack
->
context
.
Edx
;
setup_raise_exception
(
sigcontext
,
stack
);
return
TRUE
;
default:
return
FALSE
;
}
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
;
ucontext_t
*
context
=
sigcontext
;
void
*
stack_ptr
=
init_handler
(
sigcontext
);
/* check for exceptions on the signal stack caused by write watches */
if
(
TRAP_sig
(
context
)
==
TRAP_x86_PAGEFLT
&&
(
char
*
)
stack_ptr
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
stack_ptr
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
&&
!
virtual_handle_fault
(
siginfo
->
si_addr
,
(
ERROR_sig
(
context
)
>>
1
)
&
0x09
,
TRUE
))
{
return
;
}
/* check for page fault inside the thread stack */
if
(
TRAP_sig
(
context
)
==
TRAP_x86_PAGEFLT
)
{
switch
(
virtual_handle_stack_fault
(
siginfo
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception_record
(
context
,
stack_ptr
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception_record
(
context
,
stack_ptr
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
TRAP_sig
(
context
))
{
case
TRAP_x86_OFLOW
:
/* Overflow exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
TRAP_x86_BOUND
:
/* Bound range exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
TRAP_x86_PRIVINFLT
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_x86_STKFLT
:
/* Stack fault */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
case
TRAP_x86_SEGNPFLT
:
/* Segment not present exception */
case
TRAP_x86_PROTFLT
:
/* General protection fault */
{
WORD
err
=
ERROR_sig
(
context
);
if
(
!
err
&&
(
stack
->
rec
.
ExceptionCode
=
is_privileged_instr
(
&
stack
->
context
)))
break
;
if
((
err
&
7
)
==
2
&&
handle_interrupt
(
err
>>
3
,
context
,
stack
))
return
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
/* if error contains a LDT selector, use that as fault address */
if
((
err
&
7
)
==
4
&&
!
ldt_is_system
(
err
|
7
))
stack
->
rec
.
ExceptionInformation
[
1
]
=
err
&
~
7
;
else
{
stack
->
rec
.
ExceptionInformation
[
1
]
=
0xffffffff
;
if
(
check_invalid_gs
(
context
,
&
stack
->
context
))
return
;
}
}
break
;
case
TRAP_x86_PAGEFLT
:
/* Page fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
ERROR_sig
(
context
)
>>
1
)
&
0x09
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
stack
->
rec
.
ExceptionCode
=
virtual_handle_fault
(
(
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
);
if
(
!
stack
->
rec
.
ExceptionCode
)
return
;
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_ACCESS_VIOLATION
&&
stack
->
rec
.
ExceptionInformation
[
0
]
==
EXCEPTION_EXECUTE_FAULT
)
{
ULONG
flags
;
NtQueryInformationProcess
(
GetCurrentProcess
(),
ProcessExecuteFlags
,
&
flags
,
sizeof
(
flags
),
NULL
);
if
(
!
(
flags
&
MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
)
&&
check_atl_thunk
(
context
,
stack
))
return
;
/* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
if
(
!
(
flags
&
MEM_EXECUTE_OPTION_DISABLE
))
stack
->
rec
.
ExceptionInformation
[
0
]
=
EXCEPTION_READ_FAULT
;
}
break
;
case
TRAP_x86_ALIGNFLT
:
/* Alignment check exception */
/* FIXME: pass through exception handler first? */
if
(
stack
->
context
.
EFlags
&
0x00040000
)
{
EFL_sig
(
context
)
&=
~
0x00040000
;
/* disable AC flag */
return
;
}
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default:
WINE_ERR
(
"Got unexpected trap %d
\n
"
,
TRAP_sig
(
context
)
);
/* fall through */
case
TRAP_x86_NMI
:
/* NMI interrupt */
case
TRAP_x86_DNA
:
/* Device not available exception */
case
TRAP_x86_DOUBLEFLT
:
/* Double fault exception */
case
TRAP_x86_TSSFLT
:
/* Invalid TSS exception */
case
TRAP_x86_MCHK
:
/* Machine check exception */
case
TRAP_x86_CACHEFLT
:
/* Cache flush exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done:
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
ucontext_t
*
context
=
sigcontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
TRAP_sig
(
context
))
{
case
TRAP_x86_TRCTRAP
:
/* Single-step exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
/* when single stepping can't tell whether this is a hw bp or a
* single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */
if
(
!
(
stack
->
context
.
EFlags
&
0x100
)
||
(
stack
->
context
.
Dr7
&
0xff
))
{
/* (possible) hardware breakpoint, fetch the debug registers */
DWORD
saved_flags
=
stack
->
context
.
ContextFlags
;
stack
->
context
.
ContextFlags
=
CONTEXT_DEBUG_REGISTERS
;
NtGetContextThread
(
GetCurrentThread
(),
&
stack
->
context
);
stack
->
context
.
ContextFlags
|=
saved_flags
;
/* restore flags */
}
stack
->
context
.
EFlags
&=
~
0x100
;
/* clear single-step flag */
break
;
case
TRAP_x86_BPTFLT
:
/* Breakpoint exception */
stack
->
rec
.
ExceptionAddress
=
(
char
*
)
stack
->
rec
.
ExceptionAddress
-
1
;
/* back up over the int3 instruction */
/* fall through */
default:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
NumberParameters
=
is_wow64
?
1
:
3
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
0
;
/* FIXME */
stack
->
rec
.
ExceptionInformation
[
2
]
=
0
;
/* FIXME */
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
ucontext_t
*
context
=
sigcontext
;
struct
stack_layout
*
stack
=
setup_exception
(
context
);
switch
(
TRAP_sig
(
context
))
{
case
TRAP_x86_DIVIDE
:
/* Division by zero exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
case
TRAP_x86_FPOPFLT
:
/* Coprocessor segment overrun */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
case
TRAP_x86_ARITHTRAP
:
/* Floating point exception */
stack
->
rec
.
ExceptionCode
=
get_fpu_code
(
&
stack
->
context
);
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
stack
->
context
.
FloatSave
.
ErrorOffset
;
break
;
case
TRAP_x86_CACHEFLT
:
/* SIMD exception */
/* TODO:
* Behaviour only tested for divide-by-zero exceptions
* Check for other SIMD exceptions as well */
if
(
siginfo
->
si_code
!=
FPE_FLTDIV
&&
siginfo
->
si_code
!=
FPE_FLTINV
)
FIXME
(
"untested SIMD exception: %#x. Might not work correctly
\n
"
,
siginfo
->
si_code
);
stack
->
rec
.
ExceptionCode
=
STATUS_FLOAT_MULTIPLE_TRAPS
;
stack
->
rec
.
NumberParameters
=
1
;
/* no idea what meaning is actually behind this but that's what native does */
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
break
;
default:
WINE_ERR
(
"Got unexpected trap %d
\n
"
,
TRAP_sig
(
context
)
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
context
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
init_handler
(
sigcontext
);
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
init_handler
(
sigcontext
);
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/***********************************************************************
* LDT support
*/
...
...
@@ -941,11 +2203,44 @@ void signal_init_thread( TEB *teb )
ldt_set_fs
(
thread_data
->
fs
,
teb
);
thread_data
->
gs
=
get_gs
();
#ifdef __GNUC__
__asm__
volatile
(
"fninit; fldcw %0"
:
:
"m"
(
fpu_cw
));
#else
FIXME
(
"FPU setup not implemented for this platform.
\n
"
);
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_SIGINFO
|
SA_RESTART
|
SA_ONSTACK
;
#ifdef __ANDROID__
sig_act
.
sa_flags
|=
SA_RESTORER
;
sig_act
.
sa_restorer
=
rt_sigreturn
;
#endif
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
return
;
error:
perror
(
"sigaction"
);
exit
(
1
);
}
...
...
@@ -993,6 +2288,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
ctx
=
(
CONTEXT
*
)((
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
16
)
-
1
;
init_thread_context
(
ctx
,
entry
,
arg
,
relay
);
}
pthread_sigmask
(
SIG_UNBLOCK
,
&
server_block_set
,
NULL
);
ctx
->
ContextFlags
=
CONTEXT_FULL
|
CONTEXT_FLOATING_POINT
|
CONTEXT_EXTENDED_REGISTERS
;
LdrInitializeThunk
(
ctx
,
(
void
**
)
&
ctx
->
Eax
,
0
,
0
);
return
ctx
;
...
...
dlls/ntdll/unix/signal_powerpc.c
View file @
2333099c
...
...
@@ -63,10 +63,182 @@
#include "unix_private.h"
#include "wine/debug.h"
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
# define IAR_sig(context) REG_sig(nip, context)
/* Program counter */
# define MSR_sig(context) REG_sig(msr, context)
/* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
/* Count register */
# define XER_sig(context) REG_sig(xer, context)
/* User's integer exception register */
# define LR_sig(context) REG_sig(link, context)
/* Link register */
# define CR_sig(context) REG_sig(ccr, context)
/* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context) REG_sig(dar, context)
# define DSISR_sig(context) REG_sig(dsisr, context)
# define TRAP_sig(context) REG_sig(trap, context)
#endif
/* linux */
#ifdef __APPLE__
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
# define IAR_sig(context) REG_sig(srr0, context)
/* Program counter */
# define MSR_sig(context) REG_sig(srr1, context)
/* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
# define XER_sig(context) REG_sig(xer, context)
/* Link register */
# define LR_sig(context) REG_sig(lr, context)
/* User's integer exception register */
# define CR_sig(context) REG_sig(cr, context)
/* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context) FLOATREG_sig(fpscr, context)
/* Exception Registers access */
# define DAR_sig(context) EXCEPREG_sig(dar, context)
/* Fault registers for coredump */
# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context) EXCEPREG_sig(exception, context)
/* number of powerpc exception taken */
/* Signal defs : Those are undefined on darwin
SIGBUS
#undef BUS_ADRERR
#undef BUS_OBJERR
SIGILL
#undef ILL_ILLOPN
#undef ILL_ILLTRP
#undef ILL_ILLADR
#undef ILL_COPROC
#undef ILL_PRVREG
#undef ILL_BADSTK
SIGTRAP
#undef TRAP_BRKPT
#undef TRAP_TRACE
SIGFPE
*/
#endif
/* __APPLE__ */
static
pthread_key_t
teb_key
;
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
/* Save Gpr registers */
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
context
->
Iar
=
IAR_sig
(
sigcontext
);
/* Program Counter */
context
->
Msr
=
MSR_sig
(
sigcontext
);
/* Machine State Register (Supervisor) */
context
->
Ctr
=
CTR_sig
(
sigcontext
);
context
->
Xer
=
XER_sig
(
sigcontext
);
context
->
Lr
=
LR_sig
(
sigcontext
);
context
->
Cr
=
CR_sig
(
sigcontext
);
/* Saving Exception regs */
context
->
Dar
=
DAR_sig
(
sigcontext
);
context
->
Dsisr
=
DSISR_sig
(
sigcontext
);
context
->
Trap
=
TRAP_sig
(
sigcontext
);
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
IAR_sig
(
sigcontext
)
=
context
->
Iar
;
/* Program Counter */
MSR_sig
(
sigcontext
)
=
context
->
Msr
;
/* Machine State Register (Supervisor) */
CTR_sig
(
sigcontext
)
=
context
->
Ctr
;
XER_sig
(
sigcontext
)
=
context
->
Xer
;
LR_sig
(
sigcontext
)
=
context
->
Lr
;
CR_sig
(
sigcontext
)
=
context
->
Cr
;
/* Setting Exception regs */
DAR_sig
(
sigcontext
)
=
context
->
Dar
;
DSISR_sig
(
sigcontext
)
=
context
->
Dsisr
;
TRAP_sig
(
sigcontext
)
=
context
->
Trap
;
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
inline
void
save_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
context
->
Fpscr
=
FPSCR_sig
(
sigcontext
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
#define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
C
(
0
);
C
(
1
);
C
(
2
);
C
(
3
);
C
(
4
);
C
(
5
);
C
(
6
);
C
(
7
);
C
(
8
);
C
(
9
);
C
(
10
);
C
(
11
);
C
(
12
);
C
(
13
);
C
(
14
);
C
(
15
);
C
(
16
);
C
(
17
);
C
(
18
);
C
(
19
);
C
(
20
);
C
(
21
);
C
(
22
);
C
(
23
);
C
(
24
);
C
(
25
);
C
(
26
);
C
(
27
);
C
(
28
);
C
(
29
);
C
(
30
);
C
(
31
);
#undef C
FPSCR_sig
(
sigcontext
)
=
context
->
Fpscr
;
}
/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
...
...
@@ -438,6 +610,288 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
switch
(
signal
)
{
case
SIGSEGV
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
SEGV_MAPERR
:
case
SEGV_ACCERR
:
rec
.
NumberParameters
=
2
;
rec
.
ExceptionInformation
[
0
]
=
0
;
/* FIXME ? */
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
rec
.
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
break
;
default:
FIXME
(
"Unhandled SIGSEGV/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
case
SIGBUS
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
BUS_ADRALN
:
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
#ifdef BUS_ADRERR
case
BUS_ADRERR
:
#endif
#ifdef BUS_OBJERR
case
BUS_OBJERR
:
/* FIXME: correct for all cases ? */
rec
.
NumberParameters
=
2
;
rec
.
ExceptionInformation
[
0
]
=
0
;
/* FIXME ? */
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
rec
.
ExceptionCode
=
unix_funcs
->
virtual_handle_fault
(
siginfo
->
si_addr
,
rec
.
ExceptionInformation
[
0
],
FALSE
)))
goto
done
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGBUS/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
case
SIGILL
:
switch
(
siginfo
->
si_code
&
0xffff
)
{
case
ILL_ILLOPC
:
/* illegal opcode */
#ifdef ILL_ILLOPN
case
ILL_ILLOPN
:
/* illegal operand */
#endif
#ifdef ILL_ILLADR
case
ILL_ILLADR
:
/* illegal addressing mode */
#endif
#ifdef ILL_ILLTRP
case
ILL_ILLTRP
:
/* illegal trap */
#endif
#ifdef ILL_COPROC
case
ILL_COPROC
:
/* coprocessor error */
#endif
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
ILL_PRVOPC
:
/* privileged opcode */
#ifdef ILL_PRVREG
case
ILL_PRVREG
:
/* privileged register */
#endif
rec
.
ExceptionCode
=
EXCEPTION_PRIV_INSTRUCTION
;
break
;
#ifdef ILL_BADSTK
case
ILL_BADSTK
:
/* internal stack error */
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGILL/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
break
;
}
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
done:
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
/* FIXME: check if we might need to modify PC */
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef TRAP_BRKPT
case
TRAP_BRKPT
:
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
break
;
#endif
#ifdef TRAP_TRACE
case
TRAP_TRACE
:
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
#endif
default:
FIXME
(
"Unhandled SIGTRAP/%x
\n
"
,
siginfo
->
si_code
);
break
;
}
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_fpu
(
&
context
,
sigcontext
);
save_context
(
&
context
,
sigcontext
);
switch
(
siginfo
->
si_code
&
0xffff
)
{
#ifdef FPE_FLTSUB
case
FPE_FLTSUB
:
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
#endif
#ifdef FPE_INTDIV
case
FPE_INTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_INTOVF
case
FPE_INTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTDIV
case
FPE_FLTDIV
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
#endif
#ifdef FPE_FLTOVF
case
FPE_FLTOVF
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
#endif
#ifdef FPE_FLTUND
case
FPE_FLTUND
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
#endif
#ifdef FPE_FLTRES
case
FPE_FLTRES
:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
#endif
#ifdef FPE_FLTINV
case
FPE_FLTINV
:
#endif
default:
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
restore_fpu
(
&
context
,
sigcontext
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
EXCEPTION_RECORD
rec
;
CONTEXT
context
;
NTSTATUS
status
;
save_context
(
&
context
,
sigcontext
);
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
rec
.
ExceptionRecord
=
NULL
;
rec
.
ExceptionAddress
=
(
LPVOID
)
context
.
Iar
;
rec
.
NumberParameters
=
0
;
status
=
NtRaiseException
(
&
rec
,
&
context
,
TRUE
);
if
(
status
)
RtlRaiseStatus
(
status
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
unix_funcs
->
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
sigcontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
sigcontext
);
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS
CDECL
get_thread_ldt_entry
(
HANDLE
handle
,
void
*
data
,
ULONG
len
,
ULONG
*
ret_len
)
...
...
@@ -491,6 +945,40 @@ void signal_init_thread( TEB *teb )
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_RESTART
|
SA_SIGINFO
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
return
;
error:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* signal_exit_thread
*/
...
...
dlls/ntdll/unix/signal_x86_64.c
View file @
2333099c
...
...
@@ -86,11 +86,124 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
#include <asm/prctl.h>
static
inline
int
arch_prctl
(
int
func
,
void
*
ptr
)
{
return
syscall
(
__NR_arch_prctl
,
func
,
ptr
);
}
#define RAX_sig(context) ((context)->uc_mcontext.gregs[REG_RAX])
#define RBX_sig(context) ((context)->uc_mcontext.gregs[REG_RBX])
#define RCX_sig(context) ((context)->uc_mcontext.gregs[REG_RCX])
#define RDX_sig(context) ((context)->uc_mcontext.gregs[REG_RDX])
#define RSI_sig(context) ((context)->uc_mcontext.gregs[REG_RSI])
#define RDI_sig(context) ((context)->uc_mcontext.gregs[REG_RDI])
#define RBP_sig(context) ((context)->uc_mcontext.gregs[REG_RBP])
#define R8_sig(context) ((context)->uc_mcontext.gregs[REG_R8])
#define R9_sig(context) ((context)->uc_mcontext.gregs[REG_R9])
#define R10_sig(context) ((context)->uc_mcontext.gregs[REG_R10])
#define R11_sig(context) ((context)->uc_mcontext.gregs[REG_R11])
#define R12_sig(context) ((context)->uc_mcontext.gregs[REG_R12])
#define R13_sig(context) ((context)->uc_mcontext.gregs[REG_R13])
#define R14_sig(context) ((context)->uc_mcontext.gregs[REG_R14])
#define R15_sig(context) ((context)->uc_mcontext.gregs[REG_R15])
#define CS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 0))
#define GS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 1))
#define FS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 2))
#define RSP_sig(context) ((context)->uc_mcontext.gregs[REG_RSP])
#define RIP_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
#define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
#elif defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
#define RAX_sig(context) ((context)->uc_mcontext.mc_rax)
#define RBX_sig(context) ((context)->uc_mcontext.mc_rbx)
#define RCX_sig(context) ((context)->uc_mcontext.mc_rcx)
#define RDX_sig(context) ((context)->uc_mcontext.mc_rdx)
#define RSI_sig(context) ((context)->uc_mcontext.mc_rsi)
#define RDI_sig(context) ((context)->uc_mcontext.mc_rdi)
#define RBP_sig(context) ((context)->uc_mcontext.mc_rbp)
#define R8_sig(context) ((context)->uc_mcontext.mc_r8)
#define R9_sig(context) ((context)->uc_mcontext.mc_r9)
#define R10_sig(context) ((context)->uc_mcontext.mc_r10)
#define R11_sig(context) ((context)->uc_mcontext.mc_r11)
#define R12_sig(context) ((context)->uc_mcontext.mc_r12)
#define R13_sig(context) ((context)->uc_mcontext.mc_r13)
#define R14_sig(context) ((context)->uc_mcontext.mc_r14)
#define R15_sig(context) ((context)->uc_mcontext.mc_r15)
#define CS_sig(context) ((context)->uc_mcontext.mc_cs)
#define DS_sig(context) ((context)->uc_mcontext.mc_ds)
#define ES_sig(context) ((context)->uc_mcontext.mc_es)
#define FS_sig(context) ((context)->uc_mcontext.mc_fs)
#define GS_sig(context) ((context)->uc_mcontext.mc_gs)
#define SS_sig(context) ((context)->uc_mcontext.mc_ss)
#define EFL_sig(context) ((context)->uc_mcontext.mc_rflags)
#define RIP_sig(context) ((context)->uc_mcontext.mc_rip)
#define RSP_sig(context) ((context)->uc_mcontext.mc_rsp)
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.mc_fpstate))
#elif defined(__NetBSD__)
#define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
#define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
#define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
#define RDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDX])
#define RSI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RSI])
#define RDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDI])
#define RBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBP])
#define R8_sig(context) ((context)->uc_mcontext.__gregs[_REG_R8])
#define R9_sig(context) ((context)->uc_mcontext.__gregs[_REG_R9])
#define R10_sig(context) ((context)->uc_mcontext.__gregs[_REG_R10])
#define R11_sig(context) ((context)->uc_mcontext.__gregs[_REG_R11])
#define R12_sig(context) ((context)->uc_mcontext.__gregs[_REG_R12])
#define R13_sig(context) ((context)->uc_mcontext.__gregs[_REG_R13])
#define R14_sig(context) ((context)->uc_mcontext.__gregs[_REG_R14])
#define R15_sig(context) ((context)->uc_mcontext.__gregs[_REG_R15])
#define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
#define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
#define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
#define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
#define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
#define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
#define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_RFL])
#define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_RIP]))
#define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_URSP]))
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
#elif defined (__APPLE__)
#define RAX_sig(context) ((context)->uc_mcontext->__ss.__rax)
#define RBX_sig(context) ((context)->uc_mcontext->__ss.__rbx)
#define RCX_sig(context) ((context)->uc_mcontext->__ss.__rcx)
#define RDX_sig(context) ((context)->uc_mcontext->__ss.__rdx)
#define RSI_sig(context) ((context)->uc_mcontext->__ss.__rsi)
#define RDI_sig(context) ((context)->uc_mcontext->__ss.__rdi)
#define RBP_sig(context) ((context)->uc_mcontext->__ss.__rbp)
#define R8_sig(context) ((context)->uc_mcontext->__ss.__r8)
#define R9_sig(context) ((context)->uc_mcontext->__ss.__r9)
#define R10_sig(context) ((context)->uc_mcontext->__ss.__r10)
#define R11_sig(context) ((context)->uc_mcontext->__ss.__r11)
#define R12_sig(context) ((context)->uc_mcontext->__ss.__r12)
#define R13_sig(context) ((context)->uc_mcontext->__ss.__r13)
#define R14_sig(context) ((context)->uc_mcontext->__ss.__r14)
#define R15_sig(context) ((context)->uc_mcontext->__ss.__r15)
#define CS_sig(context) ((context)->uc_mcontext->__ss.__cs)
#define FS_sig(context) ((context)->uc_mcontext->__ss.__fs)
#define GS_sig(context) ((context)->uc_mcontext->__ss.__gs)
#define EFL_sig(context) ((context)->uc_mcontext->__ss.__rflags)
#define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__rip))
#define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__rsp))
#define TRAP_sig(context) ((context)->uc_mcontext->__es.__trapno)
#define ERROR_sig(context) ((context)->uc_mcontext->__es.__err)
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
#else
#error You must define the signal context functions for your platform
#endif
enum
i386_trap_code
{
TRAP_x86_UNKNOWN
=
-
1
,
/* Unknown fault (TRAP_sig not defined) */
TRAP_x86_DIVIDE
=
0
,
/* Division by zero exception */
TRAP_x86_TRCTRAP
=
1
,
/* Single-step exception */
TRAP_x86_NMI
=
2
,
/* NMI interrupt */
...
...
@@ -114,6 +227,20 @@ enum i386_trap_code
static
const
size_t
teb_size
=
0x2000
;
/* we reserve two pages for the TEB */
typedef
void
(
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
/* stack layout when calling an exception raise function */
struct
stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
ULONG64
rsi
;
ULONG64
rdi
;
ULONG64
rbp
;
ULONG64
rip
;
ULONG64
red_zone
[
16
];
};
struct
amd64_thread_data
{
DWORD_PTR
dr0
;
/* debug registers */
...
...
@@ -134,6 +261,141 @@ static inline struct amd64_thread_data *amd64_thread_data(void)
}
static
inline
void
set_sigcontext
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
RAX_sig
(
sigcontext
)
=
context
->
Rax
;
RCX_sig
(
sigcontext
)
=
context
->
Rcx
;
RDX_sig
(
sigcontext
)
=
context
->
Rdx
;
RBX_sig
(
sigcontext
)
=
context
->
Rbx
;
RSP_sig
(
sigcontext
)
=
context
->
Rsp
;
RBP_sig
(
sigcontext
)
=
context
->
Rbp
;
RSI_sig
(
sigcontext
)
=
context
->
Rsi
;
RDI_sig
(
sigcontext
)
=
context
->
Rdi
;
R8_sig
(
sigcontext
)
=
context
->
R8
;
R9_sig
(
sigcontext
)
=
context
->
R9
;
R10_sig
(
sigcontext
)
=
context
->
R10
;
R11_sig
(
sigcontext
)
=
context
->
R11
;
R12_sig
(
sigcontext
)
=
context
->
R12
;
R13_sig
(
sigcontext
)
=
context
->
R13
;
R14_sig
(
sigcontext
)
=
context
->
R14
;
R15_sig
(
sigcontext
)
=
context
->
R15
;
RIP_sig
(
sigcontext
)
=
context
->
Rip
;
CS_sig
(
sigcontext
)
=
context
->
SegCs
;
FS_sig
(
sigcontext
)
=
context
->
SegFs
;
GS_sig
(
sigcontext
)
=
context
->
SegGs
;
EFL_sig
(
sigcontext
)
=
context
->
EFlags
;
#ifdef DS_sig
DS_sig
(
sigcontext
)
=
context
->
SegDs
;
#endif
#ifdef ES_sig
ES_sig
(
sigcontext
)
=
context
->
SegEs
;
#endif
#ifdef SS_sig
SS_sig
(
sigcontext
)
=
context
->
SegSs
;
#endif
}
/***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
teb_size
;
}
/***********************************************************************
* is_inside_signal_stack
*
* Check if pointer is inside the signal stack.
*/
static
inline
BOOL
is_inside_signal_stack
(
void
*
ptr
)
{
return
((
char
*
)
ptr
>=
(
char
*
)
get_signal_stack
()
&&
(
char
*
)
ptr
<
(
char
*
)
get_signal_stack
()
+
signal_stack_size
);
}
/***********************************************************************
* save_context
*
* Set the register values from a sigcontext.
*/
static
void
save_context
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
context
->
ContextFlags
=
CONTEXT_CONTROL
|
CONTEXT_INTEGER
|
CONTEXT_SEGMENTS
|
CONTEXT_DEBUG_REGISTERS
;
context
->
Rax
=
RAX_sig
(
sigcontext
);
context
->
Rcx
=
RCX_sig
(
sigcontext
);
context
->
Rdx
=
RDX_sig
(
sigcontext
);
context
->
Rbx
=
RBX_sig
(
sigcontext
);
context
->
Rsp
=
RSP_sig
(
sigcontext
);
context
->
Rbp
=
RBP_sig
(
sigcontext
);
context
->
Rsi
=
RSI_sig
(
sigcontext
);
context
->
Rdi
=
RDI_sig
(
sigcontext
);
context
->
R8
=
R8_sig
(
sigcontext
);
context
->
R9
=
R9_sig
(
sigcontext
);
context
->
R10
=
R10_sig
(
sigcontext
);
context
->
R11
=
R11_sig
(
sigcontext
);
context
->
R12
=
R12_sig
(
sigcontext
);
context
->
R13
=
R13_sig
(
sigcontext
);
context
->
R14
=
R14_sig
(
sigcontext
);
context
->
R15
=
R15_sig
(
sigcontext
);
context
->
Rip
=
RIP_sig
(
sigcontext
);
context
->
SegCs
=
CS_sig
(
sigcontext
);
context
->
SegFs
=
FS_sig
(
sigcontext
);
context
->
SegGs
=
GS_sig
(
sigcontext
);
context
->
EFlags
=
EFL_sig
(
sigcontext
);
#ifdef DS_sig
context
->
SegDs
=
DS_sig
(
sigcontext
);
#else
__asm__
(
"movw %%ds,%0"
:
"=m"
(
context
->
SegDs
));
#endif
#ifdef ES_sig
context
->
SegEs
=
ES_sig
(
sigcontext
);
#else
__asm__
(
"movw %%es,%0"
:
"=m"
(
context
->
SegEs
));
#endif
#ifdef SS_sig
context
->
SegSs
=
SS_sig
(
sigcontext
);
#else
__asm__
(
"movw %%ss,%0"
:
"=m"
(
context
->
SegSs
));
#endif
context
->
Dr0
=
amd64_thread_data
()
->
dr0
;
context
->
Dr1
=
amd64_thread_data
()
->
dr1
;
context
->
Dr2
=
amd64_thread_data
()
->
dr2
;
context
->
Dr3
=
amd64_thread_data
()
->
dr3
;
context
->
Dr6
=
amd64_thread_data
()
->
dr6
;
context
->
Dr7
=
amd64_thread_data
()
->
dr7
;
if
(
FPU_sig
(
sigcontext
))
{
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
context
->
u
.
FltSave
=
*
FPU_sig
(
sigcontext
);
context
->
MxCsr
=
context
->
u
.
FltSave
.
MxCsr
;
}
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
amd64_thread_data
()
->
dr0
=
context
->
Dr0
;
amd64_thread_data
()
->
dr1
=
context
->
Dr1
;
amd64_thread_data
()
->
dr2
=
context
->
Dr2
;
amd64_thread_data
()
->
dr3
=
context
->
Dr3
;
amd64_thread_data
()
->
dr6
=
context
->
Dr6
;
amd64_thread_data
()
->
dr7
=
context
->
Dr7
;
set_sigcontext
(
context
,
sigcontext
);
if
(
FPU_sig
(
sigcontext
))
*
FPU_sig
(
sigcontext
)
=
context
->
u
.
FltSave
;
}
/***********************************************************************
* set_full_cpu_context
*
...
...
@@ -501,6 +763,485 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
}
extern
void
CDECL
raise_func_trampoline
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
raise_func
func
);
__ASM_GLOBAL_FUNC
(
raise_func_trampoline
,
__ASM_CFI
(
".cfi_signal_frame
\n\t
"
)
__ASM_CFI
(
".cfi_def_cfa %rbp,160
\n\t
"
)
/* red zone + rip + rbp + rdi + rsi */
__ASM_CFI
(
".cfi_rel_offset %rip,24
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rbp,16
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rdi,8
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rsi,0
\n\t
"
)
"call *%r8
\n\t
"
"int $3"
)
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
struct
stack_layout
*
stack
;
DWORD
exception_code
=
0
;
stack
=
(
struct
stack_layout
*
)(
RSP_sig
(
sigcontext
)
&
~
15
);
/* stack sanity checks */
if
(
is_inside_signal_stack
(
stack
))
{
ERR
(
"nested exception on signal stack in thread %04x eip %016lx esp %016lx stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
if
(
stack
-
1
>
stack
||
/* check for overflow in subtraction */
(
char
*
)
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
(
char
*
)
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
{
WARN
(
"exception outside of stack limits in thread %04x eip %016lx esp %016lx stack %p-%p
\n
"
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
(
char
*
)(
stack
-
1
);
ERR
(
"stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
else
if
((
char
*
)(
stack
-
1
)
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
)
{
/* stack access below stack limit, may be recoverable */
switch
(
virtual_handle_stack_fault
(
stack
-
1
))
{
case
0
:
/* not handled */
{
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
-
(
char
*
)(
stack
-
1
);
ERR
(
"stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p
\n
"
,
diff
,
GetCurrentThreadId
(),
(
ULONG_PTR
)
RIP_sig
(
sigcontext
),
(
ULONG_PTR
)
RSP_sig
(
sigcontext
),
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
case
-
1
:
/* overflow */
exception_code
=
EXCEPTION_STACK_OVERFLOW
;
break
;
}
}
stack
--
;
/* push the stack_layout structure */
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED
(
stack
,
sizeof
(
*
stack
));
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE
(
stack
,
sizeof
(
*
stack
));
#endif
stack
->
rec
.
ExceptionRecord
=
NULL
;
stack
->
rec
.
ExceptionCode
=
exception_code
;
stack
->
rec
.
ExceptionFlags
=
EXCEPTION_CONTINUABLE
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
RIP_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
save_context
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
static
void
setup_raise_exception
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
ULONG64
*
rsp_ptr
;
NTSTATUS
status
;
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_SINGLE_STEP
)
{
/* when single stepping can't tell whether this is a hw bp or a
* single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */
if
(
!
(
stack
->
context
.
EFlags
&
0x100
)
||
(
stack
->
context
.
Dr7
&
0xff
))
{
/* (possible) hardware breakpoint, fetch the debug registers */
DWORD
saved_flags
=
stack
->
context
.
ContextFlags
;
stack
->
context
.
ContextFlags
=
CONTEXT_DEBUG_REGISTERS
;
NtGetContextThread
(
GetCurrentThread
(),
&
stack
->
context
);
stack
->
context
.
ContextFlags
|=
saved_flags
;
/* restore flags */
}
stack
->
context
.
EFlags
&=
~
0x100
;
/* clear single-step flag */
}
status
=
send_debug_event
(
&
stack
->
rec
,
&
stack
->
context
,
TRUE
);
if
(
status
==
DBG_CONTINUE
||
status
==
DBG_EXCEPTION_HANDLED
)
{
restore_context
(
&
stack
->
context
,
sigcontext
);
return
;
}
/* store return address and %rbp without aligning, so that the offset is fixed */
rsp_ptr
=
(
ULONG64
*
)
RSP_sig
(
sigcontext
)
-
16
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rip
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rbp
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rdi
;
*
(
--
rsp_ptr
)
=
stack
->
context
.
Rsi
;
/* now modify the sigcontext to return to the raise function */
RIP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
raise_func_trampoline
;
RCX_sig
(
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
rec
;
RDX_sig
(
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
context
;
R8_sig
(
sigcontext
)
=
(
ULONG_PTR
)
KiUserExceptionDispatcher
;
RBP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
rsp_ptr
;
RSP_sig
(
sigcontext
)
=
(
ULONG_PTR
)
stack
;
/* clear single-step, direction, and align check flag */
EFL_sig
(
sigcontext
)
&=
~
(
0x100
|
0x400
|
0x40000
);
}
/***********************************************************************
* is_privileged_instr
*
* Check if the fault location is a privileged instruction.
*/
static
inline
DWORD
is_privileged_instr
(
CONTEXT
*
context
)
{
BYTE
instr
[
16
];
unsigned
int
i
,
prefix_count
=
0
;
unsigned
int
len
=
virtual_uninterrupted_read_memory
(
(
BYTE
*
)
context
->
Rip
,
instr
,
sizeof
(
instr
)
);
for
(
i
=
0
;
i
<
len
;
i
++
)
switch
(
instr
[
i
])
{
/* instruction prefixes */
case
0x2e
:
/* %cs: */
case
0x36
:
/* %ss: */
case
0x3e
:
/* %ds: */
case
0x26
:
/* %es: */
case
0x40
:
/* rex */
case
0x41
:
/* rex */
case
0x42
:
/* rex */
case
0x43
:
/* rex */
case
0x44
:
/* rex */
case
0x45
:
/* rex */
case
0x46
:
/* rex */
case
0x47
:
/* rex */
case
0x48
:
/* rex */
case
0x49
:
/* rex */
case
0x4a
:
/* rex */
case
0x4b
:
/* rex */
case
0x4c
:
/* rex */
case
0x4d
:
/* rex */
case
0x4e
:
/* rex */
case
0x4f
:
/* rex */
case
0x64
:
/* %fs: */
case
0x65
:
/* %gs: */
case
0x66
:
/* opcode size */
case
0x67
:
/* addr size */
case
0xf0
:
/* lock */
case
0xf2
:
/* repne */
case
0xf3
:
/* repe */
if
(
++
prefix_count
>=
15
)
return
EXCEPTION_ILLEGAL_INSTRUCTION
;
continue
;
case
0x0f
:
/* extended instruction */
if
(
i
==
len
-
1
)
return
0
;
switch
(
instr
[
i
+
1
])
{
case
0x06
:
/* clts */
case
0x08
:
/* invd */
case
0x09
:
/* wbinvd */
case
0x20
:
/* mov crX, reg */
case
0x21
:
/* mov drX, reg */
case
0x22
:
/* mov reg, crX */
case
0x23
:
/* mov reg drX */
return
EXCEPTION_PRIV_INSTRUCTION
;
}
return
0
;
case
0x6c
:
/* insb (%dx) */
case
0x6d
:
/* insl (%dx) */
case
0x6e
:
/* outsb (%dx) */
case
0x6f
:
/* outsl (%dx) */
case
0xcd
:
/* int $xx */
case
0xe4
:
/* inb al,XX */
case
0xe5
:
/* in (e)ax,XX */
case
0xe6
:
/* outb XX,al */
case
0xe7
:
/* out XX,(e)ax */
case
0xec
:
/* inb (%dx),%al */
case
0xed
:
/* inl (%dx),%eax */
case
0xee
:
/* outb %al,(%dx) */
case
0xef
:
/* outl %eax,(%dx) */
case
0xf4
:
/* hlt */
case
0xfa
:
/* cli */
case
0xfb
:
/* sti */
return
EXCEPTION_PRIV_INSTRUCTION
;
default
:
return
0
;
}
return
0
;
}
/***********************************************************************
* handle_interrupt
*
* Handle an interrupt.
*/
static
inline
BOOL
handle_interrupt
(
ucontext_t
*
sigcontext
,
struct
stack_layout
*
stack
)
{
switch
(
ERROR_sig
(
sigcontext
)
>>
3
)
{
case
0x2c
:
stack
->
rec
.
ExceptionCode
=
STATUS_ASSERTION_FAILURE
;
break
;
case
0x2d
:
switch
(
stack
->
context
.
Rax
)
{
case
1
:
/* BREAKPOINT_PRINT */
case
3
:
/* BREAKPOINT_LOAD_SYMBOLS */
case
4
:
/* BREAKPOINT_UNLOAD_SYMBOLS */
case
5
:
/* BREAKPOINT_COMMAND_STRING (>= Win2003) */
RIP_sig
(
sigcontext
)
+=
3
;
return
TRUE
;
}
stack
->
context
.
Rip
+=
3
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
ExceptionAddress
=
(
void
*
)
stack
->
context
.
Rip
;
stack
->
rec
.
NumberParameters
=
1
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
stack
->
context
.
Rax
;
break
;
default
:
return
FALSE
;
}
setup_raise_exception
(
sigcontext
,
stack
);
return
TRUE
;
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
;
ucontext_t
*
ucontext
=
sigcontext
;
stack
=
(
struct
stack_layout
*
)(
RSP_sig
(
ucontext
)
&
~
15
);
/* check for exceptions on the signal stack caused by write watches */
if
(
TRAP_sig
(
ucontext
)
==
TRAP_x86_PAGEFLT
&&
is_inside_signal_stack
(
stack
)
&&
!
virtual_handle_fault
(
siginfo
->
si_addr
,
(
ERROR_sig
(
ucontext
)
>>
1
)
&
0x09
,
TRUE
))
{
return
;
}
/* check for page fault inside the thread stack */
if
(
TRAP_sig
(
ucontext
)
==
TRAP_x86_PAGEFLT
)
{
switch
(
virtual_handle_stack_fault
(
siginfo
->
si_addr
))
{
case
1
:
/* handled */
return
;
case
-
1
:
/* overflow */
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
goto
done
;
}
}
stack
=
setup_exception
(
sigcontext
);
if
(
stack
->
rec
.
ExceptionCode
==
EXCEPTION_STACK_OVERFLOW
)
goto
done
;
switch
(
TRAP_sig
(
ucontext
))
{
case
TRAP_x86_OFLOW
:
/* Overflow exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
TRAP_x86_BOUND
:
/* Bound range exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
TRAP_x86_PRIVINFLT
:
/* Invalid opcode exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
TRAP_x86_STKFLT
:
/* Stack fault */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_STACK_OVERFLOW
;
break
;
case
TRAP_x86_SEGNPFLT
:
/* Segment not present exception */
case
TRAP_x86_PROTFLT
:
/* General protection fault */
{
WORD
err
=
ERROR_sig
(
ucontext
);
if
(
!
err
&&
(
stack
->
rec
.
ExceptionCode
=
is_privileged_instr
(
&
stack
->
context
)))
break
;
if
((
err
&
7
)
==
2
&&
handle_interrupt
(
ucontext
,
stack
))
return
;
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
0xffffffffffffffff
;
}
break
;
case
TRAP_x86_PAGEFLT
:
/* Page fault */
stack
->
rec
.
NumberParameters
=
2
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
(
ERROR_sig
(
ucontext
)
>>
1
)
&
0x09
;
stack
->
rec
.
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
siginfo
->
si_addr
;
if
(
!
(
stack
->
rec
.
ExceptionCode
=
virtual_handle_fault
((
void
*
)
stack
->
rec
.
ExceptionInformation
[
1
],
stack
->
rec
.
ExceptionInformation
[
0
],
FALSE
)))
return
;
break
;
case
TRAP_x86_ALIGNFLT
:
/* Alignment check exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default
:
ERR
(
"Got unexpected trap %ld
\n
"
,
(
ULONG_PTR
)
TRAP_sig
(
ucontext
)
);
/* fall through */
case
TRAP_x86_NMI
:
/* NMI interrupt */
case
TRAP_x86_DNA
:
/* Device not available exception */
case
TRAP_x86_DOUBLEFLT
:
/* Double fault exception */
case
TRAP_x86_TSSFLT
:
/* Invalid TSS exception */
case
TRAP_x86_MCHK
:
/* Machine check exception */
case
TRAP_x86_CACHEFLT
:
/* Cache flush exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
}
done
:
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static
void
trap_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
)
{
case
TRAP_TRACE
:
/* Single-step exception */
case
4
/* TRAP_HWBKPT */
:
/* Hardware breakpoint exception */
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
case
TRAP_BRKPT
:
/* Breakpoint exception */
#ifdef SI_KERNEL
case
SI_KERNEL
:
#endif
/* Check if this is actually icebp instruction */
if
(((
unsigned
char
*
)
stack
->
rec
.
ExceptionAddress
)[
-
1
]
==
0xF1
)
{
stack
->
rec
.
ExceptionCode
=
EXCEPTION_SINGLE_STEP
;
break
;
}
stack
->
rec
.
ExceptionAddress
=
(
char
*
)
stack
->
rec
.
ExceptionAddress
-
1
;
/* back up over the int3 instruction */
/* fall through */
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_BREAKPOINT
;
stack
->
rec
.
NumberParameters
=
1
;
stack
->
rec
.
ExceptionInformation
[
0
]
=
0
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static
void
fpe_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
switch
(
siginfo
->
si_code
)
{
case
FPE_FLTSUB
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
break
;
case
FPE_INTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_DIVIDE_BY_ZERO
;
break
;
case
FPE_INTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_INT_OVERFLOW
;
break
;
case
FPE_FLTDIV
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_DIVIDE_BY_ZERO
;
break
;
case
FPE_FLTOVF
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_OVERFLOW
;
break
;
case
FPE_FLTUND
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_UNDERFLOW
;
break
;
case
FPE_FLTRES
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INEXACT_RESULT
;
break
;
case
FPE_FLTINV
:
default
:
stack
->
rec
.
ExceptionCode
=
EXCEPTION_FLT_INVALID_OPERATION
;
break
;
}
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* int_handler
*
* Handler for SIGINT.
*/
static
void
int_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
CONTROL_C_EXIT
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* abrt_handler
*
* Handler for SIGABRT.
*/
static
void
abrt_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
sigcontext
)
{
struct
stack_layout
*
stack
=
setup_exception
(
sigcontext
);
stack
->
rec
.
ExceptionCode
=
EXCEPTION_WINE_ASSERTION
;
stack
->
rec
.
ExceptionFlags
=
EH_NONCONTINUABLE
;
setup_raise_exception
(
sigcontext
,
stack
);
}
/**********************************************************************
* quit_handler
*
* Handler for SIGQUIT.
*/
static
void
quit_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
ucontext
)
{
abort_thread
(
0
);
}
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static
void
usr1_handler
(
int
signal
,
siginfo_t
*
siginfo
,
void
*
ucontext
)
{
CONTEXT
context
;
save_context
(
&
context
,
ucontext
);
wait_suspend
(
&
context
);
restore_context
(
&
context
,
ucontext
);
}
/**********************************************************************
* get_thread_ldt_entry
*/
...
...
@@ -641,6 +1382,40 @@ void signal_init_thread( TEB *teb )
}
/**********************************************************************
* signal_init_process
*/
void
signal_init_process
(
void
)
{
struct
sigaction
sig_act
;
sig_act
.
sa_mask
=
server_block_set
;
sig_act
.
sa_flags
=
SA_SIGINFO
|
SA_RESTART
|
SA_ONSTACK
;
sig_act
.
sa_sigaction
=
int_handler
;
if
(
sigaction
(
SIGINT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
fpe_handler
;
if
(
sigaction
(
SIGFPE
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
abrt_handler
;
if
(
sigaction
(
SIGABRT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
quit_handler
;
if
(
sigaction
(
SIGQUIT
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
usr1_handler
;
if
(
sigaction
(
SIGUSR1
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
trap_handler
;
if
(
sigaction
(
SIGTRAP
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
sig_act
.
sa_sigaction
=
segv_handler
;
if
(
sigaction
(
SIGSEGV
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGILL
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
if
(
sigaction
(
SIGBUS
,
&
sig_act
,
NULL
)
==
-
1
)
goto
error
;
return
;
error
:
perror
(
"sigaction"
);
exit
(
1
);
}
/***********************************************************************
* init_thread_context
*/
...
...
@@ -681,6 +1456,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
ctx
=
(
CONTEXT
*
)((
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
0x30
)
-
1
;
init_thread_context
(
ctx
,
entry
,
arg
,
relay
);
}
pthread_sigmask
(
SIG_UNBLOCK
,
&
server_block_set
,
NULL
);
ctx
->
ContextFlags
=
CONTEXT_FULL
;
LdrInitializeThunk
(
ctx
,
(
void
**
)
&
ctx
->
Rcx
,
0
,
0
);
return
ctx
;
...
...
dlls/ntdll/unix/thread.c
View file @
2333099c
...
...
@@ -321,15 +321,6 @@ done:
/***********************************************************************
* start_process
*/
void
CDECL
start_process
(
PRTL_THREAD_START_ROUTINE
entry
,
BOOL
suspend
,
void
*
relay
)
{
signal_start_thread
(
entry
,
NtCurrentTeb
()
->
Peb
,
suspend
,
relay
,
NtCurrentTeb
()
);
}
/***********************************************************************
* abort_thread
*/
void
CDECL
abort_thread
(
int
status
)
...
...
@@ -394,7 +385,7 @@ void wait_suspend( CONTEXT *context )
*
* Send an EXCEPTION_DEBUG_EVENT event to the debugger.
*/
static
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
{
NTSTATUS
ret
;
DWORD
i
;
...
...
dlls/ntdll/unix/unix_private.h
View file @
2333099c
...
...
@@ -68,17 +68,12 @@ extern NTSTATUS CDECL virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsig
extern
void
CDECL
virtual_get_system_info
(
SYSTEM_BASIC_INFORMATION
*
info
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
CDECL
virtual_create_builtin_view
(
void
*
module
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
CDECL
virtual_alloc_thread_stack
(
INITIAL_TEB
*
stack
,
SIZE_T
reserve_size
,
SIZE_T
commit_size
,
SIZE_T
*
pthread_size
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
CDECL
virtual_handle_fault
(
LPCVOID
addr
,
DWORD
err
,
BOOL
on_signal_stack
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
CDECL
virtual_locked_server_call
(
void
*
req_ptr
)
DECLSPEC_HIDDEN
;
extern
ssize_t
CDECL
virtual_locked_read
(
int
fd
,
void
*
addr
,
size_t
size
)
DECLSPEC_HIDDEN
;
extern
ssize_t
CDECL
virtual_locked_pread
(
int
fd
,
void
*
addr
,
size_t
size
,
off_t
offset
)
DECLSPEC_HIDDEN
;
extern
ssize_t
CDECL
virtual_locked_recvmsg
(
int
fd
,
struct
msghdr
*
hdr
,
int
flags
)
DECLSPEC_HIDDEN
;
extern
BOOL
CDECL
virtual_is_valid_code_address
(
const
void
*
addr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
int
CDECL
virtual_handle_stack_fault
(
void
*
addr
)
DECLSPEC_HIDDEN
;
extern
BOOL
CDECL
virtual_check_buffer_for_read
(
const
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
BOOL
CDECL
virtual_check_buffer_for_write
(
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
SIZE_T
CDECL
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
CDECL
virtual_uninterrupted_write_memory
(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_set_force_exec
(
BOOL
enable
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_release_address_space
(
void
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_set_large_address_space
(
void
)
DECLSPEC_HIDDEN
;
...
...
@@ -97,11 +92,10 @@ extern NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned
extern
NTSTATUS
CDECL
server_handle_to_fd
(
HANDLE
handle
,
unsigned
int
access
,
int
*
unix_fd
,
unsigned
int
*
options
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
server_release_fd
(
HANDLE
handle
,
int
unix_fd
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
server_init_process_done
(
void
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
server_init_process_done
(
void
*
relay
)
DECLSPEC_HIDDEN
;
extern
TEB
*
CDECL
init_threading
(
int
*
nb_threads_ptr
,
struct
ldt_copy
**
ldt_copy
,
SIZE_T
*
size
,
BOOL
*
suspend
,
unsigned
int
*
cpus
,
BOOL
*
wow64
,
timeout_t
*
start_time
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
DECLSPEC_NORETURN
start_process
(
PRTL_THREAD_START_ROUTINE
entry
,
BOOL
suspend
,
void
*
relay
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
DECLSPEC_NORETURN
abort_thread
(
int
status
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
DECLSPEC_NORETURN
exit_thread
(
int
status
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
DECLSPEC_NORETURN
exit_process
(
int
status
)
DECLSPEC_HIDDEN
;
...
...
@@ -129,6 +123,7 @@ extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
extern
NTSTATUS
context_to_server
(
context_t
*
to
,
const
CONTEXT
*
from
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
context_from_server
(
CONTEXT
*
to
,
const
context_t
*
from
)
DECLSPEC_HIDDEN
;
extern
void
wait_suspend
(
CONTEXT
*
context
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
set_thread_context
(
HANDLE
handle
,
const
context_t
*
context
,
BOOL
*
self
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
get_thread_context
(
HANDLE
handle
,
context_t
*
context
,
unsigned
int
flags
,
BOOL
*
self
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
server_queue_process_apc
(
HANDLE
process
,
const
apc_call_t
*
call
,
...
...
@@ -141,11 +136,17 @@ extern TEB *virtual_alloc_first_teb(void) DECLSPEC_HIDDEN;
extern
NTSTATUS
virtual_alloc_teb
(
TEB
**
ret_teb
)
DECLSPEC_HIDDEN
;
extern
void
virtual_free_teb
(
TEB
*
teb
)
DECLSPEC_HIDDEN
;
extern
void
virtual_map_user_shared_data
(
void
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
virtual_handle_fault
(
LPCVOID
addr
,
DWORD
err
,
BOOL
on_signal_stack
)
DECLSPEC_HIDDEN
;
extern
BOOL
virtual_is_valid_code_address
(
const
void
*
addr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
int
virtual_handle_stack_fault
(
void
*
addr
)
DECLSPEC_HIDDEN
;
extern
SIZE_T
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
virtual_uninterrupted_write_memory
(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
void
signal_init_threading
(
void
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
signal_alloc_thread
(
TEB
*
teb
)
DECLSPEC_HIDDEN
;
extern
void
signal_free_thread
(
TEB
*
teb
)
DECLSPEC_HIDDEN
;
extern
void
signal_init_thread
(
TEB
*
teb
)
DECLSPEC_HIDDEN
;
extern
void
signal_init_process
(
void
)
DECLSPEC_HIDDEN
;
extern
void
DECLSPEC_NORETURN
signal_start_thread
(
PRTL_THREAD_START_ROUTINE
entry
,
void
*
arg
,
BOOL
suspend
,
void
*
relay
,
TEB
*
teb
)
DECLSPEC_HIDDEN
;
extern
void
DECLSPEC_NORETURN
signal_exit_thread
(
int
status
,
void
(
*
func
)(
int
)
)
DECLSPEC_HIDDEN
;
...
...
dlls/ntdll/unix/virtual.c
View file @
2333099c
...
...
@@ -2780,7 +2780,7 @@ void virtual_map_user_shared_data(void)
/***********************************************************************
* virtual_handle_fault
*/
NTSTATUS
CDECL
virtual_handle_fault
(
LPCVOID
addr
,
DWORD
err
,
BOOL
on_signal_stack
)
NTSTATUS
virtual_handle_fault
(
LPCVOID
addr
,
DWORD
err
,
BOOL
on_signal_stack
)
{
NTSTATUS
ret
=
STATUS_ACCESS_VIOLATION
;
void
*
page
=
ROUND_ADDR
(
addr
,
page_mask
);
...
...
@@ -2947,7 +2947,7 @@ ssize_t CDECL virtual_locked_recvmsg( int fd, struct msghdr *hdr, int flags )
/***********************************************************************
* virtual_is_valid_code_address
*/
BOOL
CDECL
virtual_is_valid_code_address
(
const
void
*
addr
,
SIZE_T
size
)
BOOL
virtual_is_valid_code_address
(
const
void
*
addr
,
SIZE_T
size
)
{
struct
file_view
*
view
;
BOOL
ret
=
FALSE
;
...
...
@@ -2968,7 +2968,7 @@ BOOL CDECL virtual_is_valid_code_address( const void *addr, SIZE_T size )
* Return 1 if safely handled, -1 if handled into the overflow space.
* Called from inside a signal handler.
*/
int
CDECL
virtual_handle_stack_fault
(
void
*
addr
)
int
virtual_handle_stack_fault
(
void
*
addr
)
{
int
ret
=
0
;
...
...
@@ -3076,7 +3076,7 @@ BOOL CDECL virtual_check_buffer_for_write( void *ptr, SIZE_T size )
* permissions are checked before accessing each page, to ensure that no
* exceptions can happen.
*/
SIZE_T
CDECL
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
SIZE_T
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
{
struct
file_view
*
view
;
sigset_t
sigset
;
...
...
@@ -3112,7 +3112,7 @@ SIZE_T CDECL virtual_uninterrupted_read_memory( const void *addr, void *buffer,
* permissions are checked before accessing each page, to ensure that no
* exceptions can happen.
*/
NTSTATUS
CDECL
virtual_uninterrupted_write_memory
(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
)
NTSTATUS
virtual_uninterrupted_write_memory
(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
)
{
BOOL
has_write_watch
=
FALSE
;
sigset_t
sigset
;
...
...
dlls/ntdll/unixlib.h
View file @
2333099c
...
...
@@ -28,7 +28,7 @@ struct ldt_copy;
struct
msghdr
;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 3
2
#define NTDLL_UNIXLIB_VERSION 3
3
struct
unix_funcs
{
...
...
@@ -157,17 +157,12 @@ struct unix_funcs
void
(
CDECL
*
virtual_get_system_info
)(
SYSTEM_BASIC_INFORMATION
*
info
);
NTSTATUS
(
CDECL
*
virtual_create_builtin_view
)(
void
*
module
);
NTSTATUS
(
CDECL
*
virtual_alloc_thread_stack
)(
INITIAL_TEB
*
stack
,
SIZE_T
reserve_size
,
SIZE_T
commit_size
,
SIZE_T
*
pthread_size
);
NTSTATUS
(
CDECL
*
virtual_handle_fault
)(
LPCVOID
addr
,
DWORD
err
,
BOOL
on_signal_stack
);
unsigned
int
(
CDECL
*
virtual_locked_server_call
)(
void
*
req_ptr
);
ssize_t
(
CDECL
*
virtual_locked_read
)(
int
fd
,
void
*
addr
,
size_t
size
);
ssize_t
(
CDECL
*
virtual_locked_pread
)(
int
fd
,
void
*
addr
,
size_t
size
,
off_t
offset
);
ssize_t
(
CDECL
*
virtual_locked_recvmsg
)(
int
fd
,
struct
msghdr
*
hdr
,
int
flags
);
BOOL
(
CDECL
*
virtual_is_valid_code_address
)(
const
void
*
addr
,
SIZE_T
size
);
int
(
CDECL
*
virtual_handle_stack_fault
)(
void
*
addr
);
BOOL
(
CDECL
*
virtual_check_buffer_for_read
)(
const
void
*
ptr
,
SIZE_T
size
);
BOOL
(
CDECL
*
virtual_check_buffer_for_write
)(
void
*
ptr
,
SIZE_T
size
);
SIZE_T
(
CDECL
*
virtual_uninterrupted_read_memory
)(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
);
NTSTATUS
(
CDECL
*
virtual_uninterrupted_write_memory
)(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
);
void
(
CDECL
*
virtual_set_force_exec
)(
BOOL
enable
);
void
(
CDECL
*
virtual_release_address_space
)(
void
);
void
(
CDECL
*
virtual_set_large_address_space
)(
void
);
...
...
@@ -175,7 +170,6 @@ struct unix_funcs
/* thread/process functions */
TEB
*
(
CDECL
*
init_threading
)(
int
*
nb_threads_ptr
,
struct
ldt_copy
**
ldt_copy
,
SIZE_T
*
size
,
BOOL
*
suspend
,
unsigned
int
*
cpus
,
BOOL
*
wow64
,
timeout_t
*
start_time
);
void
(
CDECL
*
start_process
)(
PRTL_THREAD_START_ROUTINE
entry
,
BOOL
suspend
,
void
*
relay
);
void
(
CDECL
*
abort_thread
)(
int
status
);
void
(
CDECL
*
exit_thread
)(
int
status
);
void
(
CDECL
*
exit_process
)(
int
status
);
...
...
@@ -196,7 +190,7 @@ struct unix_funcs
NTSTATUS
(
CDECL
*
server_handle_to_fd
)(
HANDLE
handle
,
unsigned
int
access
,
int
*
unix_fd
,
unsigned
int
*
options
);
void
(
CDECL
*
server_release_fd
)(
HANDLE
handle
,
int
unix_fd
);
void
(
CDECL
*
server_init_process_done
)(
void
);
void
(
CDECL
*
server_init_process_done
)(
void
*
relay
);
/* debugging functions */
unsigned
char
(
CDECL
*
dbg_get_channel_flags
)(
struct
__wine_debug_channel
*
channel
);
...
...
dlls/ntdll/virtual.c
View file @
2333099c
...
...
@@ -31,47 +31,19 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#ifdef HAVE_SYS_SYSINFO_H
# include <sys/sysinfo.h>
#endif
#ifdef HAVE_VALGRIND_VALGRIND_H
# include <valgrind/valgrind.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
#include "windef.h"
#include "winternl.h"
#include "wine/library.h"
#include "wine/server.h"
#include "wine/exception.h"
#include "wine/rbtree.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
virtual
);
static
const
UINT
page_shift
=
12
;
static
const
UINT_PTR
page_mask
=
0xfff
;
SIZE_T
signal_stack_size
=
0
;
SIZE_T
signal_stack_mask
=
0
;
static
SIZE_T
signal_stack_align
;
#define ROUND_SIZE(addr,size) \
(((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
/**********************************************************************
* RtlCreateUserStack (NTDLL.@)
...
...
@@ -112,20 +84,6 @@ void WINAPI RtlFreeUserStack( void *stack )
}
/***********************************************************************
* virtual_init
*/
void
virtual_init
(
void
)
{
size_t
size
=
ROUND_SIZE
(
0
,
sizeof
(
TEB
)
)
+
max
(
MINSIGSTKSZ
,
8192
);
/* find the first power of two not smaller than size */
signal_stack_align
=
page_shift
;
while
((
1u
<<
signal_stack_align
)
<
size
)
signal_stack_align
++
;
signal_stack_mask
=
(
1
<<
signal_stack_align
)
-
1
;
signal_stack_size
=
(
1
<<
signal_stack_align
)
-
ROUND_SIZE
(
0
,
sizeof
(
TEB
)
);
}
/***********************************************************************
* __wine_locked_recvmsg
*/
ssize_t
CDECL
__wine_locked_recvmsg
(
int
fd
,
struct
msghdr
*
hdr
,
int
flags
)
...
...
@@ -162,7 +120,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
NTSTATUS
WINAPI
DECLSPEC_HOTPATCH
NtProtectVirtualMemory
(
HANDLE
process
,
PVOID
*
addr_ptr
,
SIZE_T
*
size_ptr
,
ULONG
new_prot
,
ULONG
*
old_prot
)
{
return
unix_funcs
->
NtProtectVirtualMemory
(
process
,
addr_ptr
,
size_ptr
,
new_prot
,
old_prot
);
return
unix_funcs
->
NtProtectVirtualMemory
(
process
,
addr_ptr
,
size_ptr
,
new_prot
,
old_prot
);
}
...
...
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