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
1d4747c3
Commit
1d4747c3
authored
May 20, 2009
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add support for some function epilogs in RtlVirtualUnwind.
parent
fb819d64
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
141 additions
and
1 deletion
+141
-1
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+131
-1
exception.c
dlls/ntdll/tests/exception.c
+10
-0
No files found.
dlls/ntdll/signal_x86_64.c
View file @
1d4747c3
...
...
@@ -1060,6 +1060,131 @@ static int get_opcode_size( struct opcode op )
}
}
static
BOOL
is_inside_epilog
(
BYTE
*
pc
)
{
/* add or lea must be the first instruction, and it must have a rex.W prefix */
if
((
pc
[
0
]
&
0xf8
)
==
0x48
)
{
switch
(
pc
[
1
])
{
case
0x81
:
/* add $nnnn,%rsp */
if
(
pc
[
0
]
==
0x48
&&
pc
[
2
]
==
0xc4
)
{
pc
+=
7
;
break
;
}
return
FALSE
;
case
0x83
:
/* add $n,%rsp */
if
(
pc
[
0
]
==
0x48
&&
pc
[
2
]
==
0xc4
)
{
pc
+=
4
;
break
;
}
return
FALSE
;
case
0x8d
:
/* lea n(reg),%rsp */
if
(
pc
[
0
]
&
0x06
)
return
FALSE
;
/* rex.RX must be cleared */
if
(((
pc
[
2
]
>>
3
)
&
7
)
!=
4
)
return
FALSE
;
/* dest reg mus be %rsp */
if
((
pc
[
2
]
&
7
)
==
4
)
return
FALSE
;
/* no SIB byte allowed */
if
((
pc
[
2
]
>>
6
)
==
1
)
/* 8-bit offset */
{
pc
+=
4
;
break
;
}
if
((
pc
[
2
]
>>
6
)
==
2
)
/* 32-bit offset */
{
pc
+=
7
;
break
;
}
return
FALSE
;
}
}
/* now check for various pop instructions */
for
(;;)
{
BYTE
rex
=
0
;
if
((
*
pc
&
0xf0
)
==
0x40
)
rex
=
*
pc
++
&
0x0f
;
/* rex prefix */
switch
(
*
pc
)
{
case
0x58
:
/* pop %rax/%r8 */
case
0x59
:
/* pop %rcx/%r9 */
case
0x5a
:
/* pop %rdx/%r10 */
case
0x5b
:
/* pop %rbx/%r11 */
case
0x5c
:
/* pop %rsp/%r12 */
case
0x5d
:
/* pop %rbp/%r13 */
case
0x5e
:
/* pop %rsi/%r14 */
case
0x5f
:
/* pop %rdi/%r15 */
pc
++
;
continue
;
case
0xc2
:
/* ret $nn */
case
0xc3
:
/* ret */
return
TRUE
;
/* FIXME: add various jump instructions */
}
return
FALSE
;
}
}
/* execute a function epilog, which must have been validated with is_inside_epilog() */
static
void
interpret_epilog
(
BYTE
*
pc
,
CONTEXT
*
context
,
KNONVOLATILE_CONTEXT_POINTERS
*
ctx_ptr
)
{
for
(;;)
{
BYTE
rex
=
0
;
if
((
*
pc
&
0xf0
)
==
0x40
)
rex
=
*
pc
++
&
0x0f
;
/* rex prefix */
switch
(
*
pc
)
{
case
0x58
:
/* pop %rax/r8 */
case
0x59
:
/* pop %rcx/r9 */
case
0x5a
:
/* pop %rdx/r10 */
case
0x5b
:
/* pop %rbx/r11 */
case
0x5c
:
/* pop %rsp/r12 */
case
0x5d
:
/* pop %rbp/r13 */
case
0x5e
:
/* pop %rsi/r14 */
case
0x5f
:
/* pop %rdi/r15 */
set_int_reg
(
context
,
ctx_ptr
,
*
pc
-
0x58
+
(
rex
&
1
)
*
8
,
*
(
ULONG64
*
)
context
->
Rsp
);
context
->
Rsp
+=
sizeof
(
ULONG64
);
pc
++
;
continue
;
case
0x81
:
/* add $nnnn,%rsp */
context
->
Rsp
+=
*
(
LONG
*
)(
pc
+
2
);
pc
+=
2
+
sizeof
(
LONG
);
continue
;
case
0x83
:
/* add $n,%rsp */
context
->
Rsp
+=
(
signed
char
)
pc
[
2
];
pc
+=
3
;
continue
;
case
0x8d
:
if
((
pc
[
1
]
>>
6
)
==
1
)
/* lea n(reg),%rsp */
{
context
->
Rsp
=
get_int_reg
(
context
,
(
pc
[
1
]
&
7
)
+
(
rex
&
1
)
*
8
)
+
(
signed
char
)
pc
[
2
];
pc
+=
3
;
}
else
/* lea nnnn(reg),%rsp */
{
context
->
Rsp
=
get_int_reg
(
context
,
(
pc
[
1
]
&
7
)
+
(
rex
&
1
)
*
8
)
+
*
(
LONG
*
)(
pc
+
2
);
pc
+=
2
+
sizeof
(
LONG
);
}
continue
;
case
0xc2
:
/* ret $nn */
context
->
Rip
=
*
(
ULONG64
*
)
context
->
Rsp
;
context
->
Rsp
+=
sizeof
(
ULONG64
)
+
*
(
WORD
*
)(
pc
+
1
);
return
;
case
0xc3
:
/* ret */
context
->
Rip
=
*
(
ULONG64
*
)
context
->
Rsp
;
context
->
Rsp
+=
sizeof
(
ULONG64
);
return
;
/* FIXME: add various jump instructions */
}
return
;
}
}
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
...
...
@@ -1100,7 +1225,12 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
else
{
prolog_offset
=
~
0
;
/* FIXME: check for function epilog */
if
(
is_inside_epilog
(
(
BYTE
*
)
pc
))
{
interpret_epilog
(
(
BYTE
*
)
pc
,
context
,
ctx_ptr
);
*
frame_ret
=
frame
;
return
NULL
;
}
}
for
(
i
=
0
;
i
<
info
->
count
;
i
+=
get_opcode_size
(
info
->
opcodes
[
i
]))
...
...
dlls/ntdll/tests/exception.c
View file @
1d4747c3
...
...
@@ -1116,6 +1116,9 @@ static void test_virtual_unwind(void)
{
0x1c
,
0x40
,
TRUE
,
0x128
,
{
{
rsp
,
0x130
},
{
rbp
,
0x120
},
{
rbx
,
0x130
},
{
rsi
,
0x138
},
{
-
1
,
-
1
}}},
{
0x1d
,
0x40
,
TRUE
,
0x128
,
{
{
rsp
,
0x130
},
{
rbp
,
0x120
},
{
rbx
,
0x130
},
{
rsi
,
0x138
},
{
-
1
,
-
1
}}},
{
0x24
,
0x40
,
TRUE
,
0x128
,
{
{
rsp
,
0x130
},
{
rbp
,
0x120
},
{
rbx
,
0x130
},
{
rsi
,
0x138
},
{
-
1
,
-
1
}}},
{
0x2b
,
0x40
,
FALSE
,
0x128
,
{
{
rsp
,
0x130
},
{
rbp
,
0x120
},
{
-
1
,
-
1
}}},
{
0x32
,
0x40
,
FALSE
,
0x008
,
{
{
rsp
,
0x010
},
{
rbp
,
0x000
},
{
-
1
,
-
1
}}},
{
0x33
,
0x40
,
FALSE
,
0x000
,
{
{
rsp
,
0x008
},
{
-
1
,
-
1
}}},
};
...
...
@@ -1165,6 +1168,13 @@ static void test_virtual_unwind(void)
{
0x04
,
0x50
,
FALSE
,
0x020
,
{
{
rsp
,
0x028
},
{
rbx
,
0x018
},
{
rbp
,
0x010
},
{
rsi
,
0x008
},
{
rdi
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x06
,
0x50
,
FALSE
,
0x028
,
{
{
rsp
,
0x030
},
{
rbx
,
0x020
},
{
rbp
,
0x018
},
{
rsi
,
0x010
},
{
rdi
,
0x008
},
{
r12
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x0a
,
0x50
,
TRUE
,
0x058
,
{
{
rsp
,
0x060
},
{
rbx
,
0x050
},
{
rbp
,
0x048
},
{
rsi
,
0x040
},
{
rdi
,
0x038
},
{
r12
,
0x030
},
{
-
1
,
-
1
}
}},
{
0x0c
,
0x50
,
FALSE
,
0x058
,
{
{
rsp
,
0x060
},
{
rbx
,
0x050
},
{
rbp
,
0x048
},
{
rsi
,
0x040
},
{
rdi
,
0x038
},
{
r12
,
0x030
},
{
-
1
,
-
1
}
}},
{
0x10
,
0x50
,
FALSE
,
0x028
,
{
{
rsp
,
0x030
},
{
rbx
,
0x020
},
{
rbp
,
0x018
},
{
rsi
,
0x010
},
{
rdi
,
0x008
},
{
r12
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x12
,
0x50
,
FALSE
,
0x020
,
{
{
rsp
,
0x028
},
{
rbx
,
0x018
},
{
rbp
,
0x010
},
{
rsi
,
0x008
},
{
rdi
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x13
,
0x50
,
FALSE
,
0x018
,
{
{
rsp
,
0x020
},
{
rbx
,
0x010
},
{
rbp
,
0x008
},
{
rsi
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x14
,
0x50
,
FALSE
,
0x010
,
{
{
rsp
,
0x018
},
{
rbx
,
0x008
},
{
rbp
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x15
,
0x50
,
FALSE
,
0x008
,
{
{
rsp
,
0x010
},
{
rbx
,
0x000
},
{
-
1
,
-
1
}
}},
{
0x16
,
0x50
,
FALSE
,
0x000
,
{
{
rsp
,
0x008
},
{
-
1
,
-
1
}
}},
};
static
const
struct
unwind_test
tests
[]
=
...
...
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