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
498742ff
Commit
498742ff
authored
Jun 27, 2006
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Moved get/set_thread_context implementation to ptrace.c.
parent
f2bfc7b1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
226 additions
and
481 deletions
+226
-481
context_alpha.c
server/context_alpha.c
+5
-21
context_i386.c
server/context_i386.c
+0
-210
context_powerpc.c
server/context_powerpc.c
+5
-21
context_sparc.c
server/context_sparc.c
+3
-21
context_x86_64.c
server/context_x86_64.c
+0
-187
ptrace.c
server/ptrace.c
+213
-18
thread.h
server/thread.h
+0
-3
No files found.
server/context_alpha.c
View file @
498742ff
...
...
@@ -37,6 +37,8 @@
#include "thread.h"
#include "request.h"
#if 0 /* no longer used */
#ifdef HAVE_SYS_USER_H
# include <sys/user.h>
#endif
...
...
@@ -238,6 +240,8 @@ static void set_thread_context( struct thread *thread, unsigned int flags, const
file_set_error();
}
#endif /* 0 */
/* copy a context structure according to the flags */
void
copy_context
(
CONTEXT
*
to
,
const
CONTEXT
*
from
,
unsigned
int
flags
)
{
...
...
@@ -338,27 +342,7 @@ unsigned int get_context_cpu_flag(void)
/* (system regs are the ones we can't access on the client side) */
unsigned
int
get_context_system_regs
(
unsigned
int
flags
)
{
return
flags
&
~
CONTEXT_ALPHA
;
}
/* retrieve the thread context */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
get_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
}
/* set the thread context */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
set_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
return
0
;
/* FIXME: implement client-side handling */
}
#endif
/* __ALPHA__ */
server/context_i386.c
View file @
498742ff
...
...
@@ -24,17 +24,8 @@
#include <assert.h>
#include <errno.h>
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
#include <stdarg.h>
#include <unistd.h>
#ifdef HAVE_SYS_PTRACE_H
# include <sys/ptrace.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#include "windef.h"
...
...
@@ -42,207 +33,6 @@
#include "thread.h"
#include "request.h"
#ifndef PTRACE_PEEKUSER
# ifdef PTRACE_PEEKUSR
/* libc5 uses USR not USER */
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
# else
# define PTRACE_PEEKUSER PT_READ_U
# endif
#endif
#ifndef PTRACE_POKEUSER
# ifdef PTRACE_POKEUSR
/* libc5 uses USR not USER */
# define PTRACE_POKEUSER PTRACE_POKEUSR
# else
# define PTRACE_POKEUSER PT_WRITE_U
# endif
#endif
#ifdef PT_GETDBREGS
#define PTRACE_GETDBREGS PT_GETDBREGS
#endif
#ifdef PT_SETDBREGS
#define PTRACE_SETDBREGS PT_SETDBREGS
#endif
#ifdef linux
#ifdef HAVE_SYS_USER_H
# include <sys/user.h>
#endif
/* debug register offset in struct user */
#define DR_OFFSET(dr) ((int)((((struct user *)0)->u_debugreg) + (dr)))
/* retrieve a debug register */
static
inline
int
get_debug_reg
(
int
pid
,
int
num
,
DWORD
*
data
)
{
int
res
;
errno
=
0
;
res
=
ptrace
(
PTRACE_PEEKUSER
,
pid
,
DR_OFFSET
(
num
),
0
);
if
((
res
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
*
data
=
res
;
return
0
;
}
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
get_debug_reg
(
pid
,
0
,
&
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
1
,
&
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
2
,
&
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
3
,
&
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
6
,
&
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
7
,
&
context
->
Dr7
)
==
-
1
)
goto
error
;
context
->
ContextFlags
|=
CONTEXT_DEBUG_REGISTERS
;
resume_after_ptrace
(
thread
);
return
;
error:
file_set_error
();
resume_after_ptrace
(
thread
);
}
/* set the thread x86 registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
0
),
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr0
=
context
->
Dr0
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
1
),
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr1
=
context
->
Dr1
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
2
),
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr2
=
context
->
Dr2
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
3
),
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr3
=
context
->
Dr3
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
6
),
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr6
=
context
->
Dr6
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
7
),
context
->
Dr7
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr7
=
context
->
Dr7
;
resume_after_ptrace
(
thread
);
return
;
error:
file_set_error
();
resume_after_ptrace
(
thread
);
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <machine/reg.h>
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
#ifdef PTRACE_GETDBREGS
int
pid
=
get_ptrace_pid
(
thread
);
struct
dbreg
dbregs
;
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
ptrace
(
PTRACE_GETDBREGS
,
pid
,
(
caddr_t
)
&
dbregs
,
0
)
==
-
1
)
file_set_error
();
else
{
#ifdef DBREG_DRX
/* needed for FreeBSD, the structure fields have changed under 5.x */
context
->
Dr0
=
DBREG_DRX
((
&
dbregs
),
0
);
context
->
Dr1
=
DBREG_DRX
((
&
dbregs
),
1
);
context
->
Dr2
=
DBREG_DRX
((
&
dbregs
),
2
);
context
->
Dr3
=
DBREG_DRX
((
&
dbregs
),
3
);
context
->
Dr6
=
DBREG_DRX
((
&
dbregs
),
6
);
context
->
Dr7
=
DBREG_DRX
((
&
dbregs
),
7
);
#else
context
->
Dr0
=
dbregs
.
dr0
;
context
->
Dr1
=
dbregs
.
dr1
;
context
->
Dr2
=
dbregs
.
dr2
;
context
->
Dr3
=
dbregs
.
dr3
;
context
->
Dr6
=
dbregs
.
dr6
;
context
->
Dr7
=
dbregs
.
dr7
;
#endif
context
->
ContextFlags
|=
CONTEXT_DEBUG_REGISTERS
;
}
resume_after_ptrace
(
thread
);
#endif
}
/* set the thread x86 registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
#ifdef PTRACE_SETDBREGS
int
pid
=
get_ptrace_pid
(
thread
);
struct
dbreg
dbregs
;
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
#ifdef DBREG_DRX
/* needed for FreeBSD, the structure fields have changed under 5.x */
DBREG_DRX
((
&
dbregs
),
0
)
=
context
->
Dr0
;
DBREG_DRX
((
&
dbregs
),
1
)
=
context
->
Dr1
;
DBREG_DRX
((
&
dbregs
),
2
)
=
context
->
Dr2
;
DBREG_DRX
((
&
dbregs
),
3
)
=
context
->
Dr3
;
DBREG_DRX
((
&
dbregs
),
4
)
=
0
;
DBREG_DRX
((
&
dbregs
),
5
)
=
0
;
DBREG_DRX
((
&
dbregs
),
6
)
=
context
->
Dr6
;
DBREG_DRX
((
&
dbregs
),
7
)
=
context
->
Dr7
;
#else
dbregs
.
dr0
=
context
->
Dr0
;
dbregs
.
dr1
=
context
->
Dr1
;
dbregs
.
dr2
=
context
->
Dr2
;
dbregs
.
dr3
=
context
->
Dr3
;
dbregs
.
dr4
=
0
;
dbregs
.
dr5
=
0
;
dbregs
.
dr6
=
context
->
Dr6
;
dbregs
.
dr7
=
context
->
Dr7
;
#endif
if
(
ptrace
(
PTRACE_SETDBREGS
,
pid
,
(
caddr_t
)
&
dbregs
,
0
)
==
-
1
)
file_set_error
();
else
if
(
thread
->
context
)
/* update the cached values */
{
thread
->
context
->
Dr0
=
context
->
Dr0
;
thread
->
context
->
Dr1
=
context
->
Dr1
;
thread
->
context
->
Dr2
=
context
->
Dr2
;
thread
->
context
->
Dr3
=
context
->
Dr3
;
thread
->
context
->
Dr6
=
context
->
Dr6
;
thread
->
context
->
Dr7
=
context
->
Dr7
;
}
resume_after_ptrace
(
thread
);
#endif
}
#else
/* linux || __FreeBSD__ */
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
}
/* set the thread x86 debug registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
}
#endif
/* linux || __FreeBSD__ */
/* copy a context structure according to the flags */
void
copy_context
(
CONTEXT
*
to
,
const
CONTEXT
*
from
,
unsigned
int
flags
)
{
...
...
server/context_powerpc.c
View file @
498742ff
...
...
@@ -34,6 +34,8 @@
# include <sys/ptrace.h>
#endif
#if 0 /* no longer used */
#ifndef PTRACE_PEEKUSER
# ifdef PT_READ_D
# define PTRACE_PEEKUSER PT_READ_D
...
...
@@ -197,6 +199,8 @@ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags
#undef IREG
#undef FREG
#endif
/* 0 */
#define IREG(x) to->Gpr##x = from->Gpr##x;
#define FREG(x) to->Fpr##x = from->Fpr##x;
#define CREG(x) to->x = from->x;
...
...
@@ -276,27 +280,7 @@ unsigned int get_context_cpu_flag(void)
/* (system regs are the ones we can't access on the client side) */
unsigned
int
get_context_system_regs
(
unsigned
int
flags
)
{
return
flags
;
}
/* retrieve the thread context */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
get_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
}
/* set the thread context */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
set_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
return
0
;
/* FIXME: implement client-side handling */
}
#endif
/* __powerpc__ */
server/context_sparc.c
View file @
498742ff
...
...
@@ -40,6 +40,7 @@
#include "thread.h"
#include "request.h"
#if 0 /* no longer used */
#if defined(__sun) || defined(__sun__)
...
...
@@ -104,6 +105,7 @@ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags
#error You must implement get/set_thread_context_ptrace for your platform
#endif /* __sun__ */
#endif
/* 0 */
/* copy a context structure according to the flags */
void
copy_context
(
CONTEXT
*
to
,
const
CONTEXT
*
from
,
unsigned
int
flags
)
...
...
@@ -176,27 +178,7 @@ unsigned int get_context_cpu_flag(void)
/* (system regs are the ones we can't access on the client side) */
unsigned
int
get_context_system_regs
(
unsigned
int
flags
)
{
return
flags
&
~
CONTEXT_SPARC
;
}
/* retrieve the thread context */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
get_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
}
/* set the thread context */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
set_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
return
0
;
/* FIXME: implement client-side handling */
}
#endif
/* __sparc__ */
server/context_x86_64.c
View file @
498742ff
...
...
@@ -26,12 +26,6 @@
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#ifdef HAVE_SYS_PTRACE_H
# include <sys/ptrace.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#define NONAMELESSUNION
#include "windef.h"
...
...
@@ -41,167 +35,6 @@
#include "thread.h"
#include "request.h"
#ifdef __linux__
#ifdef HAVE_SYS_USER_H
# include <sys/user.h>
#endif
/* debug register offset in struct user */
#define DR_OFFSET(dr) ((unsigned long)((((struct user *)0)->u_debugreg) + (dr)))
/* retrieve a debug register */
static
inline
int
get_debug_reg
(
int
pid
,
int
num
,
DWORD64
*
data
)
{
int
res
;
errno
=
0
;
res
=
ptrace
(
PTRACE_PEEKUSER
,
pid
,
DR_OFFSET
(
num
),
0
);
if
((
res
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
*
data
=
res
;
return
0
;
}
/* retrieve a thread context */
static
void
get_thread_context_ptrace
(
struct
thread
*
thread
,
unsigned
int
flags
,
CONTEXT
*
context
)
{
int
pid
=
get_ptrace_pid
(
thread
);
if
(
flags
&
CONTEXT_FULL
)
{
struct
user_regs_struct
regs
;
if
(
ptrace
(
PTRACE_GETREGS
,
pid
,
0
,
&
regs
)
==
-
1
)
goto
error
;
if
(
flags
&
CONTEXT_INTEGER
)
{
context
->
Rax
=
regs
.
rax
;
context
->
Rbx
=
regs
.
rbx
;
context
->
Rcx
=
regs
.
rcx
;
context
->
Rdx
=
regs
.
rdx
;
context
->
Rsi
=
regs
.
rsi
;
context
->
Rdi
=
regs
.
rdi
;
context
->
R8
=
regs
.
r8
;
context
->
R9
=
regs
.
r9
;
context
->
R10
=
regs
.
r10
;
context
->
R11
=
regs
.
r11
;
context
->
R12
=
regs
.
r12
;
context
->
R13
=
regs
.
r13
;
context
->
R14
=
regs
.
r14
;
context
->
R15
=
regs
.
r15
;
}
if
(
flags
&
CONTEXT_CONTROL
)
{
context
->
Rbp
=
regs
.
rbp
;
context
->
Rsp
=
regs
.
rsp
;
context
->
Rip
=
regs
.
rip
;
context
->
SegCs
=
regs
.
cs
;
context
->
SegSs
=
regs
.
ss
;
context
->
EFlags
=
regs
.
eflags
;
}
if
(
flags
&
CONTEXT_SEGMENTS
)
{
context
->
SegDs
=
regs
.
ds
;
context
->
SegEs
=
regs
.
es
;
context
->
SegFs
=
regs
.
fs
;
context
->
SegGs
=
regs
.
gs
;
}
context
->
ContextFlags
|=
flags
&
CONTEXT_FULL
;
}
if
(
flags
&
CONTEXT_DEBUG_REGISTERS
)
{
if
(
get_debug_reg
(
pid
,
0
,
&
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
1
,
&
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
2
,
&
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
3
,
&
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
6
,
&
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
7
,
&
context
->
Dr7
)
==
-
1
)
goto
error
;
context
->
ContextFlags
|=
CONTEXT_DEBUG_REGISTERS
;
}
if
(
flags
&
CONTEXT_FLOATING_POINT
)
{
/* we can use context->FloatSave directly as it is using the */
/* correct structure (the same as fsave/frstor) */
if
(
ptrace
(
PTRACE_GETFPREGS
,
pid
,
0
,
&
context
->
u
.
FltSave
)
==
-
1
)
goto
error
;
context
->
ContextFlags
|=
CONTEXT_FLOATING_POINT
;
}
return
;
error:
file_set_error
();
}
/* set a thread context */
static
void
set_thread_context_ptrace
(
struct
thread
*
thread
,
unsigned
int
flags
,
const
CONTEXT
*
context
)
{
int
pid
=
get_ptrace_pid
(
thread
);
if
(
flags
&
CONTEXT_FULL
)
{
struct
user_regs_struct
regs
;
/* need to preserve some registers (at a minimum orig_eax must always be preserved) */
if
(
ptrace
(
PTRACE_GETREGS
,
pid
,
0
,
&
regs
)
==
-
1
)
goto
error
;
if
(
flags
&
CONTEXT_INTEGER
)
{
regs
.
rax
=
context
->
Rax
;
regs
.
rbx
=
context
->
Rbx
;
regs
.
rcx
=
context
->
Rcx
;
regs
.
rdx
=
context
->
Rdx
;
regs
.
rsi
=
context
->
Rsi
;
regs
.
rdi
=
context
->
Rdi
;
regs
.
r8
=
context
->
R8
;
regs
.
r9
=
context
->
R9
;
regs
.
r10
=
context
->
R10
;
regs
.
r11
=
context
->
R11
;
regs
.
r12
=
context
->
R12
;
regs
.
r13
=
context
->
R13
;
regs
.
r14
=
context
->
R14
;
regs
.
r15
=
context
->
R15
;
}
if
(
flags
&
CONTEXT_CONTROL
)
{
regs
.
rbp
=
context
->
Rbp
;
regs
.
rip
=
context
->
Rip
;
regs
.
rsp
=
context
->
Rsp
;
regs
.
cs
=
context
->
SegCs
;
regs
.
ss
=
context
->
SegSs
;
regs
.
eflags
=
context
->
EFlags
;
}
if
(
flags
&
CONTEXT_SEGMENTS
)
{
regs
.
ds
=
context
->
SegDs
;
regs
.
es
=
context
->
SegEs
;
regs
.
fs
=
context
->
SegFs
;
regs
.
gs
=
context
->
SegGs
;
}
if
(
ptrace
(
PTRACE_SETREGS
,
pid
,
0
,
&
regs
)
==
-
1
)
goto
error
;
}
if
(
flags
&
CONTEXT_DEBUG_REGISTERS
)
{
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
0
),
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
1
),
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
2
),
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
3
),
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
6
),
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
7
),
context
->
Dr7
)
==
-
1
)
goto
error
;
}
if
(
flags
&
CONTEXT_FLOATING_POINT
)
{
/* we can use context->FloatSave directly as it is using the */
/* correct structure (the same as fsave/frstor) */
if
(
ptrace
(
PTRACE_SETFPREGS
,
pid
,
0
,
&
context
->
u
.
FltSave
)
==
-
1
)
goto
error
;
}
return
;
error:
file_set_error
();
}
#else
/* linux */
#error You must implement get/set_thread_context_ptrace for your platform
#endif
/* linux */
/* copy a context structure according to the flags */
void
copy_context
(
CONTEXT
*
to
,
const
CONTEXT
*
from
,
unsigned
int
flags
)
{
...
...
@@ -268,24 +101,4 @@ unsigned int get_context_system_regs( unsigned int flags )
return
flags
&
(
CONTEXT_DEBUG_REGISTERS
&
~
CONTEXT_AMD64
);
}
/* retrieve the thread context */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
get_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
}
/* set the thread context */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
if
(
suspend_for_ptrace
(
thread
))
{
set_thread_context_ptrace
(
thread
,
flags
,
context
);
resume_after_ptrace
(
thread
);
}
}
#endif
/* __x86_64__ */
server/ptrace.c
View file @
498742ff
...
...
@@ -29,6 +29,12 @@
#ifdef HAVE_SYS_PTRACE_H
# include <sys/ptrace.h>
#endif
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
...
...
@@ -60,6 +66,19 @@
#ifndef PTRACE_POKEDATA
#define PTRACE_POKEDATA PT_WRITE_D
#endif
#ifndef PTRACE_PEEKUSER
#define PTRACE_PEEKUSER PT_READ_U
#endif
#ifndef PTRACE_POKEUSER
#define PTRACE_POKEUSER PT_WRITE_U
#endif
#ifdef PT_GETDBREGS
#define PTRACE_GETDBREGS PT_GETDBREGS
#endif
#ifdef PT_SETDBREGS
#define PTRACE_SETDBREGS PT_SETDBREGS
#endif
#ifndef HAVE_SYS_PTRACE_H
#define PT_CONTINUE 0
...
...
@@ -133,6 +152,13 @@ void sigchld_callback(void)
}
}
/* return the Unix pid to use in ptrace calls for a given thread */
static
int
get_ptrace_pid
(
struct
thread
*
thread
)
{
if
(
thread
->
unix_tid
!=
-
1
)
return
thread
->
unix_tid
;
return
thread
->
unix_pid
;
}
/* wait for a ptraced child to get a certain signal */
static
int
wait4_thread
(
struct
thread
*
thread
,
int
signal
)
{
...
...
@@ -164,13 +190,6 @@ static int wait4_thread( struct thread *thread, int signal )
return
(
thread
->
unix_pid
!=
-
1
);
}
/* return the Unix pid to use in ptrace calls for a given thread */
int
get_ptrace_pid
(
struct
thread
*
thread
)
{
if
(
thread
->
unix_tid
!=
-
1
)
return
thread
->
unix_tid
;
return
thread
->
unix_pid
;
}
/* send a signal to a specific thread */
static
inline
int
tkill
(
int
tgid
,
int
pid
,
int
sig
)
{
...
...
@@ -225,9 +244,19 @@ int send_thread_signal( struct thread *thread, int sig )
return
(
ret
!=
-
1
);
}
/* resume a thread after we have used ptrace on it */
static
void
resume_after_ptrace
(
struct
thread
*
thread
)
{
if
(
thread
->
unix_pid
==
-
1
)
return
;
if
(
ptrace
(
PTRACE_DETACH
,
get_ptrace_pid
(
thread
),
(
caddr_t
)
1
,
0
)
==
-
1
)
{
if
(
errno
==
ESRCH
)
thread
->
unix_pid
=
thread
->
unix_tid
=
-
1
;
/* thread got killed */
}
}
/* suspend a thread to allow using ptrace on it */
/* you must do a resume_after_ptrace when finished with the thread */
int
suspend_for_ptrace
(
struct
thread
*
thread
)
static
int
suspend_for_ptrace
(
struct
thread
*
thread
)
{
/* can't stop a thread while initialisation is in progress */
if
(
thread
->
unix_pid
==
-
1
||
!
is_process_init_done
(
thread
->
process
))
goto
error
;
...
...
@@ -245,16 +274,6 @@ int suspend_for_ptrace( struct thread *thread )
return
0
;
}
/* resume a thread after we have used ptrace on it */
void
resume_after_ptrace
(
struct
thread
*
thread
)
{
if
(
thread
->
unix_pid
==
-
1
)
return
;
if
(
ptrace
(
PTRACE_DETACH
,
get_ptrace_pid
(
thread
),
(
caddr_t
)
1
,
0
)
==
-
1
)
{
if
(
errno
==
ESRCH
)
thread
->
unix_pid
=
thread
->
unix_tid
=
-
1
;
/* thread got killed */
}
}
/* read an int from a thread address space */
static
int
read_thread_int
(
struct
thread
*
thread
,
const
int
*
addr
,
int
*
data
)
{
...
...
@@ -440,3 +459,179 @@ void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
resume_after_ptrace
(
thread
);
}
}
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
#ifdef HAVE_SYS_USER_H
# include <sys/user.h>
#endif
/* debug register offset in struct user */
#define DR_OFFSET(dr) ((int)((((struct user *)0)->u_debugreg) + (dr)))
/* retrieve a debug register */
static
inline
int
get_debug_reg
(
int
pid
,
int
num
,
DWORD
*
data
)
{
int
res
;
errno
=
0
;
res
=
ptrace
(
PTRACE_PEEKUSER
,
pid
,
DR_OFFSET
(
num
),
0
);
if
((
res
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
*
data
=
res
;
return
0
;
}
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
get_debug_reg
(
pid
,
0
,
&
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
1
,
&
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
2
,
&
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
3
,
&
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
6
,
&
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
get_debug_reg
(
pid
,
7
,
&
context
->
Dr7
)
==
-
1
)
goto
error
;
context
->
ContextFlags
|=
CONTEXT_DEBUG_REGISTERS
;
resume_after_ptrace
(
thread
);
return
;
error:
file_set_error
();
resume_after_ptrace
(
thread
);
}
/* set the thread x86 registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
0
),
context
->
Dr0
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr0
=
context
->
Dr0
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
1
),
context
->
Dr1
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr1
=
context
->
Dr1
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
2
),
context
->
Dr2
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr2
=
context
->
Dr2
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
3
),
context
->
Dr3
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr3
=
context
->
Dr3
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
6
),
context
->
Dr6
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr6
=
context
->
Dr6
;
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
DR_OFFSET
(
7
),
context
->
Dr7
)
==
-
1
)
goto
error
;
if
(
thread
->
context
)
thread
->
context
->
Dr7
=
context
->
Dr7
;
resume_after_ptrace
(
thread
);
return
;
error:
file_set_error
();
resume_after_ptrace
(
thread
);
}
#elif defined(__i386__) && defined(PTRACE_GETDBREGS) && defined(PTRACE_SETDBREGS) && \
(defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__))
#include <machine/reg.h>
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
struct
dbreg
dbregs
;
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
if
(
ptrace
(
PTRACE_GETDBREGS
,
pid
,
(
caddr_t
)
&
dbregs
,
0
)
==
-
1
)
file_set_error
();
else
{
#ifdef DBREG_DRX
/* needed for FreeBSD, the structure fields have changed under 5.x */
context
->
Dr0
=
DBREG_DRX
((
&
dbregs
),
0
);
context
->
Dr1
=
DBREG_DRX
((
&
dbregs
),
1
);
context
->
Dr2
=
DBREG_DRX
((
&
dbregs
),
2
);
context
->
Dr3
=
DBREG_DRX
((
&
dbregs
),
3
);
context
->
Dr6
=
DBREG_DRX
((
&
dbregs
),
6
);
context
->
Dr7
=
DBREG_DRX
((
&
dbregs
),
7
);
#else
context
->
Dr0
=
dbregs
.
dr0
;
context
->
Dr1
=
dbregs
.
dr1
;
context
->
Dr2
=
dbregs
.
dr2
;
context
->
Dr3
=
dbregs
.
dr3
;
context
->
Dr6
=
dbregs
.
dr6
;
context
->
Dr7
=
dbregs
.
dr7
;
#endif
context
->
ContextFlags
|=
CONTEXT_DEBUG_REGISTERS
;
}
resume_after_ptrace
(
thread
);
}
/* set the thread x86 registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
int
pid
=
get_ptrace_pid
(
thread
);
struct
dbreg
dbregs
;
/* all other regs are handled on the client side */
assert
(
(
flags
|
CONTEXT_i386
)
==
CONTEXT_DEBUG_REGISTERS
);
if
(
!
suspend_for_ptrace
(
thread
))
return
;
#ifdef DBREG_DRX
/* needed for FreeBSD, the structure fields have changed under 5.x */
DBREG_DRX
((
&
dbregs
),
0
)
=
context
->
Dr0
;
DBREG_DRX
((
&
dbregs
),
1
)
=
context
->
Dr1
;
DBREG_DRX
((
&
dbregs
),
2
)
=
context
->
Dr2
;
DBREG_DRX
((
&
dbregs
),
3
)
=
context
->
Dr3
;
DBREG_DRX
((
&
dbregs
),
4
)
=
0
;
DBREG_DRX
((
&
dbregs
),
5
)
=
0
;
DBREG_DRX
((
&
dbregs
),
6
)
=
context
->
Dr6
;
DBREG_DRX
((
&
dbregs
),
7
)
=
context
->
Dr7
;
#else
dbregs
.
dr0
=
context
->
Dr0
;
dbregs
.
dr1
=
context
->
Dr1
;
dbregs
.
dr2
=
context
->
Dr2
;
dbregs
.
dr3
=
context
->
Dr3
;
dbregs
.
dr4
=
0
;
dbregs
.
dr5
=
0
;
dbregs
.
dr6
=
context
->
Dr6
;
dbregs
.
dr7
=
context
->
Dr7
;
#endif
if
(
ptrace
(
PTRACE_SETDBREGS
,
pid
,
(
caddr_t
)
&
dbregs
,
0
)
==
-
1
)
file_set_error
();
else
if
(
thread
->
context
)
/* update the cached values */
{
thread
->
context
->
Dr0
=
context
->
Dr0
;
thread
->
context
->
Dr1
=
context
->
Dr1
;
thread
->
context
->
Dr2
=
context
->
Dr2
;
thread
->
context
->
Dr3
=
context
->
Dr3
;
thread
->
context
->
Dr6
=
context
->
Dr6
;
thread
->
context
->
Dr7
=
context
->
Dr7
;
}
resume_after_ptrace
(
thread
);
}
#else
/* linux || __FreeBSD__ */
/* retrieve the thread x86 registers */
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
)
{
}
/* set the thread x86 debug registers */
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
)
{
}
#endif
/* linux || __FreeBSD__ */
server/thread.h
View file @
498742ff
...
...
@@ -128,9 +128,6 @@ extern unsigned int get_context_system_regs( unsigned int flags );
/* ptrace functions */
extern
void
sigchld_callback
(
void
);
extern
int
get_ptrace_pid
(
struct
thread
*
thread
);
extern
int
suspend_for_ptrace
(
struct
thread
*
thread
);
extern
void
resume_after_ptrace
(
struct
thread
*
thread
);
extern
void
get_thread_context
(
struct
thread
*
thread
,
CONTEXT
*
context
,
unsigned
int
flags
);
extern
void
set_thread_context
(
struct
thread
*
thread
,
const
CONTEXT
*
context
,
unsigned
int
flags
);
extern
int
send_thread_signal
(
struct
thread
*
thread
,
int
sig
);
...
...
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