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
578c1009
Commit
578c1009
authored
Nov 14, 1999
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved ptrace support to ptrace.c. Tried to improve portability.
parent
3b832225
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
192 additions
and
149 deletions
+192
-149
Makefile.in
server/Makefile.in
+1
-0
process.c
server/process.c
+8
-34
ptrace.c
server/ptrace.c
+164
-0
thread.c
server/thread.c
+8
-112
thread.h
server/thread.h
+11
-3
No files found.
server/Makefile.in
View file @
578c1009
...
...
@@ -18,6 +18,7 @@ C_SRCS = \
object.c
\
pipe.c
\
process.c
\
ptrace.c
\
request.c
\
snapshot.c
\
select
.c
\
...
...
server/process.c
View file @
578c1009
...
...
@@ -316,30 +316,6 @@ static void set_process_info( struct process *process,
}
}
/* wrapper for reading an int with ptrace */
static
inline
int
read_word
(
int
pid
,
const
int
*
addr
,
int
*
data
)
{
if
(((
*
data
=
ptrace
(
PT_READ_D
,
pid
,
addr
))
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
return
0
;
}
/* wrapper for writing an int with ptrace */
static
inline
int
write_word
(
int
pid
,
int
*
addr
,
int
data
,
unsigned
int
mask
)
{
int
res
;
if
(
mask
!=
~
0
)
{
if
(
read_word
(
pid
,
addr
,
&
res
)
==
-
1
)
return
-
1
;
data
=
(
data
&
mask
)
|
(
res
&
~
mask
);
}
if
((
res
=
ptrace
(
PT_WRITE_D
,
pid
,
addr
,
data
))
==
-
1
)
file_set_error
();
return
res
;
}
/* read data from a process memory space */
/* len is the total size (in ints), max is the size we can actually store in the output buffer */
/* we read the total size in all cases to check for permissions */
...
...
@@ -347,7 +323,6 @@ static void read_process_memory( struct process *process, const int *addr,
size_t
len
,
size_t
max
,
int
*
dest
)
{
struct
thread
*
thread
=
process
->
thread_list
;
int
pid
=
thread
->
unix_pid
;
if
((
unsigned
int
)
addr
%
sizeof
(
int
))
/* address must be aligned */
{
...
...
@@ -359,7 +334,7 @@ static void read_process_memory( struct process *process, const int *addr,
{
while
(
len
>
0
&&
max
)
{
if
(
read_
word
(
pi
d
,
addr
++
,
dest
++
)
==
-
1
)
goto
done
;
if
(
read_
thread_int
(
threa
d
,
addr
++
,
dest
++
)
==
-
1
)
goto
done
;
max
--
;
len
--
;
}
...
...
@@ -371,9 +346,9 @@ static void read_process_memory( struct process *process, const int *addr,
{
addr
+=
page
;
len
-=
page
;
if
(
read_
word
(
pi
d
,
addr
-
1
,
&
dummy
)
==
-
1
)
goto
done
;
if
(
read_
thread_int
(
threa
d
,
addr
-
1
,
&
dummy
)
==
-
1
)
goto
done
;
}
if
(
len
&&
(
read_
word
(
pi
d
,
addr
+
len
-
1
,
&
dummy
)
==
-
1
))
goto
done
;
if
(
len
&&
(
read_
thread_int
(
threa
d
,
addr
+
len
-
1
,
&
dummy
)
==
-
1
))
goto
done
;
}
}
else
set_error
(
ERROR_ACCESS_DENIED
);
...
...
@@ -389,7 +364,6 @@ static void write_process_memory( struct process *process, int *addr, size_t len
unsigned
int
last_mask
,
const
int
*
src
)
{
struct
thread
*
thread
=
process
->
thread_list
;
int
pid
=
thread
->
unix_pid
;
if
(
!
len
||
((
unsigned
int
)
addr
%
sizeof
(
int
)))
/* address must be aligned */
{
...
...
@@ -402,7 +376,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
/* first word is special */
if
(
len
>
1
)
{
if
(
write_
word
(
pi
d
,
addr
++
,
*
src
++
,
first_mask
)
==
-
1
)
goto
done
;
if
(
write_
thread_int
(
threa
d
,
addr
++
,
*
src
++
,
first_mask
)
==
-
1
)
goto
done
;
len
--
;
max
--
;
}
...
...
@@ -410,7 +384,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
while
(
len
>
1
&&
max
)
{
if
(
write_
word
(
pi
d
,
addr
++
,
*
src
++
,
~
0
)
==
-
1
)
goto
done
;
if
(
write_
thread_int
(
threa
d
,
addr
++
,
*
src
++
,
~
0
)
==
-
1
)
goto
done
;
max
--
;
len
--
;
}
...
...
@@ -418,7 +392,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
if
(
max
)
{
/* last word is special too */
if
(
write_
word
(
pi
d
,
addr
,
*
src
,
last_mask
)
==
-
1
)
goto
done
;
if
(
write_
thread_int
(
threa
d
,
addr
,
*
src
,
last_mask
)
==
-
1
)
goto
done
;
}
else
{
...
...
@@ -428,9 +402,9 @@ static void write_process_memory( struct process *process, int *addr, size_t len
{
addr
+=
page
;
len
-=
page
;
if
(
write_
word
(
pi
d
,
addr
-
1
,
0
,
0
)
==
-
1
)
goto
done
;
if
(
write_
thread_int
(
threa
d
,
addr
-
1
,
0
,
0
)
==
-
1
)
goto
done
;
}
if
(
len
&&
(
write_
word
(
pi
d
,
addr
+
len
-
1
,
0
,
0
)
==
-
1
))
goto
done
;
if
(
len
&&
(
write_
thread_int
(
threa
d
,
addr
+
len
-
1
,
0
,
0
)
==
-
1
))
goto
done
;
}
}
else
set_error
(
ERROR_ACCESS_DENIED
);
...
...
server/ptrace.c
0 → 100644
View file @
578c1009
/*
* Server-side ptrace support
*
* Copyright (C) 1999 Alexandre Julliard
*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <sys/ptrace.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <unistd.h>
#include "process.h"
#include "thread.h"
#ifndef PTRACE_CONT
#define PTRACE_CONT PT_CONTINUE
#endif
#ifndef PTRACE_ATTACH
#define PTRACE_ATTACH PT_ATTACH
#endif
#ifndef PTRACE_DETACH
#define PTRACE_DETACH PT_DETACH
#endif
#ifndef PTRACE_PEEKDATA
#define PTRACE_PEEKDATA PT_READ_D
#endif
#ifndef PTRACE_POKEDATA
#define PTRACE_POKEDATA PT_WRITE_D
#endif
static
const
int
use_ptrace
=
1
;
/* set to 0 to disable ptrace */
/* wait for a ptraced child to get a certain signal */
/* if the signal is 0, we simply check if anything is pending and return at once */
void
wait4_thread
(
struct
thread
*
thread
,
int
signal
)
{
int
status
;
int
pid
;
restart:
pid
=
thread
?
thread
->
unix_pid
:
-
1
;
if
((
pid
=
wait4
(
pid
,
&
status
,
WUNTRACED
|
(
signal
?
0
:
WNOHANG
),
NULL
))
==
-
1
)
{
perror
(
"wait4"
);
return
;
}
if
(
WIFSTOPPED
(
status
))
{
int
sig
=
WSTOPSIG
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d got sig %d
\n
"
,
pid
,
sig
);
switch
(
sig
)
{
case
SIGSTOP
:
/* continue at once if not suspended */
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
break
;
if
(
!
(
thread
->
process
->
suspend
+
thread
->
suspend
))
ptrace
(
PTRACE_CONT
,
pid
,
0
,
sig
);
break
;
default:
/* ignore other signals for now */
ptrace
(
PTRACE_CONT
,
pid
,
0
,
sig
);
break
;
}
if
(
signal
&&
sig
!=
signal
)
goto
restart
;
}
else
if
(
WIFSIGNALED
(
status
))
{
int
exit_code
=
WTERMSIG
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d killed by sig %d
\n
"
,
pid
,
exit_code
);
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
return
;
if
(
thread
->
client
)
remove_client
(
thread
->
client
,
exit_code
);
}
else
if
(
WIFEXITED
(
status
))
{
int
exit_code
=
WEXITSTATUS
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d exited with status %d
\n
"
,
pid
,
exit_code
);
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
return
;
if
(
thread
->
client
)
remove_client
(
thread
->
client
,
exit_code
);
}
else
fprintf
(
stderr
,
"wait4: pid %d unknown status %x
\n
"
,
pid
,
status
);
}
/* attach to a Unix thread */
static
int
attach_thread
(
struct
thread
*
thread
)
{
/* this may fail if the client is already being debugged */
if
(
!
use_ptrace
||
(
ptrace
(
PTRACE_ATTACH
,
thread
->
unix_pid
,
0
,
0
)
==
-
1
))
return
0
;
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: attached to pid %d
\n
"
,
thread
->
unix_pid
);
thread
->
attached
=
1
;
wait4_thread
(
thread
,
SIGSTOP
);
return
1
;
}
/* detach from a Unix thread and kill it */
void
detach_thread
(
struct
thread
*
thread
)
{
if
(
!
thread
->
unix_pid
)
return
;
kill
(
thread
->
unix_pid
,
SIGTERM
);
if
(
thread
->
suspend
+
thread
->
process
->
suspend
)
continue_thread
(
thread
);
if
(
thread
->
attached
)
{
wait4_thread
(
thread
,
SIGTERM
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: detaching from %d
\n
"
,
thread
->
unix_pid
);
ptrace
(
PTRACE_DETACH
,
thread
->
unix_pid
,
0
,
SIGTERM
);
thread
->
attached
=
0
;
}
}
/* stop a thread (at the Unix level) */
void
stop_thread
(
struct
thread
*
thread
)
{
/* can't stop a thread while initialisation is in progress */
if
(
!
thread
->
unix_pid
||
thread
->
process
->
init_event
)
return
;
/* first try to attach to it */
if
(
!
thread
->
attached
)
if
(
attach_thread
(
thread
))
return
;
/* this will have stopped it */
/* attached already, or attach failed -> send a signal */
kill
(
thread
->
unix_pid
,
SIGSTOP
);
if
(
thread
->
attached
)
wait4_thread
(
thread
,
SIGSTOP
);
}
/* make a thread continue (at the Unix level) */
void
continue_thread
(
struct
thread
*
thread
)
{
if
(
!
thread
->
unix_pid
)
return
;
if
(
!
thread
->
attached
)
kill
(
thread
->
unix_pid
,
SIGCONT
);
else
ptrace
(
PTRACE_CONT
,
thread
->
unix_pid
,
0
,
SIGSTOP
);
}
/* read an int from a thread address space */
int
read_thread_int
(
struct
thread
*
thread
,
const
int
*
addr
,
int
*
data
)
{
if
(((
*
data
=
ptrace
(
PTRACE_PEEKDATA
,
thread
->
unix_pid
,
addr
))
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
return
0
;
}
/* write an int to a thread address space */
int
write_thread_int
(
struct
thread
*
thread
,
int
*
addr
,
int
data
,
unsigned
int
mask
)
{
int
res
;
if
(
mask
!=
~
0
)
{
if
(
read_thread_int
(
thread
,
addr
,
&
res
)
==
-
1
)
return
-
1
;
data
=
(
data
&
mask
)
|
(
res
&
~
mask
);
}
if
((
res
=
ptrace
(
PTRACE_POKEDATA
,
thread
->
unix_pid
,
addr
,
data
))
==
-
1
)
file_set_error
();
return
res
;
}
server/thread.c
View file @
578c1009
...
...
@@ -15,10 +15,8 @@
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdarg.h>
...
...
@@ -82,7 +80,6 @@ static const struct object_ops thread_ops =
destroy_thread
};
static
const
int
use_ptrace
=
1
;
/* set to 0 to disable ptrace */
static
struct
thread
*
first_thread
;
/* allocate the buffer for the communication with the client */
...
...
@@ -214,6 +211,14 @@ struct thread *get_thread_from_handle( int handle, unsigned int access )
access
,
&
thread_ops
);
}
/* find a thread from a Unix pid */
struct
thread
*
get_thread_from_pid
(
int
pid
)
{
struct
thread
*
t
=
first_thread
;
while
(
t
&&
(
t
->
unix_pid
!=
pid
))
t
=
t
->
next
;
return
t
;
}
/* set all information about a thread */
static
void
set_thread_info
(
struct
thread
*
thread
,
struct
set_thread_info_request
*
req
)
...
...
@@ -227,115 +232,6 @@ static void set_thread_info( struct thread *thread,
}
}
/* find a thread from a Unix pid */
static
struct
thread
*
get_thread_from_pid
(
int
pid
)
{
struct
thread
*
t
=
first_thread
;
while
(
t
&&
(
t
->
unix_pid
!=
pid
))
t
=
t
->
next
;
return
t
;
}
/* wait for a ptraced child to get a certain signal */
/* if the signal is 0, we simply check if anything is pending and return at once */
void
wait4_thread
(
struct
thread
*
thread
,
int
signal
)
{
int
status
;
int
pid
;
restart:
pid
=
thread
?
thread
->
unix_pid
:
-
1
;
if
((
pid
=
wait4
(
pid
,
&
status
,
WUNTRACED
|
(
signal
?
0
:
WNOHANG
),
NULL
))
==
-
1
)
{
perror
(
"wait4"
);
return
;
}
if
(
WIFSTOPPED
(
status
))
{
int
sig
=
WSTOPSIG
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d got sig %d
\n
"
,
pid
,
sig
);
switch
(
sig
)
{
case
SIGSTOP
:
/* continue at once if not suspended */
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
break
;
if
(
!
(
thread
->
process
->
suspend
+
thread
->
suspend
))
ptrace
(
PT_CONTINUE
,
pid
,
0
,
sig
);
break
;
default:
/* ignore other signals for now */
ptrace
(
PT_CONTINUE
,
pid
,
0
,
sig
);
break
;
}
if
(
signal
&&
sig
!=
signal
)
goto
restart
;
}
else
if
(
WIFSIGNALED
(
status
))
{
int
exit_code
=
WTERMSIG
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d killed by sig %d
\n
"
,
pid
,
exit_code
);
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
return
;
if
(
thread
->
client
)
remove_client
(
thread
->
client
,
exit_code
);
}
else
if
(
WIFEXITED
(
status
))
{
int
exit_code
=
WEXITSTATUS
(
status
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: pid %d exited with status %d
\n
"
,
pid
,
exit_code
);
if
(
!
thread
)
if
(
!
(
thread
=
get_thread_from_pid
(
pid
)))
return
;
if
(
thread
->
client
)
remove_client
(
thread
->
client
,
exit_code
);
}
else
fprintf
(
stderr
,
"wait4: pid %d unknown status %x
\n
"
,
pid
,
status
);
}
/* attach to a Unix thread */
static
int
attach_thread
(
struct
thread
*
thread
)
{
/* this may fail if the client is already being debugged */
if
(
!
use_ptrace
||
(
ptrace
(
PT_ATTACH
,
thread
->
unix_pid
,
0
,
0
)
==
-
1
))
return
0
;
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: attached to pid %d
\n
"
,
thread
->
unix_pid
);
thread
->
attached
=
1
;
wait4_thread
(
thread
,
SIGSTOP
);
return
1
;
}
/* detach from a Unix thread and kill it */
static
void
detach_thread
(
struct
thread
*
thread
)
{
if
(
!
thread
->
unix_pid
)
return
;
kill
(
thread
->
unix_pid
,
SIGTERM
);
if
(
thread
->
suspend
+
thread
->
process
->
suspend
)
continue_thread
(
thread
);
if
(
thread
->
attached
)
{
wait4_thread
(
thread
,
SIGTERM
);
if
(
debug_level
)
fprintf
(
stderr
,
"ptrace: detaching from %d
\n
"
,
thread
->
unix_pid
);
ptrace
(
PT_DETACH
,
thread
->
unix_pid
,
0
,
SIGTERM
);
thread
->
attached
=
0
;
}
}
/* stop a thread (at the Unix level) */
void
stop_thread
(
struct
thread
*
thread
)
{
/* can't stop a thread while initialisation is in progress */
if
(
!
thread
->
unix_pid
||
thread
->
process
->
init_event
)
return
;
/* first try to attach to it */
if
(
!
thread
->
attached
)
if
(
attach_thread
(
thread
))
return
;
/* this will have stopped it */
/* attached already, or attach failed -> send a signal */
kill
(
thread
->
unix_pid
,
SIGSTOP
);
if
(
thread
->
attached
)
wait4_thread
(
thread
,
SIGSTOP
);
}
/* make a thread continue (at the Unix level) */
void
continue_thread
(
struct
thread
*
thread
)
{
if
(
!
thread
->
unix_pid
)
return
;
if
(
!
thread
->
attached
)
kill
(
thread
->
unix_pid
,
SIGCONT
);
else
ptrace
(
PT_CONTINUE
,
thread
->
unix_pid
,
0
,
SIGSTOP
);
}
/* suspend a thread */
int
suspend_thread
(
struct
thread
*
thread
,
int
check_limit
)
{
...
...
server/thread.h
View file @
578c1009
...
...
@@ -66,9 +66,7 @@ extern struct thread *current;
extern
void
create_initial_thread
(
int
fd
);
extern
struct
thread
*
get_thread_from_id
(
void
*
id
);
extern
struct
thread
*
get_thread_from_handle
(
int
handle
,
unsigned
int
access
);
extern
void
wait4_thread
(
struct
thread
*
thread
,
int
wait
);
extern
void
stop_thread
(
struct
thread
*
thread
);
extern
void
continue_thread
(
struct
thread
*
thread
);
extern
struct
thread
*
get_thread_from_pid
(
int
pid
);
extern
int
suspend_thread
(
struct
thread
*
thread
,
int
check_limit
);
extern
int
resume_thread
(
struct
thread
*
thread
);
extern
void
suspend_all_threads
(
void
);
...
...
@@ -80,6 +78,16 @@ extern void thread_killed( struct thread *thread, int exit_code );
extern
void
thread_timeout
(
void
);
extern
void
wake_up
(
struct
object
*
obj
,
int
max
);
/* ptrace functions */
extern
void
wait4_thread
(
struct
thread
*
thread
,
int
wait
);
extern
void
stop_thread
(
struct
thread
*
thread
);
extern
void
continue_thread
(
struct
thread
*
thread
);
extern
void
detach_thread
(
struct
thread
*
thread
);
extern
int
read_thread_int
(
struct
thread
*
thread
,
const
int
*
addr
,
int
*
data
);
extern
int
write_thread_int
(
struct
thread
*
thread
,
int
*
addr
,
int
data
,
unsigned
int
mask
);
static
inline
int
get_error
(
void
)
{
return
current
->
error
;
}
static
inline
void
set_error
(
int
err
)
{
current
->
error
=
err
;
}
static
inline
void
clear_error
(
void
)
{
set_error
(
0
);
}
...
...
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