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
da9fbef9
Commit
da9fbef9
authored
Jan 16, 2013
by
André Hentschel
Committed by
Alexandre Julliard
Jan 16, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add ARM64 signal handling.
parent
d11e72f9
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
903 additions
and
1 deletion
+903
-1
Makefile.in
dlls/ntdll/Makefile.in
+1
-0
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-1
signal_arm64.c
dlls/ntdll/signal_arm64.c
+901
-0
No files found.
dlls/ntdll/Makefile.in
View file @
da9fbef9
...
...
@@ -38,6 +38,7 @@ C_SRCS = \
serial.c
\
server.c
\
signal_arm.c
\
signal_arm64.c
\
signal_i386.c
\
signal_powerpc.c
\
signal_sparc.c
\
...
...
dlls/ntdll/ntdll.spec
View file @
da9fbef9
...
...
@@ -145,7 +145,7 @@
@ stdcall NtCreateTimer(ptr long ptr long)
@ stub NtCreateToken
# @ stub NtCreateWaitablePort
@ stdcall -arch=win32 NtCurrentTeb()
@ stdcall -arch=win32
,arm64
NtCurrentTeb()
# @ stub NtDebugActiveProcess
# @ stub NtDebugContinue
@ stdcall NtDelayExecution(long ptr)
...
...
dlls/ntdll/signal_arm64.c
0 → 100644
View file @
da9fbef9
/*
* ARM64 signal handling routines
*
* Copyright 2010-2013 André Hentschel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef __aarch64__
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#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
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"
#include "wine/library.h"
#include "wine/exception.h"
#include "ntdll_misc.h"
#include "wine/debug.h"
#include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
seh
);
static
pthread_key_t
teb_key
;
/***********************************************************************
* signal context platform-specific definitions
*/
#ifdef linux
typedef
ucontext_t
SIGCONTEXT
;
/* 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 */
/* Exceptions */
# define FAULT_sig(context) REG_sig(fault_address, context)
#endif
/* linux */
static
const
size_t
teb_size
=
0x2000
;
/* we reserve two pages for the TEB */
static
size_t
signal_stack_size
;
typedef
void
(
WINAPI
*
raise_func
)(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
);
typedef
int
(
*
wine_signal_handler
)(
unsigned
int
sig
);
static
wine_signal_handler
handlers
[
256
];
/***********************************************************************
* dispatch_signal
*/
static
inline
int
dispatch_signal
(
unsigned
int
sig
)
{
if
(
handlers
[
sig
]
==
NULL
)
return
0
;
return
handlers
[
sig
](
sig
);
}
/*******************************************************************
* is_valid_frame
*/
static
inline
BOOL
is_valid_frame
(
void
*
frame
)
{
if
((
ULONG_PTR
)
frame
&
3
)
return
FALSE
;
return
(
frame
>=
NtCurrentTeb
()
->
Tib
.
StackLimit
&&
(
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(n) context->X##n = REGn_sig(n,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
);
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
);
#undef C
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
Sp
=
SP_sig
(
sigcontext
);
/* Stack pointer */
context
->
Pc
=
PC_sig
(
sigcontext
);
/* Program Counter */
context
->
PState
=
PSTATE_sig
(
sigcontext
);
/* Current State Register */
}
/***********************************************************************
* restore_context
*
* Build a sigcontext from the register values.
*/
static
void
restore_context
(
const
CONTEXT
*
context
,
ucontext_t
*
sigcontext
)
{
#define C(n) REGn_sig(n,sigcontext) = context->X##n
/* 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
);
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
);
#undef C
SP_sig
(
sigcontext
)
=
context
->
Sp
;
/* Stack pointer */
PC_sig
(
sigcontext
)
=
context
->
Pc
;
/* Program Counter */
PSTATE_sig
(
sigcontext
)
=
context
->
PState
;
/* Current State Register */
}
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
static
inline
void
save_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"Not implemented on ARM64
\n
"
);
}
/***********************************************************************
* restore_fpu
*
* Restore the FPU context to a sigcontext.
*/
static
inline
void
restore_fpu
(
CONTEXT
*
context
,
const
ucontext_t
*
sigcontext
)
{
FIXME
(
"Not implemented on ARM64
\n
"
);
}
/***********************************************************************
* RtlCaptureContext (NTDLL.@)
*/
void
WINAPI
RtlCaptureContext
(
CONTEXT
*
context
)
{
FIXME
(
"Not implemented on ARM64
\n
"
);
memset
(
context
,
0
,
sizeof
(
*
context
)
);
}
/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
*/
void
set_cpu_context
(
const
CONTEXT
*
context
)
{
FIXME
(
"Not implemented on ARM64
\n
"
);
}
/***********************************************************************
* copy_context
*
* Copy a register context according to the flags.
*/
void
copy_context
(
CONTEXT
*
to
,
const
CONTEXT
*
from
,
DWORD
flags
)
{
flags
&=
~
CONTEXT_ARM64
;
/* get rid of CPU id */
if
(
flags
&
CONTEXT_CONTROL
)
{
to
->
Sp
=
from
->
Sp
;
to
->
Pc
=
from
->
Pc
;
to
->
PState
=
from
->
PState
;
}
if
(
flags
&
CONTEXT_INTEGER
)
{
#define C(n) to->X##n = from->X##n
/* 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
);
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
);
#undef C
}
}
/***********************************************************************
* context_to_server
*
* Convert a register context to the server format.
*/
NTSTATUS
context_to_server
(
context_t
*
to
,
const
CONTEXT
*
from
)
{
DWORD
flags
=
from
->
ContextFlags
&
~
CONTEXT_ARM64
;
/* get rid of CPU id */
memset
(
to
,
0
,
sizeof
(
*
to
)
);
to
->
cpu
=
CPU_ARM64
;
if
(
flags
&
CONTEXT_CONTROL
)
{
to
->
flags
|=
SERVER_CTX_CONTROL
;
to
->
ctl
.
arm64_regs
.
sp
=
from
->
Sp
;
to
->
ctl
.
arm64_regs
.
pc
=
from
->
Pc
;
to
->
ctl
.
arm64_regs
.
pstate
=
from
->
PState
;
}
if
(
flags
&
CONTEXT_INTEGER
)
{
to
->
flags
|=
SERVER_CTX_INTEGER
;
#define C(n) to->integer.arm64_regs.x[n] = from->X##n
/* 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
);
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
);
#undef C
}
return
STATUS_SUCCESS
;
}
/***********************************************************************
* context_from_server
*
* Convert a register context from the server format.
*/
NTSTATUS
context_from_server
(
CONTEXT
*
to
,
const
context_t
*
from
)
{
if
(
from
->
cpu
!=
CPU_ARM64
)
return
STATUS_INVALID_PARAMETER
;
to
->
ContextFlags
=
CONTEXT_ARM64
;
if
(
from
->
flags
&
SERVER_CTX_CONTROL
)
{
to
->
ContextFlags
|=
CONTEXT_CONTROL
;
to
->
Sp
=
from
->
ctl
.
arm64_regs
.
sp
;
to
->
Pc
=
from
->
ctl
.
arm64_regs
.
pc
;
to
->
PState
=
from
->
ctl
.
arm64_regs
.
pstate
;
}
if
(
from
->
flags
&
SERVER_CTX_INTEGER
)
{
to
->
ContextFlags
|=
CONTEXT_INTEGER
;
#define C(n) to->X##n = from->integer.arm64_regs.x[n]
/* 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
);
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
);
#undef C
}
return
STATUS_SUCCESS
;
}
/***********************************************************************
* setup_exception_record
*
* Setup the exception record and context on the thread stack.
*/
static
EXCEPTION_RECORD
*
setup_exception
(
SIGCONTEXT
*
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
)
=
(
ULONG_PTR
)
stack
;
PC_sig
(
sigcontext
)
=
(
ULONG_PTR
)
func
;
REGn_sig
(
0
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
rec
;
/* first arg for raise_func */
REGn_sig
(
1
,
sigcontext
)
=
(
ULONG_PTR
)
&
stack
->
context
;
/* second arg for raise_func */
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
]
)))
goto
done
;
}
break
;
}
status
=
NtRaiseException
(
rec
,
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
rec
);
done:
set_cpu_context
(
context
);
}
/**********************************************************************
* call_stack_handlers
*
* Call the stack handlers chain.
*/
static
NTSTATUS
call_stack_handlers
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
EXCEPTION_REGISTRATION_RECORD
*
frame
,
*
dispatch
,
*
nested_frame
;
DWORD
res
;
frame
=
NtCurrentTeb
()
->
Tib
.
ExceptionList
;
nested_frame
=
NULL
;
while
(
frame
!=
(
EXCEPTION_REGISTRATION_RECORD
*
)
~
0UL
)
{
/* Check frame address */
if
(
!
is_valid_frame
(
frame
))
{
rec
->
ExceptionFlags
|=
EH_STACK_INVALID
;
break
;
}
/* Call handler */
TRACE
(
"calling handler at %p code=%x flags=%x
\n
"
,
frame
->
Handler
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
);
res
=
frame
->
Handler
(
rec
,
frame
,
context
,
&
dispatch
);
TRACE
(
"handler at %p returned %x
\n
"
,
frame
->
Handler
,
res
);
if
(
frame
==
nested_frame
)
{
/* no longer nested */
nested_frame
=
NULL
;
rec
->
ExceptionFlags
&=
~
EH_NESTED_CALL
;
}
switch
(
res
)
{
case
ExceptionContinueExecution
:
if
(
!
(
rec
->
ExceptionFlags
&
EH_NONCONTINUABLE
))
return
STATUS_SUCCESS
;
return
STATUS_NONCONTINUABLE_EXCEPTION
;
case
ExceptionContinueSearch
:
break
;
case
ExceptionNestedException
:
if
(
nested_frame
<
dispatch
)
nested_frame
=
dispatch
;
rec
->
ExceptionFlags
|=
EH_NESTED_CALL
;
break
;
default:
return
STATUS_INVALID_DISPOSITION
;
}
frame
=
frame
->
Prev
;
}
return
STATUS_UNHANDLED_EXCEPTION
;
}
/*******************************************************************
* raise_exception
*
* Implementation of NtRaiseException.
*/
static
NTSTATUS
raise_exception
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
{
NTSTATUS
status
;
if
(
first_chance
)
{
DWORD
c
;
for
(
c
=
0
;
c
<
rec
->
NumberParameters
;
c
++
)
TRACE
(
" info[%d]=%016lx
\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
;
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static
void
segv_handler
(
int
signal
,
siginfo_t
*
info
,
void
*
ucontext
)
{
EXCEPTION_RECORD
*
rec
;
SIGCONTEXT
*
context
=
ucontext
;
/* check for page fault inside the thread stack */
if
(
signal
==
SIGSEGV
&&
(
char
*
)
info
->
si_addr
>=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
&&
(
char
*
)
info
->
si_addr
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
&&
virtual_handle_stack_fault
(
info
->
si_addr
))
{
/* check if this was the last guard page */
if
((
char
*
)
info
->
si_addr
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
2
*
4096
)
{
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
(
signal
)
{
case
SIGILL
:
/* Invalid opcode exception */
rec
->
ExceptionCode
=
EXCEPTION_ILLEGAL_INSTRUCTION
;
break
;
case
SIGSEGV
:
/* Segmentation fault */
rec
->
ExceptionCode
=
EXCEPTION_ACCESS_VIOLATION
;
rec
->
NumberParameters
=
2
;
/* FIXME: Currently the kernel provides no way to determine if it's read or write */
rec
->
ExceptionInformation
[
0
]
=
0
;
rec
->
ExceptionInformation
[
1
]
=
(
ULONG_PTR
)
info
->
si_addr
;
break
;
case
SIGBUS
:
/* Alignment check exception */
rec
->
ExceptionCode
=
EXCEPTION_DATATYPE_MISALIGNMENT
;
break
;
default:
ERR
(
"Got unexpected signal %i
\n
"
,
signal
);
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
)
{
if
(
!
dispatch_signal
(
SIGINT
))
{
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
)
{
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
);
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int
CDECL
__wine_set_signal_handler
(
unsigned
int
sig
,
wine_signal_handler
wsh
)
{
if
(
sig
>
sizeof
(
handlers
)
/
sizeof
(
handlers
[
0
]))
return
-
1
;
if
(
handlers
[
sig
]
!=
NULL
)
return
-
2
;
handlers
[
sig
]
=
wsh
;
return
0
;
}
/**********************************************************************
* signal_alloc_thread
*/
NTSTATUS
signal_alloc_thread
(
TEB
**
teb
)
{
static
size_t
sigstack_zero_bits
;
SIZE_T
size
;
NTSTATUS
status
;
if
(
!
sigstack_zero_bits
)
{
size_t
min_size
=
teb_size
+
max
(
MINSIGSTKSZ
,
8192
);
/* find the first power of two not smaller than min_size */
sigstack_zero_bits
=
12
;
while
((
1u
<<
sigstack_zero_bits
)
<
min_size
)
sigstack_zero_bits
++
;
signal_stack_size
=
(
1
<<
sigstack_zero_bits
)
-
teb_size
;
assert
(
sizeof
(
TEB
)
<=
teb_size
);
}
size
=
1
<<
sigstack_zero_bits
;
*
teb
=
NULL
;
if
(
!
(
status
=
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
teb
,
sigstack_zero_bits
,
&
size
,
MEM_COMMIT
|
MEM_TOP_DOWN
,
PAGE_READWRITE
)))
{
(
*
teb
)
->
Tib
.
Self
=
&
(
*
teb
)
->
Tib
;
(
*
teb
)
->
Tib
.
ExceptionList
=
(
void
*
)
~
0UL
;
}
return
status
;
}
/**********************************************************************
* signal_free_thread
*/
void
signal_free_thread
(
TEB
*
teb
)
{
SIZE_T
size
;
if
(
teb
->
DeallocationStack
)
{
size
=
0
;
NtFreeVirtualMemory
(
GetCurrentProcess
(),
&
teb
->
DeallocationStack
,
&
size
,
MEM_RELEASE
);
}
size
=
0
;
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
teb
,
&
size
,
MEM_RELEASE
);
}
/**********************************************************************
* signal_init_thread
*/
void
signal_init_thread
(
TEB
*
teb
)
{
static
int
init_done
;
if
(
!
init_done
)
{
pthread_key_create
(
&
teb_key
,
NULL
);
init_done
=
1
;
}
pthread_setspecific
(
teb_key
,
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
=
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
);
}
/**********************************************************************
* __wine_enter_vm86 (NTDLL.@)
*/
void
__wine_enter_vm86
(
CONTEXT
*
context
)
{
MESSAGE
(
"vm86 mode not supported on this platform
\n
"
);
}
/***********************************************************************
* RtlUnwind (NTDLL.@)
*/
void
WINAPI
RtlUnwind
(
PVOID
pEndFrame
,
PVOID
targetIp
,
PEXCEPTION_RECORD
pRecord
,
PVOID
retval
)
{
FIXME
(
"Not implemented on ARM64
\n
"
);
}
/*******************************************************************
* NtRaiseException (NTDLL.@)
*/
NTSTATUS
WINAPI
NtRaiseException
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
{
NTSTATUS
status
=
raise_exception
(
rec
,
context
,
first_chance
);
if
(
status
==
STATUS_SUCCESS
)
NtSetContextThread
(
GetCurrentThread
(),
context
);
return
status
;
}
/***********************************************************************
* RtlRaiseException (NTDLL.@)
*/
void
WINAPI
RtlRaiseException
(
EXCEPTION_RECORD
*
rec
)
{
CONTEXT
context
;
NTSTATUS
status
;
RtlCaptureContext
(
&
context
);
rec
->
ExceptionAddress
=
(
LPVOID
)
context
.
Pc
;
status
=
raise_exception
(
rec
,
&
context
,
TRUE
);
if
(
status
)
raise_status
(
status
,
rec
);
}
/*************************************************************************
* RtlCaptureStackBackTrace (NTDLL.@)
*/
USHORT
WINAPI
RtlCaptureStackBackTrace
(
ULONG
skip
,
ULONG
count
,
PVOID
*
buffer
,
ULONG
*
hash
)
{
FIXME
(
"(%d, %d, %p, %p) stub!
\n
"
,
skip
,
count
,
buffer
,
hash
);
return
0
;
}
/***********************************************************************
* call_thread_entry_point
*/
void
call_thread_entry_point
(
LPTHREAD_START_ROUTINE
entry
,
void
*
arg
)
{
__TRY
{
exit_thread
(
entry
(
arg
));
}
__EXCEPT
(
unhandled_exception_filter
)
{
NtTerminateThread
(
GetCurrentThread
(),
GetExceptionCode
()
);
}
__ENDTRY
abort
();
/* should not be reached */
}
/***********************************************************************
* RtlExitUserThread (NTDLL.@)
*/
void
WINAPI
RtlExitUserThread
(
ULONG
status
)
{
exit_thread
(
status
);
}
/***********************************************************************
* abort_thread
*/
void
abort_thread
(
int
status
)
{
terminate_thread
(
status
);
}
/**********************************************************************
* DbgBreakPoint (NTDLL.@)
*/
void
WINAPI
DbgBreakPoint
(
void
)
{
kill
(
getpid
(),
SIGTRAP
);
}
/**********************************************************************
* DbgUserBreakPoint (NTDLL.@)
*/
void
WINAPI
DbgUserBreakPoint
(
void
)
{
kill
(
getpid
(),
SIGTRAP
);
}
/**********************************************************************
* NtCurrentTeb (NTDLL.@)
*/
TEB
*
WINAPI
NtCurrentTeb
(
void
)
{
return
pthread_getspecific
(
teb_key
);
}
#endif
/* __aarch64__ */
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