1 /*	$OpenBSD: process.c,v 1.13 2003/08/18 17:55:57 jfb Exp $	*/
2 /*
3  * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/ptrace.h>
29 #include <sys/wait.h>
30 #include <sys/stat.h>
31 
32 #include <machine/reg.h>
33 
34 #include <err.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 #include "pmdb.h"
43 #include "core.h"
44 #include "symbol.h"
45 #include "break.h"
46 
47 int
process_load(struct pstate * ps)48 process_load(struct pstate *ps)
49 {
50 	if (ps->ps_state == LOADED)
51 		return (0);
52 
53 	if (access(*ps->ps_argv, R_OK|X_OK) < 0) {
54 		fprintf(stderr, "%s: %s.\n", *ps->ps_argv,
55 		    strerror(errno));
56 		return (1);
57 	}
58 
59 	if (stat(ps->ps_argv[0], &(ps->exec_stat)) < 0)
60 		err(1, "stat()");
61 
62 	if ((ps->ps_flags & PSF_SYMBOLS) == 0) {
63 		sym_init_exec(ps, ps->ps_argv[0]);
64 		ps->ps_flags |= PSF_SYMBOLS;
65 	}
66 
67 	ps->ps_state = LOADED;
68 
69 	if (ps->ps_pid != 0) {
70 		/* attach to an already running process */
71 		if (ptrace(PT_ATTACH, ps->ps_pid, (caddr_t) 0, 0) < 0)
72 			err(1, "failed to ptrace process");
73 		ps->ps_state = STOPPED;
74 		ps->ps_flags |= PSF_ATCH;
75 	}
76 
77 	return (0);
78 }
79 
80 
81 int
process_setargv(struct pstate * ps,int argc,char ** argv)82 process_setargv(struct pstate *ps, int argc, char **argv)
83 {
84 	int i;
85 
86 	if (ps->ps_argv != NULL) {
87 		for (i = 0; i < ps->ps_argc; i++)
88 			free(ps->ps_argv[i]);
89 		free(ps->ps_argv);
90 	}
91 
92 	ps->ps_argv = (char **)calloc((argc + 1), sizeof(char *));
93 	if (ps->ps_argv == NULL) {
94 		warn("failed to allocate argument vector");
95 		return (-1);
96 	}
97 
98 	ps->ps_argc = argc;
99 	for (i = 0; i < argc; i++) {
100 		ps->ps_argv[i] = strdup(argv[i]);
101 		if (ps->ps_argv[i] == NULL) {
102 			warn("failed to copy argument");
103 			return (-1);
104 		}
105 	}
106 
107 	ps->ps_argv[i] = NULL;
108 	return (0);
109 }
110 
111 
112 int
process_run(struct pstate * ps)113 process_run(struct pstate *ps)
114 {
115 	int status;
116 
117 	if ((ps->ps_state == RUNNING) || (ps->ps_state == STOPPED)) {
118 		warnx("process is already running");
119 		return 0;
120 	}
121 
122 	switch (ps->ps_pid = fork()) {
123 	case 0:
124 		if (ptrace(PT_TRACE_ME, getpid(), NULL, 0) != 0)
125 			err(1, "ptrace(PT_TRACE_ME)");
126 		execvp(*ps->ps_argv, ps->ps_argv);
127 		err(1, "exec");
128 		/* NOTREACHED */
129 	case -1:
130 		err(1, "fork");
131 		/* NOTREACHED */
132 	default:
133 		warnx("process started with PID %d", ps->ps_pid);
134 		break;
135 	}
136 
137 	ps->ps_state = LOADED;
138 
139 	if (wait(&status) == 0)
140 		err(1, "wait");
141 
142 	return (0);
143 }
144 
145 
146 int
process_kill(struct pstate * ps)147 process_kill(struct pstate *ps)
148 {
149 	switch(ps->ps_state) {
150 	case RUNNING:
151 	case STOPPED:
152 		if (ptrace(PT_KILL, ps->ps_pid, NULL, 0) != 0)
153 			err(1, "ptrace(PT_KILL)");
154 		return (1);
155 	default:
156 		return (0);
157 	}
158 }
159 
160 int
process_read(struct pstate * ps,off_t from,void * to,size_t size)161 process_read(struct pstate *ps, off_t from, void *to, size_t size)
162 {
163 	struct ptrace_io_desc piod;
164 
165 	if (((ps->ps_state == NONE) || (ps->ps_state == LOADED) ||
166 	    (ps->ps_state == TERMINATED)) && (ps->ps_flags & PSF_CORE)) {
167 		return core_read(ps, from, to, size);
168 	} else {
169 		piod.piod_op = PIOD_READ_D;
170 		piod.piod_offs = (void *)(long)from;
171 		piod.piod_addr = to;
172 		piod.piod_len = size;
173 
174 		return (ptrace(PT_IO, ps->ps_pid, (caddr_t)&piod, 0) < 0?
175 		    -1 : piod.piod_len);
176 	}
177 }
178 
179 int
process_write(struct pstate * ps,off_t to,void * from,size_t size)180 process_write(struct pstate *ps, off_t to, void *from, size_t size)
181 {
182 	struct ptrace_io_desc piod;
183 
184 	if ((ps->ps_state == NONE) && (ps->ps_flags & PSF_CORE)) {
185 		return core_write(ps, to, from, size);
186 	} else {
187 		piod.piod_op = PIOD_WRITE_D;
188 		piod.piod_offs = (void *)(long)to;
189 		piod.piod_addr = from;
190 		piod.piod_len = size;
191 
192 		return (ptrace(PT_IO, ps->ps_pid, (caddr_t)&piod, 0) < 0?
193 		    -1 : piod.piod_len);
194 	}
195 }
196 
197 int
process_getregs(struct pstate * ps,struct reg * r)198 process_getregs(struct pstate *ps, struct reg *r)
199 {
200 
201 	if (ps->ps_flags & PSF_CORE) {
202 		memcpy(r, ps->ps_core->regs, sizeof(*r));
203 
204 		return (0);
205 	}
206 
207 	return (ptrace(PT_GETREGS, ps->ps_pid, (caddr_t)r, 0));
208 }
209 
210 int
cmd_process_kill(int argc,char ** argv,void * arg)211 cmd_process_kill(int argc, char **argv, void *arg)
212 {
213 	struct pstate *ps = arg;
214 
215 	process_kill(ps);
216 
217 	return (1);
218 }
219 
220 int
process_bkpt_main(struct pstate * ps,void * arg)221 process_bkpt_main(struct pstate *ps, void *arg)
222 {
223 	sym_update(ps);
224 
225 	return (BKPT_DEL_CONT);
226 }
227 
228 int
cmd_process_run(int argc,char ** argv,void * arg)229 cmd_process_run(int argc, char **argv, void *arg)
230 {
231 	struct pstate *ps = arg;
232 
233 	if (ps->ps_state == NONE) {
234 		reg main_addr;
235 
236 		if (process_load(ps) != 0)
237 			return (0);
238 
239 		if (sym_lookup(ps, "main", &main_addr))
240 			warnx("no main");
241 		else if (bkpt_add_cb(ps, main_addr, process_bkpt_main, NULL))
242 			warn("no bkpt at main 0x%lx", main_addr);
243 	}
244 
245 	if (ps->ps_state != LOADED) {
246 		fprintf(stderr, "Process already running.\n");
247 		return (0);
248 	}
249 
250 	process_run(ps);
251 	/*
252 	 * XXX - there isn't really any difference between STOPPED and
253 	 * LOADED, we should probably get rid of one.
254 	 */
255 	ps->ps_state = STOPPED;
256 	ps->ps_signum = 0;
257 
258 	return (cmd_process_cont(argc, argv, arg));
259 }
260 
261 int
cmd_process_cont(int argc,char ** argv,void * arg)262 cmd_process_cont(int argc, char **argv, void *arg)
263 {
264 	struct pstate *ps = arg;
265 	int signum;
266 	int req = (ps->ps_flags & PSF_STEP) ? PT_STEP : PT_CONTINUE;
267 
268 	if (ps->ps_state != STOPPED) {
269 		fprintf(stderr, "Process not loaded and stopped %d\n",
270 		    ps->ps_state);
271 		return (0);
272 	}
273 
274 	/* Catch SIGINT and SIGTRAP, pass all other signals. */
275 	switch (ps->ps_signum) {
276 	case SIGINT:
277 	case SIGTRAP:
278 		signum = 0;
279 		break;
280 	default:
281 		signum = ps->ps_signum;
282 		break;
283 	}
284 
285 	if (ptrace(req, ps->ps_pid, (caddr_t)ps->ps_npc, signum) != 0) {
286 		err(1, "ptrace(%s)", req == PT_STEP ? "PT_STEP":"PT_CONTINUE");
287 	}
288 
289 	ps->ps_state = RUNNING;
290 	ps->ps_npc = 1;
291 
292 	return (1);
293 }
294 
295 int
cmd_process_setenv(int argc,char ** argv,void * arg)296 cmd_process_setenv(int argc, char **argv, void *arg)
297 {
298 	if (setenv(argv[1], argv[2], 1))
299 		err(1, "setenv");
300 
301 	return (0);
302 }
303