blob: ee03338ad05b7327395a720f2838f8b5c865914c [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
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
151void
152tv_tv(tv, a, b)
153struct timeval *tv;
154int a;
155int b;
156{
157 tv->tv_sec = a;
158 tv->tv_usec = b;
159}
160
161int
162tv_nz(a)
163struct timeval *a;
164{
165 return a->tv_sec || a->tv_usec;
166}
167
168int
169tv_cmp(a, b)
170struct timeval *a, *b;
171{
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174 return -1;
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177 return 1;
178 return 0;
179}
180
181double
182tv_float(tv)
183struct timeval *tv;
184{
185 return tv->tv_sec + tv->tv_usec/1000000.0;
186}
187
188void
189tv_add(tv, a, b)
190struct timeval *tv, *a, *b;
191{
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
195 tv->tv_sec++;
196 tv->tv_usec -= 1000000;
197 }
198}
199
200void
201tv_sub(tv, a, b)
202struct timeval *tv, *a, *b;
203{
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
207 tv->tv_sec--;
208 tv->tv_usec += 1000000;
209 }
210}
211
212void
213tv_div(tv, a, n)
214struct timeval *tv, *a;
215int n;
216{
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
220}
221
222void
223tv_mul(tv, a, n)
224struct timeval *tv, *a;
225int n;
226{
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
230}
231
232char *
233xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000234const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235int val;
236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
244 * Print entry in struct xlat table, if there.
245 */
246void
247printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000248const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249int val;
250char *dflt;
251{
252 char *str = xlookup(xlat, val);
253
254 if (str)
255 tprintf("%s", str);
256 else
257 tprintf("%#x /* %s */", val, dflt);
258}
259
260/*
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
264 */
265int
266addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000267const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268int flags;
269{
270 int n;
271
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
275 flags &= ~xlat->val;
276 n++;
277 }
278 }
279 if (flags) {
280 tprintf("|%#x", flags);
281 n++;
282 }
283 return n;
284}
285
286int
287printflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000288const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289int flags;
290{
291 int n;
292 char *sep;
293
294 if (flags == 0 && xlat->val == 0) {
295 tprintf("%s", xlat->str);
296 return 1;
297 }
298
299 sep = "";
300 for (n = 0; xlat->str; xlat++) {
301 if (xlat->val && (flags & xlat->val) == xlat->val) {
302 tprintf("%s%s", sep, xlat->str);
303 flags &= ~xlat->val;
304 sep = "|";
305 n++;
306 }
307 }
308 if (flags) {
309 tprintf("%s%#x", sep, flags);
310 n++;
311 }
312 return n;
313}
314
315void
316printnum(tcp, addr, fmt)
317struct tcb *tcp;
318long addr;
319char *fmt;
320{
Roland McGratheb285352003-01-14 09:59:00 +0000321 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322
323 if (!addr) {
324 tprintf("NULL");
325 return;
326 }
327 if (umove(tcp, addr, &num) < 0) {
328 tprintf("%#lx", addr);
329 return;
330 }
331 tprintf("[");
332 tprintf(fmt, num);
333 tprintf("]");
334}
335
Roland McGrath6bc12202003-11-13 22:32:27 +0000336void
337printuid(text, uid)
338const char *text;
339unsigned long uid;
340{
341 tprintf("%s", text);
342 tprintf((uid == -1) ? "%ld" : "%lu", uid);
343}
344
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345static char path[MAXPATHLEN + 1];
346
347void
348string_quote(str)
349char *str;
350{
351 char buf[2 * MAXPATHLEN + 1];
352 char *s;
353
354 if (!strpbrk(str, "\"\'\\")) {
355 tprintf("\"%s\"", str);
356 return;
357 }
358 for (s = buf; *str; str++) {
359 switch (*str) {
360 case '\"': case '\'': case '\\':
361 *s++ = '\\'; *s++ = *str; break;
362 default:
363 *s++ = *str; break;
364 }
365 }
366 *s = '\0';
367 tprintf("\"%s\"", buf);
368}
369
370void
371printpath(tcp, addr)
372struct tcb *tcp;
373long addr;
374{
375 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
376 tprintf("%#lx", addr);
377 else
378 string_quote(path);
379 return;
380}
381
382void
383printpathn(tcp, addr, n)
384struct tcb *tcp;
385long addr;
386int n;
387{
388 if (umovestr(tcp, addr, n, path) < 0)
389 tprintf("%#lx", addr);
390 else {
391 path[n] = '\0';
392 string_quote(path);
393 }
394}
395
396void
397printstr(tcp, addr, len)
398struct tcb *tcp;
399long addr;
400int len;
401{
402 static unsigned char *str = NULL;
403 static char *outstr;
404 int i, n, c, usehex;
405 char *s, *outend;
406
407 if (!addr) {
408 tprintf("NULL");
409 return;
410 }
411 if (!str) {
412 if ((str = malloc(max_strlen)) == NULL
413 || (outstr = malloc(2*max_strlen)) == NULL) {
414 fprintf(stderr, "printstr: no memory\n");
415 tprintf("%#lx", addr);
416 return;
417 }
418 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000419 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000420 if (len < 0) {
421 n = max_strlen;
422 if (umovestr(tcp, addr, n, (char *) str) < 0) {
423 tprintf("%#lx", addr);
424 return;
425 }
426 }
427 else {
428 n = MIN(len, max_strlen);
429 if (umoven(tcp, addr, n, (char *) str) < 0) {
430 tprintf("%#lx", addr);
431 return;
432 }
433 }
434
435 usehex = 0;
436 if (xflag > 1)
437 usehex = 1;
438 else if (xflag) {
439 for (i = 0; i < n; i++) {
440 c = str[i];
441 if (len < 0 && c == '\0')
442 break;
443 if (!isprint(c) && !isspace(c)) {
444 usehex = 1;
445 break;
446 }
447 }
448 }
449
450 s = outstr;
451 *s++ = '\"';
452
453 if (usehex) {
454 for (i = 0; i < n; i++) {
455 c = str[i];
456 if (len < 0 && c == '\0')
457 break;
458 sprintf(s, "\\x%02x", c);
459 s += 4;
460 if (s > outend)
461 break;
462 }
463 }
464 else {
465 for (i = 0; i < n; i++) {
466 c = str[i];
467 if (len < 0 && c == '\0')
468 break;
469 switch (c) {
470 case '\"': case '\'': case '\\':
471 *s++ = '\\'; *s++ = c; break;
472 case '\f':
473 *s++ = '\\'; *s++ = 'f'; break;
474 case '\n':
475 *s++ = '\\'; *s++ = 'n'; break;
476 case '\r':
477 *s++ = '\\'; *s++ = 'r'; break;
478 case '\t':
479 *s++ = '\\'; *s++ = 't'; break;
480 case '\v':
481 *s++ = '\\'; *s++ = 'v'; break;
482 default:
483 if (isprint(c))
484 *s++ = c;
485 else if (i < n - 1 && isdigit(str[i + 1])) {
486 sprintf(s, "\\%03o", c);
487 s += 4;
488 }
489 else {
490 sprintf(s, "\\%o", c);
491 s += strlen(s);
492 }
493 break;
494 }
495 if (s > outend)
496 break;
497 }
498 }
499
500 *s++ = '\"';
501 if (i < len || (len < 0 && (i == n || s > outend))) {
502 *s++ = '.'; *s++ = '.'; *s++ = '.';
503 }
504 *s = '\0';
505 tprintf("%s", outstr);
506}
507
John Hughes1d08dcf2001-07-10 13:48:44 +0000508#if HAVE_SYS_UIO_H
509void
510dumpiov(tcp, len, addr)
511struct tcb * tcp;
512int len;
513long addr;
514{
515 struct iovec *iov;
516 int i;
517
Roland McGrath1e85cf92002-12-16 20:40:54 +0000518
John Hughes1d08dcf2001-07-10 13:48:44 +0000519 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
520 fprintf(stderr, "dump: No memory");
521 return;
522 }
523 if (umoven(tcp, addr,
524 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000525
John Hughes1d08dcf2001-07-10 13:48:44 +0000526 for (i = 0; i < len; i++) {
527 /* include the buffer number to make it easy to
528 * match up the trace with the source */
529 tprintf(" * %lu bytes in buffer %d\n",
530 (unsigned long)iov[i].iov_len, i);
531 dumpstr(tcp, (long) iov[i].iov_base,
532 iov[i].iov_len);
533 }
534 }
535 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000536
John Hughes1d08dcf2001-07-10 13:48:44 +0000537}
538#endif
539
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540void
541dumpstr(tcp, addr, len)
542struct tcb *tcp;
543long addr;
544int len;
545{
546 static int strsize = -1;
547 static unsigned char *str;
548 static char outstr[80];
549 char *s;
550 int i, j;
551
552 if (strsize < len) {
553 if (str)
554 free(str);
555 if ((str = malloc(len)) == NULL) {
556 fprintf(stderr, "dump: no memory\n");
557 return;
558 }
559 strsize = len;
560 }
561
562 if (umoven(tcp, addr, len, (char *) str) < 0)
563 return;
564
565 for (i = 0; i < len; i += 16) {
566 s = outstr;
567 sprintf(s, " | %05x ", i);
568 s += 9;
569 for (j = 0; j < 16; j++) {
570 if (j == 8)
571 *s++ = ' ';
572 if (i + j < len) {
573 sprintf(s, " %02x", str[i + j]);
574 s += 3;
575 }
576 else {
577 *s++ = ' '; *s++ = ' '; *s++ = ' ';
578 }
579 }
580 *s++ = ' '; *s++ = ' ';
581 for (j = 0; j < 16; j++) {
582 if (j == 8)
583 *s++ = ' ';
584 if (i + j < len) {
585 if (isprint(str[i + j]))
586 *s++ = str[i + j];
587 else
588 *s++ = '.';
589 }
590 else
591 *s++ = ' ';
592 }
593 tprintf("%s |\n", outstr);
594 }
595}
596
597#define PAGMASK (~(PAGSIZ - 1))
598/*
599 * move `len' bytes of data from process `pid'
600 * at address `addr' to our space at `laddr'
601 */
602int
603umoven(tcp, addr, len, laddr)
604struct tcb *tcp;
605long addr;
606int len;
607char *laddr;
608{
609
610#ifdef LINUX
611 int pid = tcp->pid;
612 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000613 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 union {
615 long val;
616 char x[sizeof(long)];
617 } u;
618
619 if (addr & (sizeof(long) - 1)) {
620 /* addr not a multiple of sizeof(long) */
621 n = addr - (addr & -sizeof(long)); /* residue */
622 addr &= -sizeof(long); /* residue */
623 errno = 0;
624 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
625 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000626 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627 /* Ran into 'end of memory' - stupid "printpath" */
628 return 0;
629 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000630 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 perror("ptrace: umoven");
632 return -1;
633 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000634 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000635 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
636 addr += sizeof(long), laddr += m, len -= m;
637 }
638 while (len) {
639 errno = 0;
640 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
641 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000642 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000643 /* Ran into 'end of memory' - stupid "printpath" */
644 return 0;
645 }
Roland McGrath4db26242003-01-30 20:15:19 +0000646 if (addr != 0)
647 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 return -1;
649 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000650 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
652 addr += sizeof(long), laddr += m, len -= m;
653 }
654#endif /* LINUX */
655
656#ifdef SUNOS4
657 int pid = tcp->pid;
658#if 0
659 int n, m;
660 union {
661 long val;
662 char x[sizeof(long)];
663 } u;
664
665 if (addr & (sizeof(long) - 1)) {
666 /* addr not a multiple of sizeof(long) */
667 n = addr - (addr & -sizeof(long)); /* residue */
668 addr &= -sizeof(long); /* residue */
669 errno = 0;
670 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
671 if (errno) {
672 perror("umoven");
673 return -1;
674 }
675 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
676 addr += sizeof(long), laddr += m, len -= m;
677 }
678 while (len) {
679 errno = 0;
680 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
681 if (errno) {
682 perror("umoven");
683 return -1;
684 }
685 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
686 addr += sizeof(long), laddr += m, len -= m;
687 }
688#else /* !oldway */
689 int n;
690
691 while (len) {
692 n = MIN(len, PAGSIZ);
693 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
694 if (ptrace(PTRACE_READDATA, pid,
695 (char *) addr, len, laddr) < 0) {
696 perror("umoven: ptrace(PTRACE_READDATA, ...)");
697 abort();
698 return -1;
699 }
700 len -= n;
701 addr += n;
702 laddr += n;
703 }
704#endif /* !oldway */
705#endif /* SUNOS4 */
706
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000707#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000708#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000709 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000710#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000711 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000713 lseek(fd, addr, SEEK_SET);
714 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000716#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717
718 return 0;
719}
720
721/*
722 * like `umove' but make the additional effort of looking
723 * for a terminating zero byte.
724 */
725int
726umovestr(tcp, addr, len, laddr)
727struct tcb *tcp;
728long addr;
729int len;
730char *laddr;
731{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000732#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000733#ifdef HAVE_MP_PROCFS
734 int fd = tcp->pfd_as;
735#else
736 int fd = tcp->pfd;
737#endif
738 /* Some systems (e.g. FreeBSD) can be upset if we read off the
739 end of valid memory, avoid this by trying to read up
740 to page boundaries. But we don't know what a page is (and
741 getpagesize(2) (if it exists) doesn't necessarily return
742 hardware page size). Assume all pages >= 1024 (a-historical
743 I know) */
744
745 int page = 1024; /* How to find this? */
746 int move = page - (addr & (page - 1));
747 int left = len;
748
749 lseek(fd, addr, SEEK_SET);
750
751 while (left) {
752 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000753 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000754 return left != len ? 0 : -1;
755 if (memchr (laddr, 0, move)) break;
756 left -= move;
757 laddr += move;
758 addr += move;
759 move = page;
760 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000761#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000762 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000763 int pid = tcp->pid;
764 int i, n, m;
765 union {
766 long val;
767 char x[sizeof(long)];
768 } u;
769
770 if (addr & (sizeof(long) - 1)) {
771 /* addr not a multiple of sizeof(long) */
772 n = addr - (addr & -sizeof(long)); /* residue */
773 addr &= -sizeof(long); /* residue */
774 errno = 0;
775 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
776 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000777 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 /* Ran into 'end of memory' - stupid "printpath" */
779 return 0;
780 }
781 perror("umovestr");
782 return -1;
783 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000784 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
786 while (n & (sizeof(long) - 1))
787 if (u.x[n++] == '\0')
788 return 0;
789 addr += sizeof(long), laddr += m, len -= m;
790 }
791 while (len) {
792 errno = 0;
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
794 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000795 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 /* Ran into 'end of memory' - stupid "printpath" */
797 return 0;
798 }
799 perror("umovestr");
800 return -1;
801 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000802 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
804 for (i = 0; i < sizeof(long); i++)
805 if (u.x[i] == '\0')
806 return 0;
807
808 addr += sizeof(long), laddr += m, len -= m;
809 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000810#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000811 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812}
813
814#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000815#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816#define PTRACE_WRITETEXT 101
817#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000818#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819#endif /* LINUX */
820
821#ifdef SUNOS4
822
823static int
824uload(cmd, pid, addr, len, laddr)
825int cmd;
826int pid;
827long addr;
828int len;
829char *laddr;
830{
831#if 0
832 int n;
833
834 while (len) {
835 n = MIN(len, PAGSIZ);
836 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
837 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
838 perror("uload: ptrace(PTRACE_WRITE, ...)");
839 return -1;
840 }
841 len -= n;
842 addr += n;
843 laddr += n;
844 }
845#else
846 int peek, poke;
847 int n, m;
848 union {
849 long val;
850 char x[sizeof(long)];
851 } u;
852
853 if (cmd == PTRACE_WRITETEXT) {
854 peek = PTRACE_PEEKTEXT;
855 poke = PTRACE_POKETEXT;
856 }
857 else {
858 peek = PTRACE_PEEKDATA;
859 poke = PTRACE_POKEDATA;
860 }
861 if (addr & (sizeof(long) - 1)) {
862 /* addr not a multiple of sizeof(long) */
863 n = addr - (addr & -sizeof(long)); /* residue */
864 addr &= -sizeof(long);
865 errno = 0;
866 u.val = ptrace(peek, pid, (char *) addr, 0);
867 if (errno) {
868 perror("uload: POKE");
869 return -1;
870 }
871 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
872 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
873 perror("uload: POKE");
874 return -1;
875 }
876 addr += sizeof(long), laddr += m, len -= m;
877 }
878 while (len) {
879 if (len < sizeof(long))
880 u.val = ptrace(peek, pid, (char *) addr, 0);
881 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
882 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
883 perror("uload: POKE");
884 return -1;
885 }
886 addr += sizeof(long), laddr += m, len -= m;
887 }
888#endif
889 return 0;
890}
891
892int
893tload(pid, addr, len, laddr)
894int pid;
895int addr, len;
896char *laddr;
897{
898 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
899}
900
901int
902dload(pid, addr, len, laddr)
903int pid;
904int addr;
905int len;
906char *laddr;
907{
908 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
909}
910
911#endif /* SUNOS4 */
912
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000913#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914
915int
916upeek(pid, off, res)
917int pid;
918long off;
919long *res;
920{
921 long val;
922
923#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
924 {
925 static int is_sun4m = -1;
926 struct utsname name;
927
928 /* Round up the usual suspects. */
929 if (is_sun4m == -1) {
930 if (uname(&name) < 0) {
931 perror("upeek: uname?");
932 exit(1);
933 }
934 is_sun4m = strcmp(name.machine, "sun4m") == 0;
935 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000936 extern const struct xlat struct_user_offsets[];
937 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938
939 for (x = struct_user_offsets; x->str; x++)
940 x->val += 1024;
941 }
942 }
943 if (is_sun4m)
944 off += 1024;
945 }
946#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
947 errno = 0;
948 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
949 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000950 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000951 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000952 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 return -1;
954 }
955 *res = val;
956 return 0;
957}
958
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000959#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960
961long
962getpc(tcp)
963struct tcb *tcp;
964{
965
966#ifdef LINUX
967 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000968#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
970 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000971#elif defined(X86_64)
972 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
973 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000974#elif defined(IA64)
975 if (upeek(tcp->pid, PT_B0, &pc) < 0)
976 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000977#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 if (upeek(tcp->pid, 4*15, &pc) < 0)
979 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000980#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000981 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000983#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
985 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000986#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 if (upeek(tcp->pid, REG_PC, &pc) < 0)
988 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000989#elif defined(MIPS)
990 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
991 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000992#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000993 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
995 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000996 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000997#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000998 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000999 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001000#elif defined(HPPA)
1001 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1002 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001003#elif defined(SH)
1004 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1005 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001006#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001007 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1008 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001009#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 return pc;
1011#endif /* LINUX */
1012
1013#ifdef SUNOS4
1014 /*
1015 * Return current program counter for `pid'
1016 * Assumes PC is never 0xffffffff
1017 */
1018 struct regs regs;
1019
1020 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1021 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1022 return -1;
1023 }
1024 return regs.r_pc;
1025#endif /* SUNOS4 */
1026
1027#ifdef SVR4
1028 /* XXX */
1029 return 0;
1030#endif /* SVR4 */
1031
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001032#ifdef FREEBSD
1033 struct reg regs;
1034 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1035 return regs.r_eip;
1036#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037}
1038
1039void
1040printcall(tcp)
1041struct tcb *tcp;
1042{
1043
1044#ifdef LINUX
1045#ifdef I386
1046 long eip;
1047
1048 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1049 tprintf("[????????] ");
1050 return;
1051 }
1052 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001053
1054#elif defined(S390) || defined(S390X)
1055 long psw;
1056 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1057 tprintf("[????????] ");
1058 return;
1059 }
1060#ifdef S390
1061 tprintf("[%08lx] ", psw);
1062#elif S390X
1063 tprintf("[%16lx] ", psw);
1064#endif
1065
Michal Ludvig0e035502002-09-23 15:41:01 +00001066#elif defined(X86_64)
1067 long rip;
1068
1069 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1070 tprintf("[????????] ");
1071 return;
1072 }
1073 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001074#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001075 long ip;
1076
1077 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1078 tprintf("[????????] ");
1079 return;
1080 }
1081 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001082#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083 long pc;
1084
Roland McGratheb285352003-01-14 09:59:00 +00001085 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086 tprintf ("[????????] ");
1087 return;
1088 }
1089 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001090#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 long pc;
1092
1093 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1094 tprintf ("[????????] ");
1095 return;
1096 }
1097 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001098#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 long pc;
1100
1101 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1102 tprintf ("[????????] ");
1103 return;
1104 }
1105 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001106#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001107 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1109 tprintf("[????????] ");
1110 return;
1111 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001112 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001113#elif defined(HPPA)
1114 long pc;
1115
1116 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1117 tprintf ("[????????] ");
1118 return;
1119 }
1120 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001121#elif defined(MIPS)
1122 long pc;
1123
1124 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1125 tprintf ("[????????] ");
1126 return;
1127 }
1128 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001129#elif defined(SH)
1130 long pc;
1131
1132 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1133 tprintf ("[????????] ");
1134 return;
1135 }
1136 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001137#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001138 long pc;
1139
1140 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1141 tprintf ("[????????] ");
1142 return;
1143 }
1144 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001145#elif defined(ARM)
1146 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001147
Roland McGrathef388682003-06-03 23:28:59 +00001148 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1149 tprintf("[????????] ");
1150 return;
1151 }
1152 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001153#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154#endif /* LINUX */
1155
1156#ifdef SUNOS4
1157 struct regs regs;
1158
1159 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1160 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1161 tprintf("[????????] ");
1162 return;
1163 }
1164 tprintf("[%08x] ", regs.r_o7);
1165#endif /* SUNOS4 */
1166
1167#ifdef SVR4
1168 /* XXX */
1169 tprintf("[????????] ");
1170#endif
1171
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001172#ifdef FREEBSD
1173 struct reg regs;
1174 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1175 tprintf("[%08x] ", regs.r_eip);
1176#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177}
1178
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001179#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180
Roland McGrathd81f1d92003-01-09 06:53:34 +00001181#if defined LINUX
1182
1183#include <sys/syscall.h>
1184#ifndef CLONE_PTRACE
1185# define CLONE_PTRACE 0x00002000
1186#endif
1187
1188#ifdef IA64
1189
Roland McGrath08267b82004-02-20 22:56:43 +00001190/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1191 subsystem has them for x86... */
1192#define SYS_fork 2
1193#define SYS_vfork 190
1194
Roland McGrathd81f1d92003-01-09 06:53:34 +00001195typedef unsigned long *arg_setup_state;
1196
1197static int
1198arg_setup(struct tcb *tcp, arg_setup_state *state)
1199{
1200 unsigned long *bsp, cfm, sof, sol;
1201
Roland McGrath08267b82004-02-20 22:56:43 +00001202 if (ia32)
1203 return 0;
1204
Roland McGrathd81f1d92003-01-09 06:53:34 +00001205 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1206 return -1;
1207 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1208 return -1;
1209
1210 sof = (cfm >> 0) & 0x7f;
1211 sol = (cfm >> 7) & 0x7f;
1212 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1213
1214 *state = bsp;
1215 return 0;
1216}
1217
1218# define arg_finish_change(tcp, state) 0
1219
1220#ifdef SYS_fork
1221static int
1222get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1223{
Roland McGrath08267b82004-02-20 22:56:43 +00001224 int ret;
1225
1226 if (ia32)
1227 ret = upeek (tcp->pid, PT_R11, valp);
1228 else
1229 ret = umoven (tcp,
1230 (unsigned long) ia64_rse_skip_regs(*state, 0),
1231 sizeof(long), (void *) valp);
1232 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001233}
1234
1235static int
1236get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1237{
Roland McGrath08267b82004-02-20 22:56:43 +00001238 int ret;
1239
1240 if (ia32)
1241 ret = upeek (tcp->pid, PT_R9, valp);
1242 else
1243 ret = umoven (tcp,
1244 (unsigned long) ia64_rse_skip_regs(*state, 1),
1245 sizeof(long), (void *) valp);
1246 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001247}
1248#endif
1249
1250static int
1251set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1252{
Roland McGrath08267b82004-02-20 22:56:43 +00001253 int req = PTRACE_POKEDATA;
1254 void *ap;
1255
1256 if (ia32) {
1257 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1258 req = PTRACE_POKEUSER;
1259 } else
1260 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001262 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263 return errno ? -1 : 0;
1264}
1265
1266static int
1267set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1268{
Roland McGrath08267b82004-02-20 22:56:43 +00001269 int req = PTRACE_POKEDATA;
1270 void *ap;
1271
1272 if (ia32) {
1273 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1274 req = PTRACE_POKEUSER;
1275 } else
1276 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001278 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279 return errno ? -1 : 0;
1280}
1281
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001282#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
1284typedef struct regs arg_setup_state;
1285
1286# define arg_setup(tcp, state) \
1287 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1288# define arg_finish_change(tcp, state) \
1289 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1290
1291# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1292# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1293# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1294# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001295# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296
1297#else
1298
1299# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001300/* Note: this is only true for the `clone' system call, which handles
1301 arguments specially. We could as well say that its first two arguments
1302 are swapped relative to other architectures, but that would just be
1303 another #ifdef in the calls. */
1304# define arg0_offset PT_GPR3
1305# define arg1_offset PT_ORIGGPR2
1306# define restore_arg0(tcp, state, val) ((void) (state), 0)
1307# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001308# define arg0_index 1
1309# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310# elif defined (ALPHA) || defined (MIPS)
1311# define arg0_offset REG_A0
1312# define arg1_offset (REG_A0+1)
1313# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001314# define arg0_offset (sizeof(unsigned long)*PT_R3)
1315# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001316# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317# elif defined (HPPA)
1318# define arg0_offset PT_GR26
1319# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001320# elif defined (X86_64)
1321# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1322# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001323# elif defined (SH)
1324# define arg0_offset (4*(REG_REG0+4))
1325# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001326# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001327 /* ABI defines arg0 & 1 in r2 & r3 */
1328# define arg0_offset (REG_OFFSET+16)
1329# define arg1_offset (REG_OFFSET+24)
1330# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001331# else
1332# define arg0_offset 0
1333# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001334# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001335# define restore_arg0(tcp, state, val) 0
1336# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337# endif
1338
1339typedef int arg_setup_state;
1340
1341# define arg_setup(tcp, state) (0)
1342# define arg_finish_change(tcp, state) 0
1343# define get_arg0(tcp, cookie, valp) \
1344 (upeek ((tcp)->pid, arg0_offset, (valp)))
1345# define get_arg1(tcp, cookie, valp) \
1346 (upeek ((tcp)->pid, arg1_offset, (valp)))
1347
1348static int
1349set_arg0 (struct tcb *tcp, void *cookie, long val)
1350{
1351 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1352}
1353
1354static int
1355set_arg1 (struct tcb *tcp, void *cookie, long val)
1356{
1357 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1358}
1359
1360#endif
1361
Roland McGrathe1df47f2003-01-14 09:46:15 +00001362#ifndef restore_arg0
1363# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1364#endif
1365#ifndef restore_arg1
1366# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1367#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001368
Roland McGrath90d0afd2004-03-01 21:05:16 +00001369#ifndef arg0_index
1370# define arg0_index 0
1371# define arg1_index 1
1372#endif
1373
Roland McGrathd81f1d92003-01-09 06:53:34 +00001374int
1375setbpt(tcp)
1376struct tcb *tcp;
1377{
1378 extern int change_syscall(struct tcb *, int);
1379 arg_setup_state state;
1380
1381 if (tcp->flags & TCB_BPTSET) {
1382 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1383 return -1;
1384 }
1385
1386 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001387#ifdef SYS_vfork
1388 case SYS_vfork:
1389#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001390#ifdef SYS_fork
1391 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001392#endif
1393#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001394 if (arg_setup (tcp, &state) < 0
1395 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1396 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1397 || change_syscall(tcp, SYS_clone) < 0
1398 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1399 || set_arg1 (tcp, &state, 0) < 0
1400 || arg_finish_change (tcp, &state) < 0)
1401 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001402 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1403 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001404 tcp->flags |= TCB_BPTSET;
1405 return 0;
1406#endif
1407
1408 case SYS_clone:
1409#ifdef SYS_clone2
1410 case SYS_clone2:
1411#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001412 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001414 || set_arg0 (tcp, &state,
1415 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001416 || arg_finish_change (tcp, &state) < 0))
1417 return -1;
1418 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001419 tcp->inst[0] = tcp->u_arg[arg0_index];
1420 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001421 return 0;
1422
1423 default:
1424 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1425 tcp->scno, tcp->pid);
1426 break;
1427 }
1428
1429 return -1;
1430}
1431
1432int
1433clearbpt(tcp)
1434struct tcb *tcp;
1435{
1436 arg_setup_state state;
1437 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001438 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1439 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001440 || arg_finish_change (tcp, &state))
1441 return -1;
1442 tcp->flags &= ~TCB_BPTSET;
1443 return 0;
1444}
1445
1446#else
1447
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448int
1449setbpt(tcp)
1450struct tcb *tcp;
1451{
1452
1453#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001454#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 /* We simply use the SunOS breakpoint code. */
1456
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001457 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001458 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459#define LOOPA 0x30800000 /* ba,a 0 */
1460
1461 if (tcp->flags & TCB_BPTSET) {
1462 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1463 return -1;
1464 }
1465 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1466 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1467 return -1;
1468 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001469 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470 errno = 0;
1471 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1472 if(errno) {
1473 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1474 return -1;
1475 }
1476
1477 /*
1478 * XXX - BRUTAL MODE ON
1479 * We cannot set a real BPT in the child, since it will not be
1480 * traced at the moment it will reach the trap and would probably
1481 * die with a core dump.
1482 * Thus, we are force our way in by taking out two instructions
1483 * and insert an eternal loop instead, in expectance of the SIGSTOP
1484 * generated by out PTRACE_ATTACH.
1485 * Of cause, if we evaporate ourselves in the middle of all this...
1486 */
1487 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001488 inst = LOOPA;
1489#if defined (SPARC64)
1490 inst <<= 32;
1491 inst |= (tcp->inst[0] & 0xffffffffUL);
1492#endif
1493 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 if(errno) {
1495 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1496 return -1;
1497 }
1498 tcp->flags |= TCB_BPTSET;
1499
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001500#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001501#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001502 if (ia32) {
1503# define LOOP 0x0000feeb
1504 if (tcp->flags & TCB_BPTSET) {
1505 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1506 tcp->pid);
1507 return -1;
1508 }
1509 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1510 return -1;
1511 if (debug)
1512 fprintf(stderr, "[%d] setting bpt at %lx\n",
1513 tcp->pid, tcp->baddr);
1514 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1515 (char *) tcp->baddr, 0);
1516 if (errno) {
1517 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1518 return -1;
1519 }
1520 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1521 if (errno) {
1522 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1523 return -1;
1524 }
1525 tcp->flags |= TCB_BPTSET;
1526 } else {
1527 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001528 * Our strategy here is to replace the bundle that
1529 * contained the clone() syscall with a bundle of the
1530 * form:
1531 *
1532 * { 1: br 1b; br 1b; br 1b }
1533 *
1534 * This ensures that the newly forked child will loop
1535 * endlessly until we've got a chance to attach to it.
1536 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001537# define LOOP0 0x0000100000000017
1538# define LOOP1 0x4000000000200000
1539 unsigned long addr, ipsr;
1540 pid_t pid;
1541
1542 pid = tcp->pid;
1543 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1544 return -1;
1545 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1546 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001547 /* store "ri" in low two bits */
1548 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001549
1550 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001551 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1552 0);
1553 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1554 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001555 if (errno) {
1556 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1557 return -1;
1558 }
1559
1560 errno = 0;
1561 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1562 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1563 if (errno) {
1564 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1565 return -1;
1566 }
1567 tcp->flags |= TCB_BPTSET;
1568 }
1569#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570
Michal Ludvig0e035502002-09-23 15:41:01 +00001571#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572#define LOOP 0x0000feeb
1573#elif defined (M68K)
1574#define LOOP 0x60fe0000
1575#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001576#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001578#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001580#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001581#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001582#define LOOP 0x1000ffff
1583#elif defined(S390)
1584#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001585#elif defined(S390X)
1586#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001587#elif defined(HPPA)
1588#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001589#elif defined(SH)
1590#ifdef __LITTLE_ENDIAN__
1591#define LOOP 0x0000affe
1592#else
1593#define LOOP 0xfeaf0000
1594#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595#else
1596#error unknown architecture
1597#endif
1598
1599 if (tcp->flags & TCB_BPTSET) {
1600 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1601 return -1;
1602 }
1603#if defined (I386)
1604 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1605 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001606#elif defined (X86_64)
1607 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1608 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609#elif defined (M68K)
1610 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1611 return -1;
1612#elif defined (ALPHA)
1613 return -1;
1614#elif defined (ARM)
1615 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001616#elif defined (MIPS)
1617 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001619 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001621#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001622 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1623 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001624#elif defined(HPPA)
1625 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1626 return -1;
1627 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001628#elif defined(SH)
1629 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1630 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631#else
1632#error unknown architecture
1633#endif
1634 if (debug)
1635 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1636 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1637 if (errno) {
1638 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1639 return -1;
1640 }
1641 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1642 if (errno) {
1643 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1644 return -1;
1645 }
1646 tcp->flags |= TCB_BPTSET;
1647
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001648#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001649#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650#endif /* LINUX */
1651
1652#ifdef SUNOS4
1653#ifdef SPARC /* This code is slightly sparc specific */
1654
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001655 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656#define BPT 0x91d02001 /* ta 1 */
1657#define LOOP 0x10800000 /* ba 0 */
1658#define LOOPA 0x30800000 /* ba,a 0 */
1659#define NOP 0x01000000
1660#if LOOPA
1661 static int loopdeloop[1] = {LOOPA};
1662#else
1663 static int loopdeloop[2] = {LOOP, NOP};
1664#endif
1665
1666 if (tcp->flags & TCB_BPTSET) {
1667 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1668 return -1;
1669 }
1670 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1671 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1672 return -1;
1673 }
1674 tcp->baddr = regs.r_o7 + 8;
1675 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1676 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1677 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1678 return -1;
1679 }
1680
1681 /*
1682 * XXX - BRUTAL MODE ON
1683 * We cannot set a real BPT in the child, since it will not be
1684 * traced at the moment it will reach the trap and would probably
1685 * die with a core dump.
1686 * Thus, we are force our way in by taking out two instructions
1687 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1688 * generated by out PTRACE_ATTACH.
1689 * Of cause, if we evaporate ourselves in the middle of all this...
1690 */
1691 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1692 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1693 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1694 return -1;
1695 }
1696 tcp->flags |= TCB_BPTSET;
1697
1698#endif /* SPARC */
1699#endif /* SUNOS4 */
1700
1701 return 0;
1702}
1703
1704int
1705clearbpt(tcp)
1706struct tcb *tcp;
1707{
1708
1709#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001710#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001712#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001714#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001716#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001718#elif defined(HPPA)
1719 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001720#elif defined(SH)
1721 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001722#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001724#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 /* Again, we borrow the SunOS breakpoint code. */
1726 if (!(tcp->flags & TCB_BPTSET)) {
1727 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1728 return -1;
1729 }
1730 errno = 0;
1731 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1732 if(errno) {
1733 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1734 return -1;
1735 }
1736 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001737#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001738 if (ia32) {
1739 unsigned long addr;
1740
1741 if (debug)
1742 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1743 if (!(tcp->flags & TCB_BPTSET)) {
1744 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1745 return -1;
1746 }
1747 errno = 0;
1748 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1749 if (errno) {
1750 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1751 return -1;
1752 }
1753 tcp->flags &= ~TCB_BPTSET;
1754
1755 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1756 return -1;
1757 if (addr != tcp->baddr) {
1758 /* The breakpoint has not been reached yet. */
1759 if (debug)
1760 fprintf(stderr,
1761 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1762 addr, tcp->baddr);
1763 return 0;
1764 }
1765 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001766 unsigned long addr, ipsr;
1767 pid_t pid;
1768
1769 pid = tcp->pid;
1770
1771 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1772 return -1;
1773 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1774 return -1;
1775
1776 /* restore original bundle: */
1777 errno = 0;
1778 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1779 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1780 if (errno) {
1781 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1782 return -1;
1783 }
1784
1785 /* restore original "ri" in ipsr: */
1786 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1787 errno = 0;
1788 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1789 if (errno) {
1790 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1791 return -1;
1792 }
1793
1794 tcp->flags &= ~TCB_BPTSET;
1795
1796 if (addr != (tcp->baddr & ~0x3)) {
1797 /* the breakpoint has not been reached yet. */
1798 if (debug)
1799 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1800 addr, tcp->baddr);
1801 return 0;
1802 }
1803 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001804#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805
1806 if (debug)
1807 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1808 if (!(tcp->flags & TCB_BPTSET)) {
1809 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1810 return -1;
1811 }
1812 errno = 0;
1813 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1814 if (errno) {
1815 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1816 return -1;
1817 }
1818 tcp->flags &= ~TCB_BPTSET;
1819
1820#ifdef I386
1821 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1822 return -1;
1823 if (eip != tcp->baddr) {
1824 /* The breakpoint has not been reached yet. */
1825 if (debug)
1826 fprintf(stderr,
1827 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1828 eip, tcp->baddr);
1829 return 0;
1830 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001831#elif defined(X86_64)
1832 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1833 return -1;
1834 if (eip != tcp->baddr) {
1835 /* The breakpoint has not been reached yet. */
1836 if (debug)
1837 fprintf(stderr,
1838 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1839 eip, tcp->baddr);
1840 return 0;
1841 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001842#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001843 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 return -1;
1845 if (pc != tcp->baddr) {
1846 /* The breakpoint has not been reached yet. */
1847 if (debug)
1848 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1849 pc, tcp->baddr);
1850 return 0;
1851 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001852#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1854 return -1;
1855 if (pc != tcp->baddr) {
1856 /* The breakpoint has not been reached yet. */
1857 if (debug)
1858 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1859 pc, tcp->baddr);
1860 return 0;
1861 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001862#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1864 return -1;
1865 if (pc != tcp->baddr) {
1866 /* The breakpoint has not been reached yet. */
1867 if (debug)
1868 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1869 pc, tcp->baddr);
1870 return 0;
1871 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001872#elif defined(HPPA)
1873 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1874 return -1;
1875 iaoq &= ~0x03;
1876 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1877 /* The breakpoint has not been reached yet. */
1878 if (debug)
1879 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1880 iaoq, tcp->baddr);
1881 return 0;
1882 }
1883 iaoq = tcp->baddr | 3;
1884 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1885 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1886 * has no significant effect.
1887 */
1888 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1889 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001890#elif defined(SH)
1891 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1892 return -1;
1893 if (pc != tcp->baddr) {
1894 /* The breakpoint has not been reached yet. */
1895 if (debug)
1896 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1897 pc, tcp->baddr);
1898 return 0;
1899 }
1900
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001901#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001902#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903#endif /* LINUX */
1904
1905#ifdef SUNOS4
1906#ifdef SPARC
1907
1908#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001909 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910#endif
1911
1912 if (!(tcp->flags & TCB_BPTSET)) {
1913 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1914 return -1;
1915 }
1916 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1917 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1918 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1919 return -1;
1920 }
1921 tcp->flags &= ~TCB_BPTSET;
1922
1923#if !LOOPA
1924 /*
1925 * Since we don't have a single instruction breakpoint, we may have
1926 * to adjust the program counter after removing the our `breakpoint'.
1927 */
1928 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1929 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1930 return -1;
1931 }
1932 if ((regs.r_pc < tcp->baddr) ||
1933 (regs.r_pc > tcp->baddr + 4)) {
1934 /* The breakpoint has not been reached yet */
1935 if (debug)
1936 fprintf(stderr,
1937 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1938 regs.r_pc, tcp->parent->baddr);
1939 return 0;
1940 }
1941 if (regs.r_pc != tcp->baddr)
1942 if (debug)
1943 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1944 regs.r_pc, tcp->baddr);
1945
1946 regs.r_pc = tcp->baddr;
1947 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1948 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1949 return -1;
1950 }
1951#endif /* LOOPA */
1952#endif /* SPARC */
1953#endif /* SUNOS4 */
1954
1955 return 0;
1956}
1957
Roland McGrathd81f1d92003-01-09 06:53:34 +00001958#endif
1959
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961
1962#ifdef SUNOS4
1963
1964static int
1965getex(pid, hdr)
1966int pid;
1967struct exec *hdr;
1968{
1969 int n;
1970
1971 for (n = 0; n < sizeof *hdr; n += 4) {
1972 long res;
1973 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1974 return -1;
1975 memcpy(((char *) hdr) + n, &res, 4);
1976 }
1977 if (debug) {
1978 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1979 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1980 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1981 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1982 }
1983 return 0;
1984}
1985
1986int
1987fixvfork(tcp)
1988struct tcb *tcp;
1989{
1990 int pid = tcp->pid;
1991 /*
1992 * Change `vfork' in a freshly exec'ed dynamically linked
1993 * executable's (internal) symbol table to plain old `fork'
1994 */
1995
1996 struct exec hdr;
1997 struct link_dynamic dyn;
1998 struct link_dynamic_2 ld;
1999 char *strtab, *cp;
2000
2001 if (getex(pid, &hdr) < 0)
2002 return -1;
2003 if (!hdr.a_dynamic)
2004 return -1;
2005
2006 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2007 fprintf(stderr, "Cannot read DYNAMIC\n");
2008 return -1;
2009 }
2010 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2011 fprintf(stderr, "Cannot read link_dynamic_2\n");
2012 return -1;
2013 }
2014 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2015 fprintf(stderr, "fixvfork: out of memory\n");
2016 return -1;
2017 }
2018 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2019 (int)ld.ld_symb_size, strtab) < 0)
2020 goto err;
2021
2022#if 0
2023 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2024 fprintf(stderr, "[symbol: %s]\n", cp);
2025 cp += strlen(cp)+1;
2026 }
2027 return 0;
2028#endif
2029 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2030 if (strcmp(cp, "_vfork") == 0) {
2031 if (debug)
2032 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2033 strcpy(cp, "_fork");
2034 break;
2035 }
2036 cp += strlen(cp)+1;
2037 }
2038 if (cp < strtab + ld.ld_symb_size)
2039 /*
2040 * Write entire symbol table back to avoid
2041 * memory alignment bugs in ptrace
2042 */
2043 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2044 (int)ld.ld_symb_size, strtab) < 0)
2045 goto err;
2046
2047 free(strtab);
2048 return 0;
2049
2050err:
2051 free(strtab);
2052 return -1;
2053}
2054
2055#endif /* SUNOS4 */