Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
0b06d4c4
Commit
0b06d4c4
authored
Jun 19, 2015
by
Sebastian Lackner
Committed by
Alexandre Julliard
Jun 19, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntoskrnl: Add initial code to emulate memory access to USER_SHARED_DATA on x86_64.
parent
c81ff0f8
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
261 additions
and
4 deletions
+261
-4
instr.c
dlls/ntoskrnl.exe/instr.c
+260
-3
ntoskrnl.c
dlls/ntoskrnl.exe/ntoskrnl.c
+1
-1
No files found.
dlls/ntoskrnl.exe/instr.c
View file @
0b06d4c4
...
...
@@ -4,6 +4,7 @@
* Copyright 1995 Alexandre Julliard
* Copyright 2005 Ivan Leo Puoti
* Copyright 2005 Laurent Pinchart
* Copyright 2014-2015 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -23,17 +24,19 @@
#include "config.h"
#include "wine/port.h"
#ifdef __i386__
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#define WIN32_NO_STATUS
#include "ddk/wdm.h"
#include "excpt.h"
#include "wine/debug.h"
#include "wine/exception.h"
#ifdef __i386__
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
#include "pshpack1.h"
...
...
@@ -475,4 +478,258 @@ LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs )
return
EXCEPTION_CONTINUE_SEARCH
;
}
#endif
/* __i386__ */
#elif defined(__x86_64__)
/* __i386__ */
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
#define REX_B 1
#define REX_X 2
#define REX_R 4
#define REX_W 8
#define REGMODRM_MOD( regmodrm, rex ) ((regmodrm) >> 6)
#define REGMODRM_REG( regmodrm, rex ) (((regmodrm) >> 3) & 7) | (((rex) & REX_R) ? 8 : 0)
#define REGMODRM_RM( regmodrm, rex ) (((regmodrm) & 7) | (((rex) & REX_B) ? 8 : 0))
#define SIB_SS( sib, rex ) ((sib) >> 6)
#define SIB_INDEX( sib, rex ) (((sib) >> 3) & 7) | (((rex) & REX_R) ? 8 : 0)
#define SIB_BASE( sib, rex ) (((sib) & 7) | (((rex) & REX_B) ? 8 : 0))
/* keep in sync with dlls/ntdll/thread.c:thread_init */
static
const
BYTE
*
wine_user_shared_data
=
(
BYTE
*
)
0x7ffe0000
;
static
const
BYTE
*
user_shared_data
=
(
BYTE
*
)
0xfffff78000000000
;
static
inline
DWORD64
*
get_int_reg
(
CONTEXT
*
context
,
int
index
)
{
return
&
context
->
Rax
+
index
;
/* index should be in range 0 .. 15 */
}
static
inline
int
get_op_size
(
int
long_op
,
int
rex
)
{
if
(
rex
&
REX_W
)
return
sizeof
(
DWORD64
);
else
if
(
long_op
)
return
sizeof
(
DWORD
);
else
return
sizeof
(
WORD
);
}
/* store an operand into a register */
static
void
store_reg_word
(
CONTEXT
*
context
,
BYTE
regmodrm
,
const
BYTE
*
addr
,
int
long_op
,
int
rex
)
{
int
index
=
REGMODRM_REG
(
regmodrm
,
rex
);
BYTE
*
reg
=
(
BYTE
*
)
get_int_reg
(
context
,
index
);
memcpy
(
reg
,
addr
,
get_op_size
(
long_op
,
rex
)
);
}
/* store an operand into a byte register */
static
void
store_reg_byte
(
CONTEXT
*
context
,
BYTE
regmodrm
,
const
BYTE
*
addr
,
int
rex
)
{
int
index
=
REGMODRM_REG
(
regmodrm
,
rex
);
BYTE
*
reg
=
(
BYTE
*
)
get_int_reg
(
context
,
index
);
if
(
!
rex
&&
index
>=
4
&&
index
<
8
)
reg
-=
(
4
*
sizeof
(
DWORD64
)
-
1
);
/* special case: ah, ch, dh, bh */
*
reg
=
*
addr
;
}
/***********************************************************************
* INSTR_GetOperandAddr
*
* Return the address of an instruction operand (from the mod/rm byte).
*/
static
BYTE
*
INSTR_GetOperandAddr
(
CONTEXT
*
context
,
BYTE
*
instr
,
int
long_addr
,
int
rex
,
int
segprefix
,
int
*
len
)
{
int
mod
,
rm
,
ss
=
0
,
off
,
have_sib
=
0
;
DWORD64
base
=
0
,
index
=
0
;
#define GET_VAL( val, type ) \
{ *val = *(type *)instr; instr += sizeof(type); *len += sizeof(type); }
*
len
=
0
;
GET_VAL
(
&
mod
,
BYTE
);
rm
=
REGMODRM_RM
(
mod
,
rex
);
mod
=
REGMODRM_MOD
(
mod
,
rex
);
if
(
mod
==
3
)
return
(
BYTE
*
)
get_int_reg
(
context
,
rm
);
if
((
rm
&
7
)
==
4
)
{
BYTE
sib
;
int
id
;
GET_VAL
(
&
sib
,
BYTE
);
rm
=
SIB_BASE
(
sib
,
rex
);
id
=
SIB_INDEX
(
sib
,
rex
);
ss
=
SIB_SS
(
sib
,
rex
);
index
=
(
id
!=
4
)
?
*
get_int_reg
(
context
,
id
)
:
0
;
if
(
!
long_addr
)
index
&=
0xffffffff
;
have_sib
=
1
;
}
base
=
*
get_int_reg
(
context
,
rm
);
if
(
!
long_addr
)
base
&=
0xffffffff
;
switch
(
mod
)
{
case
0
:
if
(
rm
==
5
)
/* special case */
{
base
=
have_sib
?
0
:
context
->
Rip
;
if
(
!
long_addr
)
base
&=
0xffffffff
;
GET_VAL
(
&
off
,
DWORD
);
base
+=
(
signed
long
)
off
;
}
break
;
case
1
:
/* 8-bit disp */
GET_VAL
(
&
off
,
BYTE
);
base
+=
(
signed
char
)
off
;
break
;
case
2
:
/* 32-bit disp */
GET_VAL
(
&
off
,
DWORD
);
base
+=
(
signed
long
)
off
;
break
;
}
/* FIXME: we assume that all segments have a base of 0 */
return
(
BYTE
*
)(
base
+
(
index
<<
ss
));
#undef GET_VAL
}
/***********************************************************************
* emulate_instruction
*
* Emulate a privileged instruction.
* Returns exception continuation status.
*/
static
DWORD
emulate_instruction
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
int
prefix
,
segprefix
,
prefixlen
,
len
,
long_op
,
long_addr
,
rex
;
BYTE
*
instr
;
long_op
=
long_addr
=
1
;
instr
=
(
BYTE
*
)
context
->
Rip
;
if
(
!
instr
)
return
ExceptionContinueSearch
;
/* First handle any possible prefix */
segprefix
=
-
1
;
/* no seg prefix */
rex
=
0
;
/* no rex prefix */
prefix
=
1
;
prefixlen
=
0
;
while
(
prefix
)
{
switch
(
*
instr
)
{
case
0x2e
:
segprefix
=
context
->
SegCs
;
break
;
case
0x36
:
segprefix
=
context
->
SegSs
;
break
;
case
0x3e
:
segprefix
=
context
->
SegDs
;
break
;
case
0x26
:
segprefix
=
context
->
SegEs
;
break
;
case
0x64
:
segprefix
=
context
->
SegFs
;
break
;
case
0x65
:
segprefix
=
context
->
SegGs
;
break
;
case
0x66
:
long_op
=
!
long_op
;
/* opcode size prefix */
break
;
case
0x67
:
long_addr
=
!
long_addr
;
/* addr size prefix */
break
;
case
0xf0
:
/* lock */
break
;
case
0xf2
:
/* repne */
break
;
case
0xf3
:
/* repe */
break
;
default:
prefix
=
0
;
/* no more prefixes */
break
;
}
if
(
*
instr
>=
0x40
&&
*
instr
<
0x50
)
/* rex */
{
rex
=
*
instr
;
prefix
=
TRUE
;
}
if
(
prefix
)
{
instr
++
;
prefixlen
++
;
}
}
/* Now look at the actual instruction */
switch
(
*
instr
)
{
case
0x8a
:
/* mov Eb, Gb */
case
0x8b
:
/* mov Ev, Gv */
{
BYTE
*
data
=
INSTR_GetOperandAddr
(
context
,
instr
+
1
,
long_addr
,
rex
,
segprefix
,
&
len
);
unsigned
int
data_size
=
(
*
instr
==
0x8b
)
?
get_op_size
(
long_op
,
rex
)
:
1
;
unsigned
int
offset
=
data
-
user_shared_data
;
if
(
offset
<=
sizeof
(
KSHARED_USER_DATA
)
-
data_size
)
{
switch
(
*
instr
)
{
case
0x8a
:
store_reg_byte
(
context
,
instr
[
1
],
wine_user_shared_data
+
offset
,
rex
);
break
;
case
0x8b
:
store_reg_word
(
context
,
instr
[
1
],
wine_user_shared_data
+
offset
,
long_op
,
rex
);
break
;
}
context
->
Rip
+=
prefixlen
+
len
+
1
;
return
ExceptionContinueExecution
;
}
break
;
/* Unable to emulate it */
}
}
return
ExceptionContinueSearch
;
/* Unable to emulate it */
}
/***********************************************************************
* vectored_handler
*
* Vectored exception handler used to emulate protected instructions
* from 64-bit code.
*/
LONG
CALLBACK
vectored_handler
(
EXCEPTION_POINTERS
*
ptrs
)
{
EXCEPTION_RECORD
*
record
=
ptrs
->
ExceptionRecord
;
CONTEXT
*
context
=
ptrs
->
ContextRecord
;
if
(
record
->
ExceptionCode
==
EXCEPTION_ACCESS_VIOLATION
&&
record
->
ExceptionInformation
[
0
]
==
EXCEPTION_READ_FAULT
)
{
if
(
emulate_instruction
(
record
,
context
)
==
ExceptionContinueExecution
)
{
TRACE
(
"next instruction rip=%lx
\n
"
,
context
->
Rip
);
TRACE
(
" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx
\n
"
,
context
->
Rax
,
context
->
Rbx
,
context
->
Rcx
,
context
->
Rdx
);
TRACE
(
" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx
\n
"
,
context
->
Rsi
,
context
->
Rdi
,
context
->
Rbp
,
context
->
Rsp
);
TRACE
(
" r8=%016lx r9=%016lx r10=%016lx r11=%016lx
\n
"
,
context
->
R8
,
context
->
R9
,
context
->
R10
,
context
->
R11
);
TRACE
(
" r12=%016lx r13=%016lx r14=%016lx r15=%016lx
\n
"
,
context
->
R12
,
context
->
R13
,
context
->
R14
,
context
->
R15
);
return
EXCEPTION_CONTINUE_EXECUTION
;
}
}
return
EXCEPTION_CONTINUE_SEARCH
;
}
#endif
/* __x86_64__ */
dlls/ntoskrnl.exe/ntoskrnl.c
View file @
0b06d4c4
...
...
@@ -2069,7 +2069,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
{
case
DLL_PROCESS_ATTACH
:
DisableThreadLibraryCalls
(
inst
);
#if
def __i386__
#if
defined(__i386__) || defined(__x86_64__)
handler
=
RtlAddVectoredExceptionHandler
(
TRUE
,
vectored_handler
);
#endif
KeQueryTickCount
(
&
count
);
/* initialize the global KeTickCount */
...
...
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