blob: 78b142726d190430ce54b0b9cb75a8cc9514d81b [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Mike Frysinger8566c502009-10-12 11:05:14 -040081#if defined(LINUXSPARC) && defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000082# undef PTRACE_GETREGS
83# define PTRACE_GETREGS PTRACE_GETREGS64
84# undef PTRACE_SETREGS
85# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000086#endif
87
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088/* macros */
89#ifndef MAX
90#define MAX(a,b) (((a) > (b)) ? (a) : (b))
91#endif
92#ifndef MIN
93#define MIN(a,b) (((a) < (b)) ? (a) : (b))
94#endif
95
Roland McGratha4d48532005-06-08 20:45:28 +000096#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000097void
98tv_tv(tv, a, b)
99struct timeval *tv;
100int a;
101int b;
102{
103 tv->tv_sec = a;
104 tv->tv_usec = b;
105}
Roland McGratha4d48532005-06-08 20:45:28 +0000106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
108int
109tv_nz(a)
110struct timeval *a;
111{
112 return a->tv_sec || a->tv_usec;
113}
114
115int
116tv_cmp(a, b)
117struct timeval *a, *b;
118{
119 if (a->tv_sec < b->tv_sec
120 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
121 return -1;
122 if (a->tv_sec > b->tv_sec
123 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
124 return 1;
125 return 0;
126}
127
128double
129tv_float(tv)
130struct timeval *tv;
131{
132 return tv->tv_sec + tv->tv_usec/1000000.0;
133}
134
135void
136tv_add(tv, a, b)
137struct timeval *tv, *a, *b;
138{
139 tv->tv_sec = a->tv_sec + b->tv_sec;
140 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000141 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142 tv->tv_sec++;
143 tv->tv_usec -= 1000000;
144 }
145}
146
147void
148tv_sub(tv, a, b)
149struct timeval *tv, *a, *b;
150{
151 tv->tv_sec = a->tv_sec - b->tv_sec;
152 tv->tv_usec = a->tv_usec - b->tv_usec;
153 if (((long) tv->tv_usec) < 0) {
154 tv->tv_sec--;
155 tv->tv_usec += 1000000;
156 }
157}
158
159void
160tv_div(tv, a, n)
161struct timeval *tv, *a;
162int n;
163{
164 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
165 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
166 tv->tv_usec %= 1000000;
167}
168
169void
170tv_mul(tv, a, n)
171struct timeval *tv, *a;
172int n;
173{
174 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000175 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176 tv->tv_usec %= 1000000;
177}
178
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000179const char *
180xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181{
182 for (; xlat->str != NULL; xlat++)
183 if (xlat->val == val)
184 return xlat->str;
185 return NULL;
186}
187
188/*
Roland McGratheb9e2e82009-06-02 16:49:22 -0700189 * Generic ptrace wrapper which tracks ESRCH errors
190 * by setting tcp->ptrace_errno to ESRCH.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000191 *
192 * We assume that ESRCH indicates likely process death (SIGKILL?),
193 * modulo bugs where process somehow ended up not stopped.
194 * Unfortunately kernel uses ESRCH for that case too. Oh well.
Roland McGratheb9e2e82009-06-02 16:49:22 -0700195 *
196 * Currently used by upeek() only.
197 * TODO: use this in all other ptrace() calls while decoding.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000198 */
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000199long
Roland McGratheb9e2e82009-06-02 16:49:22 -0700200do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000201{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000202 long l;
203
204 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400205 l = ptrace(request, tcp->pid, addr, (long) data);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700206 /* Non-ESRCH errors might be our invalid reg/mem accesses,
207 * we do not record them. */
208 if (errno == ESRCH)
209 tcp->ptrace_errno = ESRCH;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000210 return l;
211}
212
213/*
214 * Used when we want to unblock stopped traced process.
215 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
216 * Returns 0 on success or if error was ESRCH
217 * (presumably process was killed while we talk to it).
218 * Otherwise prints error message and returns -1.
219 */
220int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700221ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000222{
223 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700224 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000225
226 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400227 ptrace(op, tcp->pid, (void *) 1, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000228 err = errno;
229 if (!err || err == ESRCH)
230 return 0;
231
232 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700233 msg = "SYSCALL";
234 if (op == PTRACE_CONT)
235 msg = "CONT";
236 if (op == PTRACE_DETACH)
237 msg = "DETACH";
238 fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
239 msg, sig, strerror(err));
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000240 return -1;
241}
242
243/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 * Print entry in struct xlat table, if there.
245 */
246void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000247printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000249 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251 if (str)
252 tprintf("%s", str);
253 else
254 tprintf("%#x /* %s */", val, dflt);
255}
256
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100257#if HAVE_LONG_LONG
258/*
259 * Print 64bit argument at position llarg and return the index of the next
260 * argument.
261 */
262int
263printllval(struct tcb *tcp, const char *format, int llarg)
264{
265# if defined(FREEBSD) \
266 || (defined(LINUX) && defined(POWERPC) && !defined(__powerpc64__)) \
267 || defined (LINUX_MIPSO32)
268 /* Align 64bit argument to 64bit boundary. */
269 if (llarg % 2) llarg++;
270# endif
271# if defined LINUX && defined X86_64
272 if (current_personality == 0) {
273 tprintf(format, tcp->u_arg[llarg]);
274 llarg++;
275 } else {
276 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
277 llarg += 2;
278 }
279# elif defined IA64 || defined ALPHA || (defined POWERPC && defined __powerpc64__)
280 tprintf(format, tcp->u_arg[llarg]);
281 llarg++;
282# elif defined LINUX_MIPSN32
283 tprintf(format, tcp->ext_arg[llarg]);
284 llarg++;
285# else
286 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
287 llarg += 2;
288# endif
289 return llarg;
290}
291#endif
292
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293/*
294 * Interpret `xlat' as an array of flags
295 * print the entries whose bits are on in `flags'
296 * return # of flags printed.
297 */
298int
299addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000300const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301int flags;
302{
303 int n;
304
305 for (n = 0; xlat->str; xlat++) {
306 if (xlat->val && (flags & xlat->val) == xlat->val) {
307 tprintf("|%s", xlat->str);
308 flags &= ~xlat->val;
309 n++;
310 }
311 }
312 if (flags) {
313 tprintf("|%#x", flags);
314 n++;
315 }
316 return n;
317}
318
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000319/*
320 * Interpret `xlat' as an array of flags/
321 * Print to static string the entries whose bits are on in `flags'
322 * Return static string.
323 */
324const char *
325sprintflags(const char *prefix, const struct xlat *xlat, int flags)
326{
327 static char outstr[1024];
328 int found = 0;
329
330 strcpy(outstr, prefix);
331
332 for (; xlat->str; xlat++) {
333 if ((flags & xlat->val) == xlat->val) {
334 if (found)
335 strcat(outstr, "|");
336 strcat(outstr, xlat->str);
337 flags &= ~xlat->val;
338 found = 1;
339 }
340 }
341 if (flags) {
342 if (found)
343 strcat(outstr, "|");
344 sprintf(outstr + strlen(outstr), "%#x", flags);
345 }
346
347 return outstr;
348}
349
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350int
Roland McGrathb2dee132005-06-01 19:02:36 +0000351printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000352const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000354const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000355{
356 int n;
357 char *sep;
358
359 if (flags == 0 && xlat->val == 0) {
360 tprintf("%s", xlat->str);
361 return 1;
362 }
363
364 sep = "";
365 for (n = 0; xlat->str; xlat++) {
366 if (xlat->val && (flags & xlat->val) == xlat->val) {
367 tprintf("%s%s", sep, xlat->str);
368 flags &= ~xlat->val;
369 sep = "|";
370 n++;
371 }
372 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000373
374 if (n) {
375 if (flags) {
376 tprintf("%s%#x", sep, flags);
377 n++;
378 }
379 } else {
380 if (flags) {
381 tprintf("%#x", flags);
382 if (dflt)
383 tprintf(" /* %s */", dflt);
384 } else {
385 if (dflt)
386 tprintf("0");
387 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000388 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000389
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 return n;
391}
392
393void
394printnum(tcp, addr, fmt)
395struct tcb *tcp;
396long addr;
397char *fmt;
398{
Roland McGratheb285352003-01-14 09:59:00 +0000399 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000400
401 if (!addr) {
402 tprintf("NULL");
403 return;
404 }
405 if (umove(tcp, addr, &num) < 0) {
406 tprintf("%#lx", addr);
407 return;
408 }
409 tprintf("[");
410 tprintf(fmt, num);
411 tprintf("]");
412}
413
Roland McGrath6bc12202003-11-13 22:32:27 +0000414void
Roland McGrath9814a942005-07-04 23:28:10 +0000415printnum_int(tcp, addr, fmt)
416struct tcb *tcp;
417long addr;
418char *fmt;
419{
420 int num;
421
422 if (!addr) {
423 tprintf("NULL");
424 return;
425 }
426 if (umove(tcp, addr, &num) < 0) {
427 tprintf("%#lx", addr);
428 return;
429 }
430 tprintf("[");
431 tprintf(fmt, num);
432 tprintf("]");
433}
434
435void
Roland McGrath6bc12202003-11-13 22:32:27 +0000436printuid(text, uid)
437const char *text;
438unsigned long uid;
439{
440 tprintf("%s", text);
441 tprintf((uid == -1) ? "%ld" : "%lu", uid);
442}
443
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000444static char path[MAXPATHLEN + 1];
445
Dmitry V. Levina501f142008-11-10 23:19:13 +0000446/*
447 * Quote string `instr' of length `size'
448 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
449 * If `len' < 0, treat `instr' as a NUL-terminated string
450 * and quote at most (`size' - 1) bytes.
451 */
Roland McGrath6d970322007-11-01 23:53:59 +0000452static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000453string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000454{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000455 const unsigned char *ustr = (const unsigned char *) instr;
456 char *s = outstr;
457 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000458
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000459 if (xflag > 1)
460 usehex = 1;
461 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000462 /* Check for presence of symbol which require
463 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000464 for (i = 0; i < size; ++i) {
465 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000466 /* Check for NUL-terminated string. */
467 if (len < 0) {
468 if (c == '\0')
469 break;
470 /* Quote at most size - 1 bytes. */
471 if (i == size - 1)
472 continue;
473 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000474 if (!isprint(c) && !isspace(c)) {
475 usehex = 1;
476 break;
477 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 }
479 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000480
481 *s++ = '\"';
482
483 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000484 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000485 for (i = 0; i < size; ++i) {
486 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000487 /* Check for NUL-terminated string. */
488 if (len < 0) {
489 if (c == '\0')
490 break;
491 /* Quote at most size - 1 bytes. */
492 if (i == size - 1)
493 continue;
494 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000495 sprintf(s, "\\x%02x", c);
496 s += 4;
497 }
498 } else {
499 for (i = 0; i < size; ++i) {
500 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000501 /* Check for NUL-terminated string. */
502 if (len < 0) {
503 if (c == '\0')
504 break;
505 /* Quote at most size - 1 bytes. */
506 if (i == size - 1)
507 continue;
508 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000509 switch (c) {
510 case '\"': case '\\':
511 *s++ = '\\';
512 *s++ = c;
513 break;
514 case '\f':
515 *s++ = '\\';
516 *s++ = 'f';
517 break;
518 case '\n':
519 *s++ = '\\';
520 *s++ = 'n';
521 break;
522 case '\r':
523 *s++ = '\\';
524 *s++ = 'r';
525 break;
526 case '\t':
527 *s++ = '\\';
528 *s++ = 't';
529 break;
530 case '\v':
531 *s++ = '\\';
532 *s++ = 'v';
533 break;
534 default:
535 if (isprint(c))
536 *s++ = c;
537 else if (i + 1 < size
538 && isdigit(ustr[i + 1])) {
539 sprintf(s, "\\%03o", c);
540 s += 4;
541 } else {
542 sprintf(s, "\\%o", c);
543 s += strlen(s);
544 }
545 break;
546 }
547 }
548 }
549
550 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000552
553 /* Return nonzero if the string was unterminated. */
554 return i == size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555}
556
Dmitry V. Levina501f142008-11-10 23:19:13 +0000557/*
558 * Print path string specified by address `addr' and length `n'.
559 * If path length exceeds `n', append `...' to the output.
560 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000562printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563{
Dmitry V. Levina501f142008-11-10 23:19:13 +0000564 if (!addr) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000565 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000566 return;
567 }
568
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569 /* Cap path length to the path buffer size,
570 and NUL-terminate the buffer. */
571 if (n > sizeof path - 1)
572 n = sizeof path - 1;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000573 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000574
575 /* Fetch one byte more to find out whether path length > n. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000576 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000577 tprintf("%#lx", addr);
578 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000579 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
580 int trunc = (path[n] != '\0');
581
582 if (trunc)
583 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000584 (void) string_quote(path, outstr, -1, n + 1);
585 if (trunc)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000586 strcat(outstr, "...");
587 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 }
589}
590
591void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000592printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000594 printpathn(tcp, addr, sizeof path - 1);
595}
596
Dmitry V. Levina501f142008-11-10 23:19:13 +0000597/*
598 * Print string specified by address `addr' and length `len'.
599 * If `len' < 0, treat the string as a NUL-terminated string.
600 * If string length exceeds `max_strlen', append `...' to the output.
601 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000602void
603printstr(struct tcb *tcp, long addr, int len)
604{
605 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000607 int size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608
609 if (!addr) {
610 tprintf("NULL");
611 return;
612 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000613 /* Allocate static buffers if they are not allocated yet. */
614 if (!str)
615 str = malloc(max_strlen + 1);
616 if (!outstr)
617 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
618 if (!str || !outstr) {
619 fprintf(stderr, "out of memory\n");
620 tprintf("%#lx", addr);
621 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000622 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000623
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000625 /*
626 * Treat as a NUL-terminated string: fetch one byte more
627 * because string_quote() quotes one byte less.
628 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000629 size = max_strlen + 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000630 str[max_strlen] = '\0';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000631 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632 tprintf("%#lx", addr);
633 return;
634 }
635 }
636 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000637 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000638 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639 tprintf("%#lx", addr);
640 return;
641 }
642 }
643
Dmitry V. Levina501f142008-11-10 23:19:13 +0000644 if (string_quote(str, outstr, len, size) &&
645 (len < 0 || len > max_strlen))
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000646 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000647
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 tprintf("%s", outstr);
649}
650
John Hughes1d08dcf2001-07-10 13:48:44 +0000651#if HAVE_SYS_UIO_H
652void
653dumpiov(tcp, len, addr)
654struct tcb * tcp;
655int len;
656long addr;
657{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000658#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
659 union {
660 struct { u_int32_t base; u_int32_t len; } *iov32;
661 struct { u_int64_t base; u_int64_t len; } *iov64;
662 } iovu;
663#define iov iovu.iov64
664#define sizeof_iov \
665 (personality_wordsize[current_personality] == 4 \
666 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
667#define iov_iov_base(i) \
668 (personality_wordsize[current_personality] == 4 \
669 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
670#define iov_iov_len(i) \
671 (personality_wordsize[current_personality] == 4 \
672 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
673#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000674 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000675#define sizeof_iov sizeof(*iov)
676#define iov_iov_base(i) iov[i].iov_base
677#define iov_iov_len(i) iov[i].iov_len
678#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000679 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000680 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000681
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000682 size = sizeof_iov * (unsigned long) len;
683 if (size / sizeof_iov != len
684 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000685 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000686 return;
687 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000688 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000689 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000690 /* include the buffer number to make it easy to
691 * match up the trace with the source */
692 tprintf(" * %lu bytes in buffer %d\n",
693 (unsigned long)iov_iov_len(i), i);
694 dumpstr(tcp, (long) iov_iov_base(i),
695 iov_iov_len(i));
696 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000697 }
698 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000699#undef sizeof_iov
700#undef iov_iov_base
701#undef iov_iov_len
702#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000703}
704#endif
705
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000706void
707dumpstr(tcp, addr, len)
708struct tcb *tcp;
709long addr;
710int len;
711{
712 static int strsize = -1;
713 static unsigned char *str;
714 static char outstr[80];
715 char *s;
716 int i, j;
717
718 if (strsize < len) {
719 if (str)
720 free(str);
721 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000722 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 return;
724 }
725 strsize = len;
726 }
727
728 if (umoven(tcp, addr, len, (char *) str) < 0)
729 return;
730
731 for (i = 0; i < len; i += 16) {
732 s = outstr;
733 sprintf(s, " | %05x ", i);
734 s += 9;
735 for (j = 0; j < 16; j++) {
736 if (j == 8)
737 *s++ = ' ';
738 if (i + j < len) {
739 sprintf(s, " %02x", str[i + j]);
740 s += 3;
741 }
742 else {
743 *s++ = ' '; *s++ = ' '; *s++ = ' ';
744 }
745 }
746 *s++ = ' '; *s++ = ' ';
747 for (j = 0; j < 16; j++) {
748 if (j == 8)
749 *s++ = ' ';
750 if (i + j < len) {
751 if (isprint(str[i + j]))
752 *s++ = str[i + j];
753 else
754 *s++ = '.';
755 }
756 else
757 *s++ = ' ';
758 }
759 tprintf("%s |\n", outstr);
760 }
761}
762
763#define PAGMASK (~(PAGSIZ - 1))
764/*
765 * move `len' bytes of data from process `pid'
766 * at address `addr' to our space at `laddr'
767 */
768int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000769umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000770{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000771#ifdef LINUX
Roland McGratheb9e2e82009-06-02 16:49:22 -0700772 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000774 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000775 union {
776 long val;
777 char x[sizeof(long)];
778 } u;
779
780 if (addr & (sizeof(long) - 1)) {
781 /* addr not a multiple of sizeof(long) */
782 n = addr - (addr & -sizeof(long)); /* residue */
783 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700784 errno = 0;
785 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
786 if (errno) {
787 if (started && (errno==EPERM || errno==EIO)) {
788 /* Ran into 'end of memory' - stupid "printpath" */
789 return 0;
790 }
791 /* But if not started, we had a bogus address. */
792 if (addr != 0 && errno != EIO && errno != ESRCH)
793 perror("ptrace: umoven");
794 return -1;
795 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000796 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
798 addr += sizeof(long), laddr += m, len -= m;
799 }
800 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700801 errno = 0;
802 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
803 if (errno) {
804 if (started && (errno==EPERM || errno==EIO)) {
805 /* Ran into 'end of memory' - stupid "printpath" */
806 return 0;
807 }
808 if (addr != 0 && errno != EIO && errno != ESRCH)
809 perror("ptrace: umoven");
810 return -1;
811 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000812 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
814 addr += sizeof(long), laddr += m, len -= m;
815 }
816#endif /* LINUX */
817
818#ifdef SUNOS4
819 int pid = tcp->pid;
820#if 0
821 int n, m;
822 union {
823 long val;
824 char x[sizeof(long)];
825 } u;
826
827 if (addr & (sizeof(long) - 1)) {
828 /* addr not a multiple of sizeof(long) */
829 n = addr - (addr & -sizeof(long)); /* residue */
830 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700831 errno = 0;
832 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
833 if (errno) {
834 if (errno != ESRCH)
835 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700837 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000838 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
839 addr += sizeof(long), laddr += m, len -= m;
840 }
841 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700842 errno = 0;
843 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
844 if (errno) {
845 if (errno != ESRCH)
846 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700848 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000849 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
850 addr += sizeof(long), laddr += m, len -= m;
851 }
852#else /* !oldway */
853 int n;
854
855 while (len) {
856 n = MIN(len, PAGSIZ);
857 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700858 if (ptrace(PTRACE_READDATA, pid,
859 (char *) addr, len, laddr) < 0) {
860 if (errno != ESRCH) {
861 perror("umoven: ptrace(PTRACE_READDATA, ...)");
862 abort();
863 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 return -1;
865 }
866 len -= n;
867 addr += n;
868 laddr += n;
869 }
870#endif /* !oldway */
871#endif /* SUNOS4 */
872
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000873#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000874#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000875 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000876#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000877 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000879 lseek(fd, addr, SEEK_SET);
880 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000882#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883
884 return 0;
885}
886
887/*
888 * like `umove' but make the additional effort of looking
889 * for a terminating zero byte.
890 */
891int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000892umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000894#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000895#ifdef HAVE_MP_PROCFS
896 int fd = tcp->pfd_as;
897#else
898 int fd = tcp->pfd;
899#endif
900 /* Some systems (e.g. FreeBSD) can be upset if we read off the
901 end of valid memory, avoid this by trying to read up
902 to page boundaries. But we don't know what a page is (and
903 getpagesize(2) (if it exists) doesn't necessarily return
904 hardware page size). Assume all pages >= 1024 (a-historical
905 I know) */
906
907 int page = 1024; /* How to find this? */
908 int move = page - (addr & (page - 1));
909 int left = len;
910
911 lseek(fd, addr, SEEK_SET);
912
913 while (left) {
914 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000915 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000916 return left != len ? 0 : -1;
917 if (memchr (laddr, 0, move)) break;
918 left -= move;
919 laddr += move;
920 addr += move;
921 move = page;
922 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000923#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000924 int started = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700925 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 int i, n, m;
927 union {
928 long val;
929 char x[sizeof(long)];
930 } u;
931
932 if (addr & (sizeof(long) - 1)) {
933 /* addr not a multiple of sizeof(long) */
934 n = addr - (addr & -sizeof(long)); /* residue */
935 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700936 errno = 0;
937 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
938 if (errno) {
939 if (started && (errno==EPERM || errno==EIO)) {
940 /* Ran into 'end of memory' - stupid "printpath" */
941 return 0;
942 }
943 if (addr != 0 && errno != EIO && errno != ESRCH)
944 perror("umovestr");
945 return -1;
946 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000947 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
949 while (n & (sizeof(long) - 1))
950 if (u.x[n++] == '\0')
951 return 0;
952 addr += sizeof(long), laddr += m, len -= m;
953 }
954 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700955 errno = 0;
956 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
957 if (errno) {
958 if (started && (errno==EPERM || errno==EIO)) {
959 /* Ran into 'end of memory' - stupid "printpath" */
960 return 0;
961 }
962 if (addr != 0 && errno != EIO && errno != ESRCH)
963 perror("umovestr");
964 return -1;
965 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000966 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
968 for (i = 0; i < sizeof(long); i++)
969 if (u.x[i] == '\0')
970 return 0;
971
972 addr += sizeof(long), laddr += m, len -= m;
973 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000974#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000975 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976}
977
978#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000979# if !defined (SPARC) && !defined(SPARC64)
980# define PTRACE_WRITETEXT 101
981# define PTRACE_WRITEDATA 102
982# endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983#endif /* LINUX */
984
985#ifdef SUNOS4
986
987static int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700988uload(cmd, pid, addr, len, laddr)
989int cmd;
990int pid;
991long addr;
992int len;
993char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000995# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 int n;
997
998 while (len) {
999 n = MIN(len, PAGSIZ);
1000 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001001 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
1002 perror("uload: ptrace(PTRACE_WRITE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 return -1;
1004 }
1005 len -= n;
1006 addr += n;
1007 laddr += n;
1008 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001009# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 int peek, poke;
1011 int n, m;
1012 union {
1013 long val;
1014 char x[sizeof(long)];
1015 } u;
1016
1017 if (cmd == PTRACE_WRITETEXT) {
1018 peek = PTRACE_PEEKTEXT;
1019 poke = PTRACE_POKETEXT;
1020 }
1021 else {
1022 peek = PTRACE_PEEKDATA;
1023 poke = PTRACE_POKEDATA;
1024 }
1025 if (addr & (sizeof(long) - 1)) {
1026 /* addr not a multiple of sizeof(long) */
1027 n = addr - (addr & -sizeof(long)); /* residue */
1028 addr &= -sizeof(long);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001029 errno = 0;
1030 u.val = ptrace(peek, pid, (char *) addr, 0);
1031 if (errno) {
1032 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 return -1;
1034 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001035 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
1036 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
1037 perror("uload: POKE");
1038 return -1;
1039 }
1040 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 }
1042 while (len) {
1043 if (len < sizeof(long))
Roland McGratheb9e2e82009-06-02 16:49:22 -07001044 u.val = ptrace(peek, pid, (char *) addr, 0);
1045 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
1046 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
1047 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 return -1;
1049 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001050 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001052# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 return 0;
1054}
1055
Roland McGratheb9e2e82009-06-02 16:49:22 -07001056int
1057tload(pid, addr, len, laddr)
1058int pid;
1059int addr, len;
1060char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001062 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1063}
1064
1065int
1066dload(pid, addr, len, laddr)
1067int pid;
1068int addr;
1069int len;
1070char *laddr;
1071{
1072 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073}
1074
1075#endif /* SUNOS4 */
1076
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001077#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078
1079int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001080upeek(tcp, off, res)
1081struct tcb *tcp;
1082long off;
1083long *res;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084{
1085 long val;
1086
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001087# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 {
1089 static int is_sun4m = -1;
1090 struct utsname name;
1091
1092 /* Round up the usual suspects. */
1093 if (is_sun4m == -1) {
1094 if (uname(&name) < 0) {
1095 perror("upeek: uname?");
1096 exit(1);
1097 }
1098 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1099 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001100 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101
1102 for (x = struct_user_offsets; x->str; x++)
1103 x->val += 1024;
1104 }
1105 }
1106 if (is_sun4m)
1107 off += 1024;
1108 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001109# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001110 errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001111 val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001112 if (val == -1 && errno) {
1113 if (errno != ESRCH) {
1114 char buf[60];
1115 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1116 perror(buf);
1117 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001119 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 *res = val;
1121 return 0;
1122}
1123
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001124#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125
Roland McGratha4d48532005-06-08 20:45:28 +00001126#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127long
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001128getpc(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129{
1130
1131#ifdef LINUX
1132 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001133# if defined(I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001134 if (upeek(tcp, 4*EIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001136# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001137 if (upeek(tcp, 8*RIP, &pc) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001138 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001139# elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001140 if (upeek(tcp, PT_B0, &pc) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001141 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001142# elif defined(ARM)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001143 if (upeek(tcp, 4*15, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001145# elif defined(AVR32)
1146 if (upeek(tcp, REG_PC, &pc) < 0)
1147 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001148# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001149 if (upeek(tcp, REG_PC, &pc) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001150 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001151# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001152 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001154# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001155 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001157# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001158 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001160# elif defined(MIPS)
1161 if (upeek(tcp, REG_EPC, &pc) < 0)
1162 return -1;
1163# elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001164 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001165 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001167# if defined(SPARC64)
1168 pc = regs.tpc;
1169# else
1170 pc = regs.pc;
1171# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001172# elif defined(S390) || defined(S390X)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001173 if(upeek(tcp,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001174 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001175# elif defined(HPPA)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001176 if(upeek(tcp,PT_IAOQ0,&pc) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001177 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001178# elif defined(SH)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001179 if (upeek(tcp, 4*REG_PC ,&pc) < 0)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001180 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001181# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001182 if (upeek(tcp, REG_PC ,&pc) < 0)
1183 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001184# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 return pc;
1186#endif /* LINUX */
1187
1188#ifdef SUNOS4
1189 /*
1190 * Return current program counter for `pid'
1191 * Assumes PC is never 0xffffffff
1192 */
1193 struct regs regs;
1194
Roland McGratheb9e2e82009-06-02 16:49:22 -07001195 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1196 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001198 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 return regs.r_pc;
1200#endif /* SUNOS4 */
1201
1202#ifdef SVR4
1203 /* XXX */
1204 return 0;
1205#endif /* SVR4 */
1206
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001207#ifdef FREEBSD
1208 struct reg regs;
1209 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1210 return regs.r_eip;
1211#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001213#endif /* 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214
1215void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001216printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217{
Roland McGrath7a918832005-02-02 20:55:23 +00001218#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1219 sizeof(long) == 8 ? "[????????????????] " : \
1220 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221
1222#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001223# ifdef I386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 long eip;
1225
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001226 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001227 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 return;
1229 }
1230 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001231
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001232# elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001233 long psw;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001234 if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001235 PRINTBADPC;
1236 return;
1237 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001238# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001239 tprintf("[%08lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001240# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001241 tprintf("[%16lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001242# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001243
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001244# elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001245 long rip;
1246
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001247 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001248 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001249 return;
1250 }
1251 tprintf("[%16lx] ", rip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001252# elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001253 long ip;
1254
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001255 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001256 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001257 return;
1258 }
1259 tprintf("[%08lx] ", ip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001260# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 long pc;
1262
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001263 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 tprintf ("[????????] ");
1265 return;
1266 }
1267 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001268# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 long pc;
1270
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001271 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 tprintf ("[????????] ");
1273 return;
1274 }
1275 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001276# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277 long pc;
1278
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001279 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001280 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281 return;
1282 }
1283 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001284# elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001285 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001286 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001287 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288 return;
1289 }
Mike Frysinger8566c502009-10-12 11:05:14 -04001290# if defined(SPARC64)
1291 tprintf("[%08lx] ", regs.tpc);
1292# else
1293 tprintf("[%08lx] ", regs.pc);
1294# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001295# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001296 long pc;
1297
Roland McGratheb9e2e82009-06-02 16:49:22 -07001298 if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001299 tprintf ("[????????] ");
1300 return;
1301 }
1302 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001303# elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001304 long pc;
1305
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001306 if (upeek(tcp, REG_EPC, &pc) < 0) {
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001307 tprintf ("[????????] ");
1308 return;
1309 }
1310 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001311# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001312 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001313
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001314 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1315 tprintf ("[????????] ");
1316 return;
1317 }
1318 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001319# elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001320 long pc;
1321
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001322 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001323 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001324 return;
1325 }
1326 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001327# elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001328 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001329
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001330 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001331 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001332 return;
1333 }
1334 tprintf("[%08lx] ", pc);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001335# elif defined(AVR32)
1336 long pc;
1337
1338 if (upeek(tcp, REG_PC, &pc) < 0) {
1339 tprintf("[????????] ");
1340 return;
1341 }
1342 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001343# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001344 long pc;
1345
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001346 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001347 PRINTBADPC;
1348 return;
1349 }
1350 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001351#elif defined(CRISV10)
1352 long pc;
1353
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001354 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001355 PRINTBADPC;
1356 return;
1357 }
1358 tprintf("[%08lx] ", pc);
1359#elif defined(CRISV32)
1360 long pc;
1361
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001362 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001363 PRINTBADPC;
1364 return;
1365 }
1366 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001367# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368#endif /* LINUX */
1369
1370#ifdef SUNOS4
1371 struct regs regs;
1372
Roland McGratheb9e2e82009-06-02 16:49:22 -07001373 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1374 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001375 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376 return;
1377 }
1378 tprintf("[%08x] ", regs.r_o7);
1379#endif /* SUNOS4 */
1380
1381#ifdef SVR4
1382 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001383 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384#endif
1385
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001386#ifdef FREEBSD
1387 struct reg regs;
1388 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1389 tprintf("[%08x] ", regs.r_eip);
1390#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391}
1392
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001393
1394/*
1395 * These #if's are huge, please indent them correctly.
1396 * It's easy to get confused otherwise.
1397 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001398#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001400# if defined LINUX
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001402# include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001403
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001404# include <sys/syscall.h>
1405# ifndef CLONE_PTRACE
1406# define CLONE_PTRACE 0x00002000
1407# endif
1408# ifndef CLONE_VFORK
1409# define CLONE_VFORK 0x00004000
1410# endif
1411# ifndef CLONE_VM
1412# define CLONE_VM 0x00000100
1413# endif
1414# ifndef CLONE_STOPPED
1415# define CLONE_STOPPED 0x02000000
1416# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001418# ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001419
Roland McGrath08267b82004-02-20 22:56:43 +00001420/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1421 subsystem has them for x86... */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001422# define SYS_fork 2
1423# define SYS_vfork 190
Roland McGrath08267b82004-02-20 22:56:43 +00001424
Roland McGrathd81f1d92003-01-09 06:53:34 +00001425typedef unsigned long *arg_setup_state;
1426
1427static int
1428arg_setup(struct tcb *tcp, arg_setup_state *state)
1429{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001430 unsigned long cfm, sof, sol;
1431 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001432
Jan Kratochvil1f942712008-08-06 21:38:52 +00001433 if (ia32) {
1434 /* Satisfy a false GCC warning. */
1435 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001436 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001437 }
Roland McGrath08267b82004-02-20 22:56:43 +00001438
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001439 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001440 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001441 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001442 return -1;
1443
1444 sof = (cfm >> 0) & 0x7f;
1445 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001446 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001447
Jan Kratochvil1f942712008-08-06 21:38:52 +00001448 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001449 return 0;
1450}
1451
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001452# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001454# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001455static int
1456get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1457{
Roland McGrath08267b82004-02-20 22:56:43 +00001458 int ret;
1459
1460 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001461 ret = upeek (tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001462 else
1463 ret = umoven (tcp,
1464 (unsigned long) ia64_rse_skip_regs(*state, 0),
1465 sizeof(long), (void *) valp);
1466 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001467}
1468
1469static int
1470get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1471{
Roland McGrath08267b82004-02-20 22:56:43 +00001472 int ret;
1473
1474 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001475 ret = upeek (tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001476 else
1477 ret = umoven (tcp,
1478 (unsigned long) ia64_rse_skip_regs(*state, 1),
1479 sizeof(long), (void *) valp);
1480 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001482# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483
1484static int
1485set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1486{
Roland McGrath08267b82004-02-20 22:56:43 +00001487 int req = PTRACE_POKEDATA;
1488 void *ap;
1489
1490 if (ia32) {
1491 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1492 req = PTRACE_POKEUSER;
1493 } else
1494 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001495 errno = 0;
1496 ptrace(req, tcp->pid, ap, val);
1497 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001498}
1499
1500static int
1501set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1502{
Roland McGrath08267b82004-02-20 22:56:43 +00001503 int req = PTRACE_POKEDATA;
1504 void *ap;
1505
1506 if (ia32) {
1507 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1508 req = PTRACE_POKEUSER;
1509 } else
1510 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001511 errno = 0;
1512 ptrace(req, tcp->pid, ap, val);
1513 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001514}
1515
Roland McGrathb659f872008-07-18 01:19:36 +00001516/* ia64 does not return the input arguments from functions (and syscalls)
1517 according to ia64 RSE (Register Stack Engine) behavior. */
1518
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001519# define restore_arg0(tcp, state, val) ((void) (state), 0)
1520# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001521
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001522# elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001523
Mike Frysinger8566c502009-10-12 11:05:14 -04001524typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001525
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001526# define arg_setup(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001527 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001528# define arg_finish_change(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001529 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001530
Mike Frysinger8566c502009-10-12 11:05:14 -04001531# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1532# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1533# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1534# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001535# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001536
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001537# else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001538
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001539# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001540/* Note: this is only true for the `clone' system call, which handles
1541 arguments specially. We could as well say that its first two arguments
1542 are swapped relative to other architectures, but that would just be
1543 another #ifdef in the calls. */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001544# define arg0_offset PT_GPR3
1545# define arg1_offset PT_ORIGGPR2
1546# define restore_arg0(tcp, state, val) ((void) (state), 0)
1547# define restore_arg1(tcp, state, val) ((void) (state), 0)
1548# define arg0_index 1
1549# define arg1_index 0
1550# elif defined (ALPHA) || defined (MIPS)
1551# define arg0_offset REG_A0
1552# define arg1_offset (REG_A0+1)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001553# elif defined (AVR32)
1554# define arg0_offset (REG_R12)
1555# define arg1_offset (REG_R11)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001556# elif defined (POWERPC)
1557# define arg0_offset (sizeof(unsigned long)*PT_R3)
1558# define arg1_offset (sizeof(unsigned long)*PT_R4)
1559# define restore_arg0(tcp, state, val) ((void) (state), 0)
1560# elif defined (HPPA)
1561# define arg0_offset PT_GR26
1562# define arg1_offset (PT_GR26-4)
1563# elif defined (X86_64)
1564# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1565# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1566# elif defined (SH)
1567# define arg0_offset (4*(REG_REG0+4))
1568# define arg1_offset (4*(REG_REG0+5))
1569# elif defined (SH64)
1570 /* ABI defines arg0 & 1 in r2 & r3 */
1571# define arg0_offset (REG_OFFSET+16)
1572# define arg1_offset (REG_OFFSET+24)
1573# define restore_arg0(tcp, state, val) 0
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001574# elif defined CRISV10 || defined CRISV32
1575# define arg0_offset (4*PT_R11)
1576# define arg1_offset (4*PT_ORIG_R10)
1577# define restore_arg0(tcp, state, val) 0
1578# define restore_arg1(tcp, state, val) 0
1579# define arg0_index 1
1580# define arg1_index 0
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001581# else
1582# define arg0_offset 0
1583# define arg1_offset 4
1584# if defined ARM
1585# define restore_arg0(tcp, state, val) 0
1586# endif
1587# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001588
1589typedef int arg_setup_state;
1590
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001591# define arg_setup(tcp, state) (0)
1592# define arg_finish_change(tcp, state) 0
1593# define get_arg0(tcp, cookie, valp) \
1594 (upeek ((tcp), arg0_offset, (valp)))
1595# define get_arg1(tcp, cookie, valp) \
1596 (upeek ((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001597
1598static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001599set_arg0 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001600{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001601 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001602}
1603
1604static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001605set_arg1 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001606{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001607 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001608}
1609
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001610# endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001611
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001612# ifndef restore_arg0
1613# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1614# endif
1615# ifndef restore_arg1
1616# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1617# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001618
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001619# ifndef arg0_index
1620# define arg0_index 0
1621# define arg1_index 1
1622# endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001623
Roland McGrathd81f1d92003-01-09 06:53:34 +00001624int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001625setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001626{
Roland McGrath3291ef22008-05-20 00:34:34 +00001627 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001628 arg_setup_state state;
1629
1630 if (tcp->flags & TCB_BPTSET) {
1631 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1632 return -1;
1633 }
1634
Roland McGrath3291ef22008-05-20 00:34:34 +00001635 /*
1636 * It's a silly kludge to initialize this with a search at runtime.
1637 * But it's better than maintaining another magic thing in the
1638 * godforsaken tables.
1639 */
1640 if (clone_scno[current_personality] == 0) {
1641 int i;
1642 for (i = 0; i < nsyscalls; ++i)
1643 if (sysent[i].sys_func == sys_clone) {
1644 clone_scno[current_personality] = i;
1645 break;
1646 }
1647 }
1648
Roland McGrath76989d72005-06-07 23:21:31 +00001649 switch (known_scno(tcp)) {
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001650# ifdef SYS_vfork
Roland McGrath9383c6c2003-01-18 00:19:31 +00001651 case SYS_vfork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001652# endif
1653# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001654 case SYS_fork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001655# endif
1656# if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001657 if (arg_setup (tcp, &state) < 0
1658 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1659 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001660 || change_syscall(tcp, clone_scno[current_personality]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001661 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1662 || set_arg1 (tcp, &state, 0) < 0
1663 || arg_finish_change (tcp, &state) < 0)
1664 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001665 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1666 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001667 tcp->flags |= TCB_BPTSET;
1668 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001669# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001670
1671 case SYS_clone:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001672# ifdef SYS_clone2
Roland McGrathd81f1d92003-01-09 06:53:34 +00001673 case SYS_clone2:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001674# endif
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001675 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1676 contrary to x86 SYS_vfork above. Even on x86 we turn the
1677 vfork semantics into plain fork - each application must not
1678 depend on the vfork specifics according to POSIX. We would
1679 hang waiting for the parent resume otherwise. We need to
1680 clear also CLONE_VM but only in the CLONE_VFORK case as
1681 otherwise we would break pthread_create. */
1682
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001683 if ((arg_setup (tcp, &state) < 0
1684 || set_arg0 (tcp, &state,
1685 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001686 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
1687 ? CLONE_VFORK | CLONE_VM : 0)) < 0
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001688 || arg_finish_change (tcp, &state) < 0))
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001689 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001690 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001691 tcp->inst[0] = tcp->u_arg[arg0_index];
1692 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001693 return 0;
1694
1695 default:
1696 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1697 tcp->scno, tcp->pid);
1698 break;
1699 }
1700
1701 return -1;
1702}
1703
1704int
1705clearbpt(tcp)
1706struct tcb *tcp;
1707{
1708 arg_setup_state state;
1709 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001710 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1711 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001712 || arg_finish_change (tcp, &state))
Andreas Schwab46ed50d2009-11-11 13:54:04 +01001713 if (errno != ESRCH) return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001714 tcp->flags &= ~TCB_BPTSET;
1715 return 0;
1716}
1717
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001718# else /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001719
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720int
1721setbpt(tcp)
1722struct tcb *tcp;
1723{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001724# ifdef LINUX
1725 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1726# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 /* We simply use the SunOS breakpoint code. */
1728
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001729 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001730 unsigned long inst;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001731# define LOOPA 0x30800000 /* ba,a 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732
1733 if (tcp->flags & TCB_BPTSET) {
1734 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1735 return -1;
1736 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001737 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1738 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 return -1;
1740 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001741 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001742 errno = 0;
1743 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1744 if(errno) {
1745 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001747 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748
1749 /*
1750 * XXX - BRUTAL MODE ON
1751 * We cannot set a real BPT in the child, since it will not be
1752 * traced at the moment it will reach the trap and would probably
1753 * die with a core dump.
1754 * Thus, we are force our way in by taking out two instructions
1755 * and insert an eternal loop instead, in expectance of the SIGSTOP
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001756 * generated by our PTRACE_ATTACH.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757 * Of cause, if we evaporate ourselves in the middle of all this...
1758 */
1759 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001760 inst = LOOPA;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001761# if defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001762 inst <<= 32;
1763 inst |= (tcp->inst[0] & 0xffffffffUL);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001764# endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07001765 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1766 if(errno) {
1767 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001769 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770 tcp->flags |= TCB_BPTSET;
1771
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001772# else /* !SPARC && !SPARC64 */
1773# ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001774 if (ia32) {
1775# define LOOP 0x0000feeb
1776 if (tcp->flags & TCB_BPTSET) {
1777 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1778 tcp->pid);
1779 return -1;
1780 }
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001781 if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001782 return -1;
1783 if (debug)
1784 fprintf(stderr, "[%d] setting bpt at %lx\n",
1785 tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001786 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1787 (char *) tcp->baddr, 0);
1788 if (errno) {
1789 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001790 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001791 }
1792 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1793 if (errno) {
1794 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001795 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001796 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001797 tcp->flags |= TCB_BPTSET;
1798 } else {
1799 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001800 * Our strategy here is to replace the bundle that
1801 * contained the clone() syscall with a bundle of the
1802 * form:
1803 *
1804 * { 1: br 1b; br 1b; br 1b }
1805 *
1806 * This ensures that the newly forked child will loop
1807 * endlessly until we've got a chance to attach to it.
1808 */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001809# define LOOP0 0x0000100000000017
1810# define LOOP1 0x4000000000200000
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001811 unsigned long addr, ipsr;
1812 pid_t pid;
1813
1814 pid = tcp->pid;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001815 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001816 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001817 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001818 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001819 /* store "ri" in low two bits */
1820 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001821
Roland McGratheb9e2e82009-06-02 16:49:22 -07001822 errno = 0;
1823 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1824 0);
1825 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1826 0);
1827 if (errno) {
1828 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001829 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001830 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001831
Roland McGratheb9e2e82009-06-02 16:49:22 -07001832 errno = 0;
1833 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1834 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1835 if (errno) {
1836 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001837 return -1;
1838 }
1839 tcp->flags |= TCB_BPTSET;
1840 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001841# else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001842
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001843# if defined (I386) || defined(X86_64)
1844# define LOOP 0x0000feeb
1845# elif defined (M68K)
1846# define LOOP 0x60fe0000
1847# elif defined (ALPHA)
1848# define LOOP 0xc3ffffff
1849# elif defined (POWERPC)
1850# define LOOP 0x48000000
1851# elif defined(ARM)
1852# define LOOP 0xEAFFFFFE
1853# elif defined(MIPS)
1854# define LOOP 0x1000ffff
1855# elif defined(S390)
1856# define LOOP 0xa7f40000 /* BRC 15,0 */
1857# elif defined(S390X)
1858# define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1859# elif defined(HPPA)
1860# define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1861# elif defined(SH)
1862# ifdef __LITTLE_ENDIAN__
1863# define LOOP 0x0000affe
1864# else
1865# define LOOP 0xfeaf0000
1866# endif
1867# else
1868# error unknown architecture
1869# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870
1871 if (tcp->flags & TCB_BPTSET) {
1872 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1873 return -1;
1874 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001875# if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001876 if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001878# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001879 if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001880 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001881# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001882 if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001883 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001884# elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001886# elif defined (ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001888# elif defined (MIPS)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001889 return -1; /* FIXME: I do not know what i do - Flo */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001890# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001891 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001893# elif defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001894 if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001895 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001896# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001897 if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001898 return -1;
1899 tcp->baddr &= ~0x03;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001900# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001901 if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
1902 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001903# else
1904# error unknown architecture
1905# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906 if (debug)
1907 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001908 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1909 if (errno) {
1910 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001912 }
1913 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1914 if (errno) {
1915 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001916 return -1;
1917 }
1918 tcp->flags |= TCB_BPTSET;
1919
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001920# endif /* !IA64 */
1921# endif /* !SPARC && !SPARC64 */
1922# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001924# ifdef SUNOS4
1925# ifdef SPARC /* This code is slightly sparc specific */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001927 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001928# define BPT 0x91d02001 /* ta 1 */
1929# define LOOP 0x10800000 /* ba 0 */
1930# define LOOPA 0x30800000 /* ba,a 0 */
1931# define NOP 0x01000000
1932# if LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933 static int loopdeloop[1] = {LOOPA};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001934# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001935 static int loopdeloop[2] = {LOOP, NOP};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001936# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937
1938 if (tcp->flags & TCB_BPTSET) {
1939 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1940 return -1;
1941 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001942 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1943 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944 return -1;
1945 }
1946 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001947 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1948 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1949 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 return -1;
1951 }
1952
1953 /*
1954 * XXX - BRUTAL MODE ON
1955 * We cannot set a real BPT in the child, since it will not be
1956 * traced at the moment it will reach the trap and would probably
1957 * die with a core dump.
1958 * Thus, we are force our way in by taking out two instructions
1959 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1960 * generated by out PTRACE_ATTACH.
1961 * Of cause, if we evaporate ourselves in the middle of all this...
1962 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001963 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001964 sizeof loopdeloop, (char *) loopdeloop) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001965 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 return -1;
1967 }
1968 tcp->flags |= TCB_BPTSET;
1969
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001970# endif /* SPARC */
1971# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001972
1973 return 0;
1974}
1975
1976int
1977clearbpt(tcp)
1978struct tcb *tcp;
1979{
1980
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001981# ifdef LINUX
1982 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1983# if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 long eip;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001985# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001987# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001989# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001991# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001992 long iaoq;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001993# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001994 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001995# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001997# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 /* Again, we borrow the SunOS breakpoint code. */
1999 if (!(tcp->flags & TCB_BPTSET)) {
2000 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2001 return -1;
2002 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002003 errno = 0;
2004 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2005 if(errno) {
2006 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 return -1;
2008 }
2009 tcp->flags &= ~TCB_BPTSET;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002010# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002011 if (ia32) {
2012 unsigned long addr;
2013
2014 if (debug)
2015 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2016 if (!(tcp->flags & TCB_BPTSET)) {
2017 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2018 return -1;
2019 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002020 errno = 0;
2021 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2022 if (errno) {
2023 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002024 return -1;
2025 }
2026 tcp->flags &= ~TCB_BPTSET;
2027
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002028 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002029 return -1;
2030 if (addr != tcp->baddr) {
2031 /* The breakpoint has not been reached yet. */
2032 if (debug)
2033 fprintf(stderr,
2034 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2035 addr, tcp->baddr);
2036 return 0;
2037 }
2038 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002039 unsigned long addr, ipsr;
2040 pid_t pid;
2041
2042 pid = tcp->pid;
2043
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002044 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002045 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002046 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002047 return -1;
2048
2049 /* restore original bundle: */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002050 errno = 0;
2051 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
2052 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
2053 if (errno) {
2054 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002055 return -1;
2056 }
2057
2058 /* restore original "ri" in ipsr: */
2059 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002060 errno = 0;
2061 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
2062 if (errno) {
2063 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002064 return -1;
2065 }
2066
2067 tcp->flags &= ~TCB_BPTSET;
2068
2069 if (addr != (tcp->baddr & ~0x3)) {
2070 /* the breakpoint has not been reached yet. */
2071 if (debug)
2072 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2073 addr, tcp->baddr);
2074 return 0;
2075 }
2076 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002077# else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078
2079 if (debug)
2080 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2081 if (!(tcp->flags & TCB_BPTSET)) {
2082 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2083 return -1;
2084 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002085 errno = 0;
2086 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2087 if (errno) {
2088 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089 return -1;
2090 }
2091 tcp->flags &= ~TCB_BPTSET;
2092
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002093# ifdef I386
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002094 if (upeek(tcp, 4*EIP, &eip) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 return -1;
2096 if (eip != tcp->baddr) {
2097 /* The breakpoint has not been reached yet. */
2098 if (debug)
2099 fprintf(stderr,
2100 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2101 eip, tcp->baddr);
2102 return 0;
2103 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002104# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002105 if (upeek(tcp, 8*RIP, &eip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002106 return -1;
2107 if (eip != tcp->baddr) {
2108 /* The breakpoint has not been reached yet. */
2109 if (debug)
2110 fprintf(stderr,
2111 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2112 eip, tcp->baddr);
2113 return 0;
2114 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002115# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002116 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002117 return -1;
2118 if (pc != tcp->baddr) {
2119 /* The breakpoint has not been reached yet. */
2120 if (debug)
2121 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2122 pc, tcp->baddr);
2123 return 0;
2124 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002125# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002126 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 return -1;
2128 if (pc != tcp->baddr) {
2129 /* The breakpoint has not been reached yet. */
2130 if (debug)
2131 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2132 pc, tcp->baddr);
2133 return 0;
2134 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002135# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002136 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 return -1;
2138 if (pc != tcp->baddr) {
2139 /* The breakpoint has not been reached yet. */
2140 if (debug)
2141 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2142 pc, tcp->baddr);
2143 return 0;
2144 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002145# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002146 if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002147 return -1;
2148 iaoq &= ~0x03;
2149 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2150 /* The breakpoint has not been reached yet. */
2151 if (debug)
2152 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2153 iaoq, tcp->baddr);
2154 return 0;
2155 }
2156 iaoq = tcp->baddr | 3;
2157 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2158 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2159 * has no significant effect.
2160 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002161 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2162 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002163# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002164 if (upeek(tcp, 4*REG_PC, &pc) < 0)
2165 return -1;
2166 if (pc != tcp->baddr) {
2167 /* The breakpoint has not been reached yet. */
2168 if (debug)
2169 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2170 pc, tcp->baddr);
2171 return 0;
2172 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002173
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002174# endif /* arch */
2175# endif /* !SPARC && !SPARC64 && !IA64 */
2176# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002178# ifdef SUNOS4
2179# ifdef SPARC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002181# if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00002182 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002183# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184
2185 if (!(tcp->flags & TCB_BPTSET)) {
2186 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2187 return -1;
2188 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002189 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 sizeof tcp->inst, (char *) tcp->inst) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002191 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192 return -1;
2193 }
2194 tcp->flags &= ~TCB_BPTSET;
2195
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002196# if !LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 /*
2198 * Since we don't have a single instruction breakpoint, we may have
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002199 * to adjust the program counter after removing our `breakpoint'.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002201 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2202 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 return -1;
2204 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002205 if ((regs.r_pc < tcp->baddr) ||
2206 (regs.r_pc > tcp->baddr + 4)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207 /* The breakpoint has not been reached yet */
2208 if (debug)
2209 fprintf(stderr,
2210 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002211 regs.r_pc, tcp->baddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 return 0;
2213 }
2214 if (regs.r_pc != tcp->baddr)
2215 if (debug)
2216 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2217 regs.r_pc, tcp->baddr);
2218
2219 regs.r_pc = tcp->baddr;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002220 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2221 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002222 return -1;
2223 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002224# endif /* LOOPA */
2225# endif /* SPARC */
2226# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227
2228 return 0;
2229}
2230
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002231# endif /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00002232
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002233#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002235
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236#ifdef SUNOS4
2237
2238static int
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002239getex(tcp, hdr)
2240struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002241struct exec *hdr;
2242{
2243 int n;
2244
2245 for (n = 0; n < sizeof *hdr; n += 4) {
2246 long res;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002247 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 return -1;
2249 memcpy(((char *) hdr) + n, &res, 4);
2250 }
2251 if (debug) {
2252 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2253 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2254 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2255 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2256 }
2257 return 0;
2258}
2259
2260int
2261fixvfork(tcp)
2262struct tcb *tcp;
2263{
2264 int pid = tcp->pid;
2265 /*
2266 * Change `vfork' in a freshly exec'ed dynamically linked
2267 * executable's (internal) symbol table to plain old `fork'
2268 */
2269
2270 struct exec hdr;
2271 struct link_dynamic dyn;
2272 struct link_dynamic_2 ld;
2273 char *strtab, *cp;
2274
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002275 if (getex(tcp, &hdr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276 return -1;
2277 if (!hdr.a_dynamic)
2278 return -1;
2279
2280 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2281 fprintf(stderr, "Cannot read DYNAMIC\n");
2282 return -1;
2283 }
2284 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2285 fprintf(stderr, "Cannot read link_dynamic_2\n");
2286 return -1;
2287 }
2288 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002289 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002290 return -1;
2291 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002292 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002293 (int)ld.ld_symb_size, strtab) < 0)
2294 goto err;
2295
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002296# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002297 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2298 fprintf(stderr, "[symbol: %s]\n", cp);
2299 cp += strlen(cp)+1;
2300 }
2301 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002302# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002303 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2304 if (strcmp(cp, "_vfork") == 0) {
2305 if (debug)
2306 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2307 strcpy(cp, "_fork");
2308 break;
2309 }
2310 cp += strlen(cp)+1;
2311 }
2312 if (cp < strtab + ld.ld_symb_size)
2313 /*
2314 * Write entire symbol table back to avoid
2315 * memory alignment bugs in ptrace
2316 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002317 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318 (int)ld.ld_symb_size, strtab) < 0)
2319 goto err;
2320
2321 free(strtab);
2322 return 0;
2323
2324err:
2325 free(strtab);
2326 return -1;
2327}
2328
2329#endif /* SUNOS4 */