blob: 68b0f7ded122c02d4021755e2448f5ba40b28b1d [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)
234struct xlat *xlat;
235int 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)
248struct xlat *xlat;
249int 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)
267struct xlat *xlat;
268int 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)
288struct xlat *xlat;
289int 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) {
936 extern struct xlat struct_user_offsets[];
937 struct xlat *x;
938
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);
Michal Ludvig0e035502002-09-23 15:41:01 +00001053#elif defined(X86_64)
1054 long rip;
1055
1056 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1057 tprintf("[????????] ");
1058 return;
1059 }
1060 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001061#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001062 long ip;
1063
1064 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1065 tprintf("[????????] ");
1066 return;
1067 }
1068 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001069#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 long pc;
1071
Roland McGratheb285352003-01-14 09:59:00 +00001072 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 tprintf ("[????????] ");
1074 return;
1075 }
1076 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001077#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 long pc;
1079
1080 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1081 tprintf ("[????????] ");
1082 return;
1083 }
1084 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001085#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086 long pc;
1087
1088 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1089 tprintf ("[????????] ");
1090 return;
1091 }
1092 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001093#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001094 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1096 tprintf("[????????] ");
1097 return;
1098 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001099 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001100#elif defined(HPPA)
1101 long pc;
1102
1103 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1104 tprintf ("[????????] ");
1105 return;
1106 }
1107 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001108#elif defined(MIPS)
1109 long pc;
1110
1111 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1112 tprintf ("[????????] ");
1113 return;
1114 }
1115 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001116#elif defined(SH)
1117 long pc;
1118
1119 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1120 tprintf ("[????????] ");
1121 return;
1122 }
1123 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001124#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001125 long pc;
1126
1127 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1128 tprintf ("[????????] ");
1129 return;
1130 }
1131 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001132#elif defined(ARM)
1133 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001134
Roland McGrathef388682003-06-03 23:28:59 +00001135 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1136 tprintf("[????????] ");
1137 return;
1138 }
1139 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001140#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141#endif /* LINUX */
1142
1143#ifdef SUNOS4
1144 struct regs regs;
1145
1146 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1147 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1148 tprintf("[????????] ");
1149 return;
1150 }
1151 tprintf("[%08x] ", regs.r_o7);
1152#endif /* SUNOS4 */
1153
1154#ifdef SVR4
1155 /* XXX */
1156 tprintf("[????????] ");
1157#endif
1158
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001159#ifdef FREEBSD
1160 struct reg regs;
1161 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1162 tprintf("[%08x] ", regs.r_eip);
1163#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164}
1165
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001166#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167
Roland McGrathd81f1d92003-01-09 06:53:34 +00001168#if defined LINUX
1169
1170#include <sys/syscall.h>
1171#ifndef CLONE_PTRACE
1172# define CLONE_PTRACE 0x00002000
1173#endif
1174
1175#ifdef IA64
1176
Roland McGrath08267b82004-02-20 22:56:43 +00001177/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1178 subsystem has them for x86... */
1179#define SYS_fork 2
1180#define SYS_vfork 190
1181
Roland McGrathd81f1d92003-01-09 06:53:34 +00001182typedef unsigned long *arg_setup_state;
1183
1184static int
1185arg_setup(struct tcb *tcp, arg_setup_state *state)
1186{
1187 unsigned long *bsp, cfm, sof, sol;
1188
Roland McGrath08267b82004-02-20 22:56:43 +00001189 if (ia32)
1190 return 0;
1191
Roland McGrathd81f1d92003-01-09 06:53:34 +00001192 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1193 return -1;
1194 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1195 return -1;
1196
1197 sof = (cfm >> 0) & 0x7f;
1198 sol = (cfm >> 7) & 0x7f;
1199 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1200
1201 *state = bsp;
1202 return 0;
1203}
1204
1205# define arg_finish_change(tcp, state) 0
1206
1207#ifdef SYS_fork
1208static int
1209get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1210{
Roland McGrath08267b82004-02-20 22:56:43 +00001211 int ret;
1212
1213 if (ia32)
1214 ret = upeek (tcp->pid, PT_R11, valp);
1215 else
1216 ret = umoven (tcp,
1217 (unsigned long) ia64_rse_skip_regs(*state, 0),
1218 sizeof(long), (void *) valp);
1219 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220}
1221
1222static int
1223get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1224{
Roland McGrath08267b82004-02-20 22:56:43 +00001225 int ret;
1226
1227 if (ia32)
1228 ret = upeek (tcp->pid, PT_R9, valp);
1229 else
1230 ret = umoven (tcp,
1231 (unsigned long) ia64_rse_skip_regs(*state, 1),
1232 sizeof(long), (void *) valp);
1233 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001234}
1235#endif
1236
1237static int
1238set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1239{
Roland McGrath08267b82004-02-20 22:56:43 +00001240 int req = PTRACE_POKEDATA;
1241 void *ap;
1242
1243 if (ia32) {
1244 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1245 req = PTRACE_POKEUSER;
1246 } else
1247 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001249 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001250 return errno ? -1 : 0;
1251}
1252
1253static int
1254set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1255{
Roland McGrath08267b82004-02-20 22:56:43 +00001256 int req = PTRACE_POKEDATA;
1257 void *ap;
1258
1259 if (ia32) {
1260 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1261 req = PTRACE_POKEUSER;
1262 } else
1263 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001264 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001265 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001266 return errno ? -1 : 0;
1267}
1268
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001269#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270
1271typedef struct regs arg_setup_state;
1272
1273# define arg_setup(tcp, state) \
1274 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1275# define arg_finish_change(tcp, state) \
1276 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1277
1278# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1279# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1280# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1281# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001282# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
1284#else
1285
1286# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001287/* Note: this is only true for the `clone' system call, which handles
1288 arguments specially. We could as well say that its first two arguments
1289 are swapped relative to other architectures, but that would just be
1290 another #ifdef in the calls. */
1291# define arg0_offset PT_GPR3
1292# define arg1_offset PT_ORIGGPR2
1293# define restore_arg0(tcp, state, val) ((void) (state), 0)
1294# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001295# define arg0_index 1
1296# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001297# elif defined (ALPHA) || defined (MIPS)
1298# define arg0_offset REG_A0
1299# define arg1_offset (REG_A0+1)
1300# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001301# define arg0_offset (sizeof(unsigned long)*PT_R3)
1302# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001303# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304# elif defined (HPPA)
1305# define arg0_offset PT_GR26
1306# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001307# elif defined (X86_64)
1308# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1309# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001310# elif defined (SH)
1311# define arg0_offset (4*(REG_REG0+4))
1312# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001313# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001314 /* ABI defines arg0 & 1 in r2 & r3 */
1315# define arg0_offset (REG_OFFSET+16)
1316# define arg1_offset (REG_OFFSET+24)
1317# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318# else
1319# define arg0_offset 0
1320# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001321# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001322# define restore_arg0(tcp, state, val) 0
1323# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324# endif
1325
1326typedef int arg_setup_state;
1327
1328# define arg_setup(tcp, state) (0)
1329# define arg_finish_change(tcp, state) 0
1330# define get_arg0(tcp, cookie, valp) \
1331 (upeek ((tcp)->pid, arg0_offset, (valp)))
1332# define get_arg1(tcp, cookie, valp) \
1333 (upeek ((tcp)->pid, arg1_offset, (valp)))
1334
1335static int
1336set_arg0 (struct tcb *tcp, void *cookie, long val)
1337{
1338 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1339}
1340
1341static int
1342set_arg1 (struct tcb *tcp, void *cookie, long val)
1343{
1344 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1345}
1346
1347#endif
1348
Roland McGrathe1df47f2003-01-14 09:46:15 +00001349#ifndef restore_arg0
1350# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1351#endif
1352#ifndef restore_arg1
1353# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1354#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355
Roland McGrath90d0afd2004-03-01 21:05:16 +00001356#ifndef arg0_index
1357# define arg0_index 0
1358# define arg1_index 1
1359#endif
1360
Roland McGrathd81f1d92003-01-09 06:53:34 +00001361int
1362setbpt(tcp)
1363struct tcb *tcp;
1364{
1365 extern int change_syscall(struct tcb *, int);
1366 arg_setup_state state;
1367
1368 if (tcp->flags & TCB_BPTSET) {
1369 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1370 return -1;
1371 }
1372
1373 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001374#ifdef SYS_vfork
1375 case SYS_vfork:
1376#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001377#ifdef SYS_fork
1378 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001379#endif
1380#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001381 if (arg_setup (tcp, &state) < 0
1382 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1383 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1384 || change_syscall(tcp, SYS_clone) < 0
1385 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1386 || set_arg1 (tcp, &state, 0) < 0
1387 || arg_finish_change (tcp, &state) < 0)
1388 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001389 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1390 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001391 tcp->flags |= TCB_BPTSET;
1392 return 0;
1393#endif
1394
1395 case SYS_clone:
1396#ifdef SYS_clone2
1397 case SYS_clone2:
1398#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001399 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001400 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001401 || set_arg0 (tcp, &state,
1402 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001403 || arg_finish_change (tcp, &state) < 0))
1404 return -1;
1405 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001406 tcp->inst[0] = tcp->u_arg[arg0_index];
1407 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001408 return 0;
1409
1410 default:
1411 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1412 tcp->scno, tcp->pid);
1413 break;
1414 }
1415
1416 return -1;
1417}
1418
1419int
1420clearbpt(tcp)
1421struct tcb *tcp;
1422{
1423 arg_setup_state state;
1424 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001425 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1426 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427 || arg_finish_change (tcp, &state))
1428 return -1;
1429 tcp->flags &= ~TCB_BPTSET;
1430 return 0;
1431}
1432
1433#else
1434
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435int
1436setbpt(tcp)
1437struct tcb *tcp;
1438{
1439
1440#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001441#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 /* We simply use the SunOS breakpoint code. */
1443
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001444 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001445 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446#define LOOPA 0x30800000 /* ba,a 0 */
1447
1448 if (tcp->flags & TCB_BPTSET) {
1449 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1450 return -1;
1451 }
1452 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1453 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1454 return -1;
1455 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001456 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 errno = 0;
1458 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1459 if(errno) {
1460 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1461 return -1;
1462 }
1463
1464 /*
1465 * XXX - BRUTAL MODE ON
1466 * We cannot set a real BPT in the child, since it will not be
1467 * traced at the moment it will reach the trap and would probably
1468 * die with a core dump.
1469 * Thus, we are force our way in by taking out two instructions
1470 * and insert an eternal loop instead, in expectance of the SIGSTOP
1471 * generated by out PTRACE_ATTACH.
1472 * Of cause, if we evaporate ourselves in the middle of all this...
1473 */
1474 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001475 inst = LOOPA;
1476#if defined (SPARC64)
1477 inst <<= 32;
1478 inst |= (tcp->inst[0] & 0xffffffffUL);
1479#endif
1480 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 if(errno) {
1482 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1483 return -1;
1484 }
1485 tcp->flags |= TCB_BPTSET;
1486
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001487#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001488#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001489 if (ia32) {
1490# define LOOP 0x0000feeb
1491 if (tcp->flags & TCB_BPTSET) {
1492 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1493 tcp->pid);
1494 return -1;
1495 }
1496 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1497 return -1;
1498 if (debug)
1499 fprintf(stderr, "[%d] setting bpt at %lx\n",
1500 tcp->pid, tcp->baddr);
1501 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1502 (char *) tcp->baddr, 0);
1503 if (errno) {
1504 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1505 return -1;
1506 }
1507 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1508 if (errno) {
1509 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1510 return -1;
1511 }
1512 tcp->flags |= TCB_BPTSET;
1513 } else {
1514 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001515 * Our strategy here is to replace the bundle that
1516 * contained the clone() syscall with a bundle of the
1517 * form:
1518 *
1519 * { 1: br 1b; br 1b; br 1b }
1520 *
1521 * This ensures that the newly forked child will loop
1522 * endlessly until we've got a chance to attach to it.
1523 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001524# define LOOP0 0x0000100000000017
1525# define LOOP1 0x4000000000200000
1526 unsigned long addr, ipsr;
1527 pid_t pid;
1528
1529 pid = tcp->pid;
1530 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1531 return -1;
1532 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1533 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001534 /* store "ri" in low two bits */
1535 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001536
1537 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001538 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1539 0);
1540 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1541 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001542 if (errno) {
1543 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1544 return -1;
1545 }
1546
1547 errno = 0;
1548 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1549 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1550 if (errno) {
1551 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1552 return -1;
1553 }
1554 tcp->flags |= TCB_BPTSET;
1555 }
1556#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557
Michal Ludvig0e035502002-09-23 15:41:01 +00001558#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559#define LOOP 0x0000feeb
1560#elif defined (M68K)
1561#define LOOP 0x60fe0000
1562#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001563#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001565#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001567#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001568#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001569#define LOOP 0x1000ffff
1570#elif defined(S390)
1571#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001572#elif defined(S390X)
1573#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001574#elif defined(HPPA)
1575#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001576#elif defined(SH)
1577#ifdef __LITTLE_ENDIAN__
1578#define LOOP 0x0000affe
1579#else
1580#define LOOP 0xfeaf0000
1581#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582#else
1583#error unknown architecture
1584#endif
1585
1586 if (tcp->flags & TCB_BPTSET) {
1587 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1588 return -1;
1589 }
1590#if defined (I386)
1591 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1592 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001593#elif defined (X86_64)
1594 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1595 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596#elif defined (M68K)
1597 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1598 return -1;
1599#elif defined (ALPHA)
1600 return -1;
1601#elif defined (ARM)
1602 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001603#elif defined (MIPS)
1604 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001606 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001608#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001609 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1610 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001611#elif defined(HPPA)
1612 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1613 return -1;
1614 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001615#elif defined(SH)
1616 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1617 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618#else
1619#error unknown architecture
1620#endif
1621 if (debug)
1622 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1623 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1624 if (errno) {
1625 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1626 return -1;
1627 }
1628 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1629 if (errno) {
1630 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1631 return -1;
1632 }
1633 tcp->flags |= TCB_BPTSET;
1634
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001635#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001636#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637#endif /* LINUX */
1638
1639#ifdef SUNOS4
1640#ifdef SPARC /* This code is slightly sparc specific */
1641
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001642 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643#define BPT 0x91d02001 /* ta 1 */
1644#define LOOP 0x10800000 /* ba 0 */
1645#define LOOPA 0x30800000 /* ba,a 0 */
1646#define NOP 0x01000000
1647#if LOOPA
1648 static int loopdeloop[1] = {LOOPA};
1649#else
1650 static int loopdeloop[2] = {LOOP, NOP};
1651#endif
1652
1653 if (tcp->flags & TCB_BPTSET) {
1654 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1655 return -1;
1656 }
1657 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1658 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1659 return -1;
1660 }
1661 tcp->baddr = regs.r_o7 + 8;
1662 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1663 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1664 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1665 return -1;
1666 }
1667
1668 /*
1669 * XXX - BRUTAL MODE ON
1670 * We cannot set a real BPT in the child, since it will not be
1671 * traced at the moment it will reach the trap and would probably
1672 * die with a core dump.
1673 * Thus, we are force our way in by taking out two instructions
1674 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1675 * generated by out PTRACE_ATTACH.
1676 * Of cause, if we evaporate ourselves in the middle of all this...
1677 */
1678 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1679 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1680 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1681 return -1;
1682 }
1683 tcp->flags |= TCB_BPTSET;
1684
1685#endif /* SPARC */
1686#endif /* SUNOS4 */
1687
1688 return 0;
1689}
1690
1691int
1692clearbpt(tcp)
1693struct tcb *tcp;
1694{
1695
1696#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001697#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001699#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001701#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001703#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001705#elif defined(HPPA)
1706 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001707#elif defined(SH)
1708 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001709#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001711#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 /* Again, we borrow the SunOS breakpoint code. */
1713 if (!(tcp->flags & TCB_BPTSET)) {
1714 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1715 return -1;
1716 }
1717 errno = 0;
1718 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1719 if(errno) {
1720 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1721 return -1;
1722 }
1723 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001724#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001725 if (ia32) {
1726 unsigned long addr;
1727
1728 if (debug)
1729 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1730 if (!(tcp->flags & TCB_BPTSET)) {
1731 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1732 return -1;
1733 }
1734 errno = 0;
1735 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1736 if (errno) {
1737 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1738 return -1;
1739 }
1740 tcp->flags &= ~TCB_BPTSET;
1741
1742 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1743 return -1;
1744 if (addr != tcp->baddr) {
1745 /* The breakpoint has not been reached yet. */
1746 if (debug)
1747 fprintf(stderr,
1748 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1749 addr, tcp->baddr);
1750 return 0;
1751 }
1752 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001753 unsigned long addr, ipsr;
1754 pid_t pid;
1755
1756 pid = tcp->pid;
1757
1758 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1759 return -1;
1760 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1761 return -1;
1762
1763 /* restore original bundle: */
1764 errno = 0;
1765 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1766 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1767 if (errno) {
1768 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1769 return -1;
1770 }
1771
1772 /* restore original "ri" in ipsr: */
1773 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1774 errno = 0;
1775 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1776 if (errno) {
1777 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1778 return -1;
1779 }
1780
1781 tcp->flags &= ~TCB_BPTSET;
1782
1783 if (addr != (tcp->baddr & ~0x3)) {
1784 /* the breakpoint has not been reached yet. */
1785 if (debug)
1786 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1787 addr, tcp->baddr);
1788 return 0;
1789 }
1790 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001791#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792
1793 if (debug)
1794 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1795 if (!(tcp->flags & TCB_BPTSET)) {
1796 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1797 return -1;
1798 }
1799 errno = 0;
1800 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1801 if (errno) {
1802 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1803 return -1;
1804 }
1805 tcp->flags &= ~TCB_BPTSET;
1806
1807#ifdef I386
1808 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1809 return -1;
1810 if (eip != tcp->baddr) {
1811 /* The breakpoint has not been reached yet. */
1812 if (debug)
1813 fprintf(stderr,
1814 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1815 eip, tcp->baddr);
1816 return 0;
1817 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001818#elif defined(X86_64)
1819 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1820 return -1;
1821 if (eip != tcp->baddr) {
1822 /* The breakpoint has not been reached yet. */
1823 if (debug)
1824 fprintf(stderr,
1825 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1826 eip, tcp->baddr);
1827 return 0;
1828 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001829#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001830 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001831 return -1;
1832 if (pc != tcp->baddr) {
1833 /* The breakpoint has not been reached yet. */
1834 if (debug)
1835 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1836 pc, tcp->baddr);
1837 return 0;
1838 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001839#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1841 return -1;
1842 if (pc != tcp->baddr) {
1843 /* The breakpoint has not been reached yet. */
1844 if (debug)
1845 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1846 pc, tcp->baddr);
1847 return 0;
1848 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001849#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1851 return -1;
1852 if (pc != tcp->baddr) {
1853 /* The breakpoint has not been reached yet. */
1854 if (debug)
1855 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856 pc, tcp->baddr);
1857 return 0;
1858 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001859#elif defined(HPPA)
1860 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1861 return -1;
1862 iaoq &= ~0x03;
1863 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1864 /* The breakpoint has not been reached yet. */
1865 if (debug)
1866 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1867 iaoq, tcp->baddr);
1868 return 0;
1869 }
1870 iaoq = tcp->baddr | 3;
1871 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1872 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1873 * has no significant effect.
1874 */
1875 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1876 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001877#elif defined(SH)
1878 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1879 return -1;
1880 if (pc != tcp->baddr) {
1881 /* The breakpoint has not been reached yet. */
1882 if (debug)
1883 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1884 pc, tcp->baddr);
1885 return 0;
1886 }
1887
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001888#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001889#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890#endif /* LINUX */
1891
1892#ifdef SUNOS4
1893#ifdef SPARC
1894
1895#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001896 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897#endif
1898
1899 if (!(tcp->flags & TCB_BPTSET)) {
1900 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1901 return -1;
1902 }
1903 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1904 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1905 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1906 return -1;
1907 }
1908 tcp->flags &= ~TCB_BPTSET;
1909
1910#if !LOOPA
1911 /*
1912 * Since we don't have a single instruction breakpoint, we may have
1913 * to adjust the program counter after removing the our `breakpoint'.
1914 */
1915 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1916 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1917 return -1;
1918 }
1919 if ((regs.r_pc < tcp->baddr) ||
1920 (regs.r_pc > tcp->baddr + 4)) {
1921 /* The breakpoint has not been reached yet */
1922 if (debug)
1923 fprintf(stderr,
1924 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1925 regs.r_pc, tcp->parent->baddr);
1926 return 0;
1927 }
1928 if (regs.r_pc != tcp->baddr)
1929 if (debug)
1930 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1931 regs.r_pc, tcp->baddr);
1932
1933 regs.r_pc = tcp->baddr;
1934 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1935 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1936 return -1;
1937 }
1938#endif /* LOOPA */
1939#endif /* SPARC */
1940#endif /* SUNOS4 */
1941
1942 return 0;
1943}
1944
Roland McGrathd81f1d92003-01-09 06:53:34 +00001945#endif
1946
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001947#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948
1949#ifdef SUNOS4
1950
1951static int
1952getex(pid, hdr)
1953int pid;
1954struct exec *hdr;
1955{
1956 int n;
1957
1958 for (n = 0; n < sizeof *hdr; n += 4) {
1959 long res;
1960 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1961 return -1;
1962 memcpy(((char *) hdr) + n, &res, 4);
1963 }
1964 if (debug) {
1965 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1966 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1967 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1968 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1969 }
1970 return 0;
1971}
1972
1973int
1974fixvfork(tcp)
1975struct tcb *tcp;
1976{
1977 int pid = tcp->pid;
1978 /*
1979 * Change `vfork' in a freshly exec'ed dynamically linked
1980 * executable's (internal) symbol table to plain old `fork'
1981 */
1982
1983 struct exec hdr;
1984 struct link_dynamic dyn;
1985 struct link_dynamic_2 ld;
1986 char *strtab, *cp;
1987
1988 if (getex(pid, &hdr) < 0)
1989 return -1;
1990 if (!hdr.a_dynamic)
1991 return -1;
1992
1993 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1994 fprintf(stderr, "Cannot read DYNAMIC\n");
1995 return -1;
1996 }
1997 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1998 fprintf(stderr, "Cannot read link_dynamic_2\n");
1999 return -1;
2000 }
2001 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2002 fprintf(stderr, "fixvfork: out of memory\n");
2003 return -1;
2004 }
2005 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2006 (int)ld.ld_symb_size, strtab) < 0)
2007 goto err;
2008
2009#if 0
2010 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2011 fprintf(stderr, "[symbol: %s]\n", cp);
2012 cp += strlen(cp)+1;
2013 }
2014 return 0;
2015#endif
2016 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2017 if (strcmp(cp, "_vfork") == 0) {
2018 if (debug)
2019 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2020 strcpy(cp, "_fork");
2021 break;
2022 }
2023 cp += strlen(cp)+1;
2024 }
2025 if (cp < strtab + ld.ld_symb_size)
2026 /*
2027 * Write entire symbol table back to avoid
2028 * memory alignment bugs in ptrace
2029 */
2030 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2031 (int)ld.ld_symb_size, strtab) < 0)
2032 goto err;
2033
2034 free(strtab);
2035 return 0;
2036
2037err:
2038 free(strtab);
2039 return -1;
2040}
2041
2042#endif /* SUNOS4 */