diff options
Diffstat (limited to 'arch/um/os-Linux/process.c')
-rw-r--r-- | arch/um/os-Linux/process.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c new file mode 100644 index 000000000000..ba9ca1cc790a --- /dev/null +++ b/arch/um/os-Linux/process.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <stdio.h> | ||
8 | #include <errno.h> | ||
9 | #include <signal.h> | ||
10 | #include <linux/unistd.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include <sys/wait.h> | ||
13 | #include "ptrace_user.h" | ||
14 | #include "os.h" | ||
15 | #include "user.h" | ||
16 | #include "user_util.h" | ||
17 | |||
18 | #define ARBITRARY_ADDR -1 | ||
19 | #define FAILURE_PID -1 | ||
20 | |||
21 | #define STAT_PATH_LEN sizeof("/proc/#######/stat\0") | ||
22 | #define COMM_SCANF "%*[^)])" | ||
23 | |||
24 | unsigned long os_process_pc(int pid) | ||
25 | { | ||
26 | char proc_stat[STAT_PATH_LEN], buf[256]; | ||
27 | unsigned long pc; | ||
28 | int fd, err; | ||
29 | |||
30 | sprintf(proc_stat, "/proc/%d/stat", pid); | ||
31 | fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); | ||
32 | if(fd < 0){ | ||
33 | printk("os_process_pc - couldn't open '%s', err = %d\n", | ||
34 | proc_stat, -fd); | ||
35 | return(ARBITRARY_ADDR); | ||
36 | } | ||
37 | err = os_read_file(fd, buf, sizeof(buf)); | ||
38 | if(err < 0){ | ||
39 | printk("os_process_pc - couldn't read '%s', err = %d\n", | ||
40 | proc_stat, -err); | ||
41 | os_close_file(fd); | ||
42 | return(ARBITRARY_ADDR); | ||
43 | } | ||
44 | os_close_file(fd); | ||
45 | pc = ARBITRARY_ADDR; | ||
46 | if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " | ||
47 | "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " | ||
48 | "%*d %*d %*d %*d %*d %lu", &pc) != 1){ | ||
49 | printk("os_process_pc - couldn't find pc in '%s'\n", buf); | ||
50 | } | ||
51 | return(pc); | ||
52 | } | ||
53 | |||
54 | int os_process_parent(int pid) | ||
55 | { | ||
56 | char stat[STAT_PATH_LEN]; | ||
57 | char data[256]; | ||
58 | int parent, n, fd; | ||
59 | |||
60 | if(pid == -1) return(-1); | ||
61 | |||
62 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); | ||
63 | fd = os_open_file(stat, of_read(OPENFLAGS()), 0); | ||
64 | if(fd < 0){ | ||
65 | printk("Couldn't open '%s', err = %d\n", stat, -fd); | ||
66 | return(FAILURE_PID); | ||
67 | } | ||
68 | |||
69 | n = os_read_file(fd, data, sizeof(data)); | ||
70 | os_close_file(fd); | ||
71 | |||
72 | if(n < 0){ | ||
73 | printk("Couldn't read '%s', err = %d\n", stat, -n); | ||
74 | return(FAILURE_PID); | ||
75 | } | ||
76 | |||
77 | parent = FAILURE_PID; | ||
78 | n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); | ||
79 | if(n != 1) | ||
80 | printk("Failed to scan '%s'\n", data); | ||
81 | |||
82 | return(parent); | ||
83 | } | ||
84 | |||
85 | void os_stop_process(int pid) | ||
86 | { | ||
87 | kill(pid, SIGSTOP); | ||
88 | } | ||
89 | |||
90 | void os_kill_process(int pid, int reap_child) | ||
91 | { | ||
92 | kill(pid, SIGKILL); | ||
93 | if(reap_child) | ||
94 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
95 | |||
96 | } | ||
97 | |||
98 | /* Kill off a ptraced child by all means available. kill it normally first, | ||
99 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from | ||
100 | * which it can't exit directly. | ||
101 | */ | ||
102 | |||
103 | void os_kill_ptraced_process(int pid, int reap_child) | ||
104 | { | ||
105 | kill(pid, SIGKILL); | ||
106 | ptrace(PTRACE_KILL, pid); | ||
107 | ptrace(PTRACE_CONT, pid); | ||
108 | if(reap_child) | ||
109 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
110 | } | ||
111 | |||
112 | void os_usr1_process(int pid) | ||
113 | { | ||
114 | kill(pid, SIGUSR1); | ||
115 | } | ||
116 | |||
117 | /*Don't use the glibc version, which caches the result in TLS. It misses some | ||
118 | * syscalls, and also breaks with clone(), which does not unshare the TLS.*/ | ||
119 | inline _syscall0(pid_t, getpid) | ||
120 | |||
121 | int os_getpid(void) | ||
122 | { | ||
123 | return(getpid()); | ||
124 | } | ||
125 | |||
126 | int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, | ||
127 | int r, int w, int x) | ||
128 | { | ||
129 | void *loc; | ||
130 | int prot; | ||
131 | |||
132 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
133 | (x ? PROT_EXEC : 0); | ||
134 | |||
135 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, | ||
136 | fd, off); | ||
137 | if(loc == MAP_FAILED) | ||
138 | return(-errno); | ||
139 | return(0); | ||
140 | } | ||
141 | |||
142 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) | ||
143 | { | ||
144 | int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
145 | (x ? PROT_EXEC : 0)); | ||
146 | |||
147 | if(mprotect(addr, len, prot) < 0) | ||
148 | return(-errno); | ||
149 | return(0); | ||
150 | } | ||
151 | |||
152 | int os_unmap_memory(void *addr, int len) | ||
153 | { | ||
154 | int err; | ||
155 | |||
156 | err = munmap(addr, len); | ||
157 | if(err < 0) | ||
158 | return(-errno); | ||
159 | return(0); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
164 | * Emacs will notice this stuff at the end of the file and automatically | ||
165 | * adjust the settings for this buffer only. This must remain at the end | ||
166 | * of the file. | ||
167 | * --------------------------------------------------------------------------- | ||
168 | * Local variables: | ||
169 | * c-file-style: "linux" | ||
170 | * End: | ||
171 | */ | ||