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
ca45eda7
Commit
ca45eda7
authored
Jul 15, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add a helper function to push the exception data to the thread stack.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
9a9fb47e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
78 additions
and
186 deletions
+78
-186
signal_arm.c
dlls/ntdll/unix/signal_arm.c
+5
-10
signal_arm64.c
dlls/ntdll/unix/signal_arm64.c
+7
-11
signal_i386.c
dlls/ntdll/unix/signal_i386.c
+5
-65
signal_x86_64.c
dlls/ntdll/unix/signal_x86_64.c
+5
-75
unix_private.h
dlls/ntdll/unix/unix_private.h
+1
-1
virtual.c
dlls/ntdll/unix/virtual.c
+55
-24
No files found.
dlls/ntdll/unix/signal_arm.c
View file @
ca45eda7
...
...
@@ -531,17 +531,12 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun
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
;
EXCEPTION_RECORD
rec
=
{
0
};
void
*
stack_ptr
=
(
void
*
)(
SP_sig
(
sigcontext
)
&
~
3
);
rec
.
ExceptionAddress
=
(
void
*
)
PC_sig
(
sigcontext
);
stack
=
virtual_setup_exception
(
stack_ptr
,
sizeof
(
*
stack
),
&
rec
);
stack
->
rec
=
rec
;
save_context
(
&
stack
->
context
,
sigcontext
);
/* now modify the sigcontext to return to the raise function */
...
...
dlls/ntdll/unix/signal_arm64.c
View file @
ca45eda7
...
...
@@ -121,8 +121,9 @@ struct stack_layout
{
CONTEXT
context
;
EXCEPTION_RECORD
rec
;
void
*
redzone
[
2
];
void
*
redzone
[
3
];
};
C_ASSERT
(
!
(
sizeof
(
struct
stack_layout
)
%
16
)
);
struct
arm64_thread_data
{
...
...
@@ -540,18 +541,13 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
EXCEPTION_RECORD
rec
=
{
0
};
void
*
stack_ptr
=
(
void
*
)(
SP_sig
(
sigcontext
)
&
~
15
);
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
;
rec
.
ExceptionAddress
=
(
void
*
)
PC_sig
(
sigcontext
);
stack
=
virtual_setup_exception
(
stack_ptr
,
sizeof
(
*
stack
),
&
rec
);
stack
->
rec
=
rec
;
save_context
(
&
stack
->
context
,
sigcontext
);
save_fpu
(
&
stack
->
context
,
sigcontext
);
return
stack
;
...
...
dlls/ntdll/unix/signal_i386.c
View file @
ca45eda7
...
...
@@ -1460,72 +1460,12 @@ static BOOL check_atl_thunk( ucontext_t *sigcontext, struct stack_layout *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
;
EXCEPTION_RECORD
rec
=
{
0
};
struct
stack_layout
*
stack
;
rec
.
ExceptionAddress
=
(
void
*
)
EIP_sig
(
sigcontext
);
stack
=
virtual_setup_exception
(
stack_ptr
,
sizeof
(
*
stack
),
&
rec
);
stack
->
rec
=
rec
;
save_context
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
...
...
dlls/ntdll/unix/signal_x86_64.c
View file @
ca45eda7
...
...
@@ -1378,18 +1378,6 @@ static inline void set_sigcontext( const CONTEXT *context, ucontext_t *sigcontex
/***********************************************************************
* 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.
...
...
@@ -1847,72 +1835,14 @@ __ASM_GLOBAL_FUNC( raise_func_trampoline,
*/
static
struct
stack_layout
*
setup_exception
(
ucontext_t
*
sigcontext
)
{
EXCEPTION_RECORD
rec
=
{
0
};
void
*
stack_ptr
=
(
void
*
)(
RSP_sig
(
sigcontext
)
&
~
15
);
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
;
rec
.
ExceptionAddress
=
(
void
*
)
RIP_sig
(
sigcontext
);
stack
=
virtual_setup_exception
(
stack_ptr
,
sizeof
(
*
stack
),
&
rec
);
stack
->
rec
=
rec
;
save_context
(
&
stack
->
context
,
sigcontext
);
return
stack
;
}
...
...
dlls/ntdll/unix/unix_private.h
View file @
ca45eda7
...
...
@@ -201,7 +201,7 @@ extern unsigned int virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN;
extern
ssize_t
virtual_locked_read
(
int
fd
,
void
*
addr
,
size_t
size
)
DECLSPEC_HIDDEN
;
extern
ssize_t
virtual_locked_pread
(
int
fd
,
void
*
addr
,
size_t
size
,
off_t
offset
)
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
void
*
virtual_setup_exception
(
void
*
stack_ptr
,
size_t
size
,
EXCEPTION_RECORD
*
rec
)
DECLSPEC_HIDDEN
;
extern
BOOL
virtual_check_buffer_for_read
(
const
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
BOOL
virtual_check_buffer_for_write
(
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
SIZE_T
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
...
...
dlls/ntdll/unix/virtual.c
View file @
ca45eda7
...
...
@@ -2913,6 +2913,61 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack )
/***********************************************************************
* virtual_setup_exception
*/
void
*
virtual_setup_exception
(
void
*
stack_ptr
,
size_t
size
,
EXCEPTION_RECORD
*
rec
)
{
char
*
stack
=
stack_ptr
;
if
(
is_inside_signal_stack
(
stack
))
{
ERR
(
"nested exception on signal stack in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
if
(
stack
-
size
>
stack
||
/* check for overflow in subtraction */
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
{
WARN
(
"exception outside of stack limits in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
return
stack
-
size
;
}
stack
-=
size
;
if
(
stack
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
stack
;
ERR
(
"stack overflow %u bytes in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
diff
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
else
if
(
stack
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackLimit
)
{
pthread_mutex_lock
(
&
virtual_mutex
);
/* no need for signal masking inside signal handler */
if
((
get_page_vprot
(
stack
)
&
VPROT_GUARD
)
&&
grow_thread_stack
(
ROUND_ADDR
(
stack
,
page_mask
)))
{
rec
->
ExceptionCode
=
STATUS_STACK_OVERFLOW
;
rec
->
NumberParameters
=
0
;
}
pthread_mutex_unlock
(
&
virtual_mutex
);
}
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED
(
stack
,
size
);
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE
(
stack
,
size
);
#endif
return
stack
;
}
/***********************************************************************
* check_write_access
*
* Check if the memory range is writable, temporarily disabling write watches if necessary.
...
...
@@ -3061,30 +3116,6 @@ BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size )
/***********************************************************************
* virtual_handle_stack_fault
*
* Handle an access fault inside the current thread stack.
* Return 1 if safely handled, -1 if handled into the overflow space.
* Called from inside a signal handler.
*/
int
virtual_handle_stack_fault
(
void
*
addr
)
{
int
ret
=
0
;
if
((
char
*
)
addr
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
)
return
0
;
if
((
char
*
)
addr
>=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
return
0
;
pthread_mutex_lock
(
&
virtual_mutex
);
/* no need for signal masking inside signal handler */
if
(
get_page_vprot
(
addr
)
&
VPROT_GUARD
)
{
ret
=
grow_thread_stack
(
ROUND_ADDR
(
addr
,
page_mask
))
?
-
1
:
1
;
}
pthread_mutex_unlock
(
&
virtual_mutex
);
return
ret
;
}
/***********************************************************************
* virtual_check_buffer_for_read
*
* Check if a memory buffer can be read, triggering page faults if needed for DIB section access.
...
...
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