blob: 488ecf42552fbe7510140011df035bd4cac0e9ff [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
Roland McGratha4d48532005-06-08 20:45:28 +0000151#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152void
153tv_tv(tv, a, b)
154struct timeval *tv;
155int a;
156int b;
157{
158 tv->tv_sec = a;
159 tv->tv_usec = b;
160}
Roland McGratha4d48532005-06-08 20:45:28 +0000161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163int
164tv_nz(a)
165struct timeval *a;
166{
167 return a->tv_sec || a->tv_usec;
168}
169
170int
171tv_cmp(a, b)
172struct timeval *a, *b;
173{
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
176 return -1;
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
179 return 1;
180 return 0;
181}
182
183double
184tv_float(tv)
185struct timeval *tv;
186{
187 return tv->tv_sec + tv->tv_usec/1000000.0;
188}
189
190void
191tv_add(tv, a, b)
192struct timeval *tv, *a, *b;
193{
194 tv->tv_sec = a->tv_sec + b->tv_sec;
195 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000196 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197 tv->tv_sec++;
198 tv->tv_usec -= 1000000;
199 }
200}
201
202void
203tv_sub(tv, a, b)
204struct timeval *tv, *a, *b;
205{
206 tv->tv_sec = a->tv_sec - b->tv_sec;
207 tv->tv_usec = a->tv_usec - b->tv_usec;
208 if (((long) tv->tv_usec) < 0) {
209 tv->tv_sec--;
210 tv->tv_usec += 1000000;
211 }
212}
213
214void
215tv_div(tv, a, n)
216struct timeval *tv, *a;
217int n;
218{
219 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
220 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
221 tv->tv_usec %= 1000000;
222}
223
224void
225tv_mul(tv, a, n)
226struct timeval *tv, *a;
227int n;
228{
229 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000230 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 tv->tv_usec %= 1000000;
232}
233
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000234const char *
235xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236{
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
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000247printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000249 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251 if (str)
252 tprintf("%s", str);
253 else
254 tprintf("%#x /* %s */", val, dflt);
255}
256
257/*
258 * Interpret `xlat' as an array of flags
259 * print the entries whose bits are on in `flags'
260 * return # of flags printed.
261 */
262int
263addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000264const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265int flags;
266{
267 int n;
268
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("|%s", xlat->str);
272 flags &= ~xlat->val;
273 n++;
274 }
275 }
276 if (flags) {
277 tprintf("|%#x", flags);
278 n++;
279 }
280 return n;
281}
282
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000283/*
284 * Interpret `xlat' as an array of flags/
285 * Print to static string the entries whose bits are on in `flags'
286 * Return static string.
287 */
288const char *
289sprintflags(const char *prefix, const struct xlat *xlat, int flags)
290{
291 static char outstr[1024];
292 int found = 0;
293
294 strcpy(outstr, prefix);
295
296 for (; xlat->str; xlat++) {
297 if ((flags & xlat->val) == xlat->val) {
298 if (found)
299 strcat(outstr, "|");
300 strcat(outstr, xlat->str);
301 flags &= ~xlat->val;
302 found = 1;
303 }
304 }
305 if (flags) {
306 if (found)
307 strcat(outstr, "|");
308 sprintf(outstr + strlen(outstr), "%#x", flags);
309 }
310
311 return outstr;
312}
313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314int
Roland McGrathb2dee132005-06-01 19:02:36 +0000315printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000316const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000318const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
320 int n;
321 char *sep;
322
323 if (flags == 0 && xlat->val == 0) {
324 tprintf("%s", xlat->str);
325 return 1;
326 }
327
328 sep = "";
329 for (n = 0; xlat->str; xlat++) {
330 if (xlat->val && (flags & xlat->val) == xlat->val) {
331 tprintf("%s%s", sep, xlat->str);
332 flags &= ~xlat->val;
333 sep = "|";
334 n++;
335 }
336 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000337
338 if (n) {
339 if (flags) {
340 tprintf("%s%#x", sep, flags);
341 n++;
342 }
343 } else {
344 if (flags) {
345 tprintf("%#x", flags);
346 if (dflt)
347 tprintf(" /* %s */", dflt);
348 } else {
349 if (dflt)
350 tprintf("0");
351 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000354 return n;
355}
356
357void
358printnum(tcp, addr, fmt)
359struct tcb *tcp;
360long addr;
361char *fmt;
362{
Roland McGratheb285352003-01-14 09:59:00 +0000363 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364
365 if (!addr) {
366 tprintf("NULL");
367 return;
368 }
369 if (umove(tcp, addr, &num) < 0) {
370 tprintf("%#lx", addr);
371 return;
372 }
373 tprintf("[");
374 tprintf(fmt, num);
375 tprintf("]");
376}
377
Roland McGrath6bc12202003-11-13 22:32:27 +0000378void
Roland McGrath9814a942005-07-04 23:28:10 +0000379printnum_int(tcp, addr, fmt)
380struct tcb *tcp;
381long addr;
382char *fmt;
383{
384 int num;
385
386 if (!addr) {
387 tprintf("NULL");
388 return;
389 }
390 if (umove(tcp, addr, &num) < 0) {
391 tprintf("%#lx", addr);
392 return;
393 }
394 tprintf("[");
395 tprintf(fmt, num);
396 tprintf("]");
397}
398
399void
Roland McGrath6bc12202003-11-13 22:32:27 +0000400printuid(text, uid)
401const char *text;
402unsigned long uid;
403{
404 tprintf("%s", text);
405 tprintf((uid == -1) ? "%ld" : "%lu", uid);
406}
407
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408static char path[MAXPATHLEN + 1];
409
Roland McGrath6d970322007-11-01 23:53:59 +0000410static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000411string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000412{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000413 const unsigned char *ustr = (const unsigned char *) instr;
414 char *s = outstr;
415 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000417 if (xflag > 1)
418 usehex = 1;
419 else if (xflag) {
420 for (i = 0; i < size; ++i) {
421 c = ustr[i];
Roland McGrath6d970322007-11-01 23:53:59 +0000422 if (len < 0 && i == size - 2 && c != '\0')
423 ++i;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000424 if (len < 0 && c == '\0')
425 break;
426 if (!isprint(c) && !isspace(c)) {
427 usehex = 1;
428 break;
429 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000430 }
431 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000432
433 *s++ = '\"';
434
435 if (usehex) {
436 for (i = 0; i < size; ++i) {
437 c = ustr[i];
438 if (len < 0 && c == '\0')
439 break;
440 sprintf(s, "\\x%02x", c);
441 s += 4;
442 }
443 } else {
444 for (i = 0; i < size; ++i) {
445 c = ustr[i];
Roland McGrath6d970322007-11-01 23:53:59 +0000446 if (len < 0 && i == size - 2 && c != '\0')
447 ++i;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000448 if (len < 0 && c == '\0')
449 break;
450 switch (c) {
451 case '\"': case '\\':
452 *s++ = '\\';
453 *s++ = c;
454 break;
455 case '\f':
456 *s++ = '\\';
457 *s++ = 'f';
458 break;
459 case '\n':
460 *s++ = '\\';
461 *s++ = 'n';
462 break;
463 case '\r':
464 *s++ = '\\';
465 *s++ = 'r';
466 break;
467 case '\t':
468 *s++ = '\\';
469 *s++ = 't';
470 break;
471 case '\v':
472 *s++ = '\\';
473 *s++ = 'v';
474 break;
475 default:
476 if (isprint(c))
477 *s++ = c;
478 else if (i + 1 < size
479 && isdigit(ustr[i + 1])) {
480 sprintf(s, "\\%03o", c);
481 s += 4;
482 } else {
483 sprintf(s, "\\%o", c);
484 s += strlen(s);
485 }
486 break;
487 }
488 }
489 }
490
491 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000492 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000493
494 /* Return nonzero if the string was unterminated. */
495 return i == size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000496}
497
498void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000499printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000500{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000501 if (n > sizeof path - 1)
Roland McGrathb15c4e42005-10-21 22:06:46 +0000502 n = sizeof path - 1;
503
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000504 if (addr == 0) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000505 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000506 return;
507 }
508
509 path[n] = '\0';
510 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 tprintf("%#lx", addr);
512 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000513 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
514 int trunc = (path[n] != '\0');
515
516 if (trunc)
517 path[n] = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000518 if (string_quote(path, outstr, -1, n + 1) || trunc)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000519 strcat(outstr, "...");
520 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521 }
522}
523
524void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000525printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000527 printpathn(tcp, addr, sizeof path - 1);
528}
529
530void
531printstr(struct tcb *tcp, long addr, int len)
532{
533 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000535 int size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536
537 if (!addr) {
538 tprintf("NULL");
539 return;
540 }
541 if (!str) {
Roland McGratha503dcf2007-08-02 02:06:26 +0000542 if ((str = malloc(max_strlen + 1)) == NULL
Roland McGrath779c4662007-07-11 07:23:40 +0000543 || (outstr = malloc(4*max_strlen
544 + sizeof "\"\"...")) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000545 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000546 tprintf("%#lx", addr);
547 return;
548 }
549 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 if (len < 0) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000552 size = max_strlen + 1;
553 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000554 tprintf("%#lx", addr);
555 return;
556 }
557 }
558 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000559 size = MIN(len, max_strlen + 1);
560 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 tprintf("%#lx", addr);
562 return;
563 }
564 }
565
Roland McGrath6d970322007-11-01 23:53:59 +0000566 if (string_quote(str, outstr, len, size))
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000567 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000568
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569 tprintf("%s", outstr);
570}
571
John Hughes1d08dcf2001-07-10 13:48:44 +0000572#if HAVE_SYS_UIO_H
573void
574dumpiov(tcp, len, addr)
575struct tcb * tcp;
576int len;
577long addr;
578{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000579#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
580 union {
581 struct { u_int32_t base; u_int32_t len; } *iov32;
582 struct { u_int64_t base; u_int64_t len; } *iov64;
583 } iovu;
584#define iov iovu.iov64
585#define sizeof_iov \
586 (personality_wordsize[current_personality] == 4 \
587 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
588#define iov_iov_base(i) \
589 (personality_wordsize[current_personality] == 4 \
590 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
591#define iov_iov_len(i) \
592 (personality_wordsize[current_personality] == 4 \
593 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
594#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000595 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000596#define sizeof_iov sizeof(*iov)
597#define iov_iov_base(i) iov[i].iov_base
598#define iov_iov_len(i) iov[i].iov_len
599#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000600 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000601 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000602
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000603 size = sizeof_iov * (unsigned long) len;
604 if (size / sizeof_iov != len
605 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000606 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000607 return;
608 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000609 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000610 for (i = 0; i < len; i++) {
611 /* include the buffer number to make it easy to
612 * match up the trace with the source */
613 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000614 (unsigned long)iov_iov_len(i), i);
615 dumpstr(tcp, (long) iov_iov_base(i),
616 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000617 }
618 }
619 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000620#undef sizeof_iov
621#undef iov_iov_base
622#undef iov_iov_len
623#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000624}
625#endif
626
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627void
628dumpstr(tcp, addr, len)
629struct tcb *tcp;
630long addr;
631int len;
632{
633 static int strsize = -1;
634 static unsigned char *str;
635 static char outstr[80];
636 char *s;
637 int i, j;
638
639 if (strsize < len) {
640 if (str)
641 free(str);
642 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000643 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000644 return;
645 }
646 strsize = len;
647 }
648
649 if (umoven(tcp, addr, len, (char *) str) < 0)
650 return;
651
652 for (i = 0; i < len; i += 16) {
653 s = outstr;
654 sprintf(s, " | %05x ", i);
655 s += 9;
656 for (j = 0; j < 16; j++) {
657 if (j == 8)
658 *s++ = ' ';
659 if (i + j < len) {
660 sprintf(s, " %02x", str[i + j]);
661 s += 3;
662 }
663 else {
664 *s++ = ' '; *s++ = ' '; *s++ = ' ';
665 }
666 }
667 *s++ = ' '; *s++ = ' ';
668 for (j = 0; j < 16; j++) {
669 if (j == 8)
670 *s++ = ' ';
671 if (i + j < len) {
672 if (isprint(str[i + j]))
673 *s++ = str[i + j];
674 else
675 *s++ = '.';
676 }
677 else
678 *s++ = ' ';
679 }
680 tprintf("%s |\n", outstr);
681 }
682}
683
684#define PAGMASK (~(PAGSIZ - 1))
685/*
686 * move `len' bytes of data from process `pid'
687 * at address `addr' to our space at `laddr'
688 */
689int
690umoven(tcp, addr, len, laddr)
691struct tcb *tcp;
692long addr;
693int len;
694char *laddr;
695{
696
697#ifdef LINUX
698 int pid = tcp->pid;
699 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000700 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701 union {
702 long val;
703 char x[sizeof(long)];
704 } u;
705
706 if (addr & (sizeof(long) - 1)) {
707 /* addr not a multiple of sizeof(long) */
708 n = addr - (addr & -sizeof(long)); /* residue */
709 addr &= -sizeof(long); /* residue */
710 errno = 0;
711 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
712 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000713 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 /* Ran into 'end of memory' - stupid "printpath" */
715 return 0;
716 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000717 /* But if not started, we had a bogus address. */
Roland McGrath1c459762007-08-02 02:22:06 +0000718 if (addr != 0 && errno != EIO)
719 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720 return -1;
721 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000722 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
724 addr += sizeof(long), laddr += m, len -= m;
725 }
726 while (len) {
727 errno = 0;
728 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
729 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000730 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000731 /* Ran into 'end of memory' - stupid "printpath" */
732 return 0;
733 }
Roland McGrath1c459762007-08-02 02:22:06 +0000734 if (addr != 0 && errno != EIO)
Roland McGrath4db26242003-01-30 20:15:19 +0000735 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000736 return -1;
737 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000738 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000739 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
740 addr += sizeof(long), laddr += m, len -= m;
741 }
742#endif /* LINUX */
743
744#ifdef SUNOS4
745 int pid = tcp->pid;
746#if 0
747 int n, m;
748 union {
749 long val;
750 char x[sizeof(long)];
751 } u;
752
753 if (addr & (sizeof(long) - 1)) {
754 /* addr not a multiple of sizeof(long) */
755 n = addr - (addr & -sizeof(long)); /* residue */
756 addr &= -sizeof(long); /* residue */
757 errno = 0;
758 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
759 if (errno) {
760 perror("umoven");
761 return -1;
762 }
763 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
764 addr += sizeof(long), laddr += m, len -= m;
765 }
766 while (len) {
767 errno = 0;
768 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
769 if (errno) {
770 perror("umoven");
771 return -1;
772 }
773 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
774 addr += sizeof(long), laddr += m, len -= m;
775 }
776#else /* !oldway */
777 int n;
778
779 while (len) {
780 n = MIN(len, PAGSIZ);
781 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
782 if (ptrace(PTRACE_READDATA, pid,
783 (char *) addr, len, laddr) < 0) {
784 perror("umoven: ptrace(PTRACE_READDATA, ...)");
785 abort();
786 return -1;
787 }
788 len -= n;
789 addr += n;
790 laddr += n;
791 }
792#endif /* !oldway */
793#endif /* SUNOS4 */
794
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000795#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000796#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000797 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000798#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000799 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000801 lseek(fd, addr, SEEK_SET);
802 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000804#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805
806 return 0;
807}
808
809/*
810 * like `umove' but make the additional effort of looking
811 * for a terminating zero byte.
812 */
813int
814umovestr(tcp, addr, len, laddr)
815struct tcb *tcp;
816long addr;
817int len;
818char *laddr;
819{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000820#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000821#ifdef HAVE_MP_PROCFS
822 int fd = tcp->pfd_as;
823#else
824 int fd = tcp->pfd;
825#endif
826 /* Some systems (e.g. FreeBSD) can be upset if we read off the
827 end of valid memory, avoid this by trying to read up
828 to page boundaries. But we don't know what a page is (and
829 getpagesize(2) (if it exists) doesn't necessarily return
830 hardware page size). Assume all pages >= 1024 (a-historical
831 I know) */
832
833 int page = 1024; /* How to find this? */
834 int move = page - (addr & (page - 1));
835 int left = len;
836
837 lseek(fd, addr, SEEK_SET);
838
839 while (left) {
840 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000841 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000842 return left != len ? 0 : -1;
843 if (memchr (laddr, 0, move)) break;
844 left -= move;
845 laddr += move;
846 addr += move;
847 move = page;
848 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000849#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000850 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 int pid = tcp->pid;
852 int i, n, m;
853 union {
854 long val;
855 char x[sizeof(long)];
856 } u;
857
858 if (addr & (sizeof(long) - 1)) {
859 /* addr not a multiple of sizeof(long) */
860 n = addr - (addr & -sizeof(long)); /* residue */
861 addr &= -sizeof(long); /* residue */
862 errno = 0;
863 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
864 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000865 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000866 /* Ran into 'end of memory' - stupid "printpath" */
867 return 0;
868 }
Roland McGrath1c459762007-08-02 02:22:06 +0000869 if (addr != 0 && errno != EIO)
870 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871 return -1;
872 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000873 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000874 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
875 while (n & (sizeof(long) - 1))
876 if (u.x[n++] == '\0')
877 return 0;
878 addr += sizeof(long), laddr += m, len -= m;
879 }
880 while (len) {
881 errno = 0;
882 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
883 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000884 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 /* Ran into 'end of memory' - stupid "printpath" */
886 return 0;
887 }
Roland McGrath1c459762007-08-02 02:22:06 +0000888 if (addr != 0 && errno != EIO)
889 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 return -1;
891 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000892 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
894 for (i = 0; i < sizeof(long); i++)
895 if (u.x[i] == '\0')
896 return 0;
897
898 addr += sizeof(long), laddr += m, len -= m;
899 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000900#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000901 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902}
903
904#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000905#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906#define PTRACE_WRITETEXT 101
907#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000908#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909#endif /* LINUX */
910
911#ifdef SUNOS4
912
913static int
914uload(cmd, pid, addr, len, laddr)
915int cmd;
916int pid;
917long addr;
918int len;
919char *laddr;
920{
921#if 0
922 int n;
923
924 while (len) {
925 n = MIN(len, PAGSIZ);
926 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
927 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
928 perror("uload: ptrace(PTRACE_WRITE, ...)");
929 return -1;
930 }
931 len -= n;
932 addr += n;
933 laddr += n;
934 }
935#else
936 int peek, poke;
937 int n, m;
938 union {
939 long val;
940 char x[sizeof(long)];
941 } u;
942
943 if (cmd == PTRACE_WRITETEXT) {
944 peek = PTRACE_PEEKTEXT;
945 poke = PTRACE_POKETEXT;
946 }
947 else {
948 peek = PTRACE_PEEKDATA;
949 poke = PTRACE_POKEDATA;
950 }
951 if (addr & (sizeof(long) - 1)) {
952 /* addr not a multiple of sizeof(long) */
953 n = addr - (addr & -sizeof(long)); /* residue */
954 addr &= -sizeof(long);
955 errno = 0;
956 u.val = ptrace(peek, pid, (char *) addr, 0);
957 if (errno) {
958 perror("uload: POKE");
959 return -1;
960 }
961 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
962 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
963 perror("uload: POKE");
964 return -1;
965 }
966 addr += sizeof(long), laddr += m, len -= m;
967 }
968 while (len) {
969 if (len < sizeof(long))
970 u.val = ptrace(peek, pid, (char *) addr, 0);
971 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
972 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
973 perror("uload: POKE");
974 return -1;
975 }
976 addr += sizeof(long), laddr += m, len -= m;
977 }
978#endif
979 return 0;
980}
981
982int
983tload(pid, addr, len, laddr)
984int pid;
985int addr, len;
986char *laddr;
987{
988 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
989}
990
991int
992dload(pid, addr, len, laddr)
993int pid;
994int addr;
995int len;
996char *laddr;
997{
998 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
999}
1000
1001#endif /* SUNOS4 */
1002
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001003#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004
1005int
1006upeek(pid, off, res)
1007int pid;
1008long off;
1009long *res;
1010{
1011 long val;
1012
1013#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
1014 {
1015 static int is_sun4m = -1;
1016 struct utsname name;
1017
1018 /* Round up the usual suspects. */
1019 if (is_sun4m == -1) {
1020 if (uname(&name) < 0) {
1021 perror("upeek: uname?");
1022 exit(1);
1023 }
1024 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1025 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001026 extern const struct xlat struct_user_offsets[];
1027 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028
1029 for (x = struct_user_offsets; x->str; x++)
1030 x->val += 1024;
1031 }
1032 }
1033 if (is_sun4m)
1034 off += 1024;
1035 }
1036#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1037 errno = 0;
1038 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1039 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001040 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001041 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001042 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 return -1;
1044 }
1045 *res = val;
1046 return 0;
1047}
1048
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001049#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050
Roland McGratha4d48532005-06-08 20:45:28 +00001051#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052long
1053getpc(tcp)
1054struct tcb *tcp;
1055{
1056
1057#ifdef LINUX
1058 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001059#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1061 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001062#elif defined(X86_64)
1063 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1064 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001065#elif defined(IA64)
1066 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1067 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001068#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 if (upeek(tcp->pid, 4*15, &pc) < 0)
1070 return -1;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001071#elif defined(BFIN)
1072 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1073 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001074#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001075 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001077#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1079 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001080#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1082 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001083#elif defined(MIPS)
1084 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1085 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001086#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001087 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1089 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001090 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001091#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001092 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001093 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001094#elif defined(HPPA)
1095 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1096 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001097#elif defined(SH)
1098 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1099 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001100#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001101 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1102 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001103#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 return pc;
1105#endif /* LINUX */
1106
1107#ifdef SUNOS4
1108 /*
1109 * Return current program counter for `pid'
1110 * Assumes PC is never 0xffffffff
1111 */
1112 struct regs regs;
1113
1114 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1115 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1116 return -1;
1117 }
1118 return regs.r_pc;
1119#endif /* SUNOS4 */
1120
1121#ifdef SVR4
1122 /* XXX */
1123 return 0;
1124#endif /* SVR4 */
1125
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001126#ifdef FREEBSD
1127 struct reg regs;
1128 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1129 return regs.r_eip;
1130#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131}
Roland McGratha4d48532005-06-08 20:45:28 +00001132#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133
1134void
1135printcall(tcp)
1136struct tcb *tcp;
1137{
Roland McGrath7a918832005-02-02 20:55:23 +00001138#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1139 sizeof(long) == 8 ? "[????????????????] " : \
1140 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141
1142#ifdef LINUX
1143#ifdef I386
1144 long eip;
1145
1146 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001147 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 return;
1149 }
1150 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001151
1152#elif defined(S390) || defined(S390X)
1153 long psw;
1154 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001155 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001156 return;
1157 }
1158#ifdef S390
1159 tprintf("[%08lx] ", psw);
1160#elif S390X
1161 tprintf("[%16lx] ", psw);
1162#endif
1163
Michal Ludvig0e035502002-09-23 15:41:01 +00001164#elif defined(X86_64)
1165 long rip;
1166
1167 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001168 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001169 return;
1170 }
1171 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001172#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001173 long ip;
1174
1175 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001176 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001177 return;
1178 }
1179 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001180#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 long pc;
1182
Roland McGratheb285352003-01-14 09:59:00 +00001183 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 tprintf ("[????????] ");
1185 return;
1186 }
1187 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001188#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 long pc;
1190
1191 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1192 tprintf ("[????????] ");
1193 return;
1194 }
1195 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001196#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197 long pc;
1198
1199 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001200 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 return;
1202 }
1203 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001204#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001205 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001207 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 return;
1209 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001210 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001211#elif defined(HPPA)
1212 long pc;
1213
1214 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1215 tprintf ("[????????] ");
1216 return;
1217 }
1218 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001219#elif defined(MIPS)
1220 long pc;
1221
1222 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1223 tprintf ("[????????] ");
1224 return;
1225 }
1226 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001227#elif defined(SH)
1228 long pc;
1229
1230 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1231 tprintf ("[????????] ");
1232 return;
1233 }
1234 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001235#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001236 long pc;
1237
1238 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001239 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001240 return;
1241 }
1242 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001243#elif defined(ARM)
1244 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001245
Roland McGrathef388682003-06-03 23:28:59 +00001246 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001247 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001248 return;
1249 }
1250 tprintf("[%08lx] ", pc);
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001251#elif defined(BFIN)
1252 long pc;
1253
1254 if (upeek(tcp->pid, PT_PC, &pc) < 0) {
1255 PRINTBADPC;
1256 return;
1257 }
1258 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001259#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260#endif /* LINUX */
1261
1262#ifdef SUNOS4
1263 struct regs regs;
1264
1265 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1266 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001267 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 return;
1269 }
1270 tprintf("[%08x] ", regs.r_o7);
1271#endif /* SUNOS4 */
1272
1273#ifdef SVR4
1274 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001275 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276#endif
1277
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001278#ifdef FREEBSD
1279 struct reg regs;
1280 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1281 tprintf("[%08x] ", regs.r_eip);
1282#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283}
1284
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001285#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287#if defined LINUX
1288
Roland McGrath3291ef22008-05-20 00:34:34 +00001289#include "syscall.h"
1290
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291#include <sys/syscall.h>
1292#ifndef CLONE_PTRACE
1293# define CLONE_PTRACE 0x00002000
1294#endif
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001295#ifndef CLONE_VFORK
1296# define CLONE_VFORK 0x00004000
1297#endif
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001298#ifndef CLONE_VM
1299# define CLONE_VM 0x00000100
1300#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001301#ifndef CLONE_STOPPED
1302# define CLONE_STOPPED 0x02000000
1303#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304
1305#ifdef IA64
1306
Roland McGrath08267b82004-02-20 22:56:43 +00001307/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1308 subsystem has them for x86... */
1309#define SYS_fork 2
1310#define SYS_vfork 190
1311
Roland McGrathd81f1d92003-01-09 06:53:34 +00001312typedef unsigned long *arg_setup_state;
1313
1314static int
1315arg_setup(struct tcb *tcp, arg_setup_state *state)
1316{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001317 unsigned long cfm, sof, sol;
1318 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001319
Jan Kratochvil1f942712008-08-06 21:38:52 +00001320 if (ia32) {
1321 /* Satisfy a false GCC warning. */
1322 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001323 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001324 }
Roland McGrath08267b82004-02-20 22:56:43 +00001325
Jan Kratochvil1f942712008-08-06 21:38:52 +00001326 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327 return -1;
1328 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1329 return -1;
1330
1331 sof = (cfm >> 0) & 0x7f;
1332 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001333 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001334
Jan Kratochvil1f942712008-08-06 21:38:52 +00001335 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336 return 0;
1337}
1338
1339# define arg_finish_change(tcp, state) 0
1340
1341#ifdef SYS_fork
1342static int
1343get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1344{
Roland McGrath08267b82004-02-20 22:56:43 +00001345 int ret;
1346
1347 if (ia32)
1348 ret = upeek (tcp->pid, PT_R11, valp);
1349 else
1350 ret = umoven (tcp,
1351 (unsigned long) ia64_rse_skip_regs(*state, 0),
1352 sizeof(long), (void *) valp);
1353 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001354}
1355
1356static int
1357get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1358{
Roland McGrath08267b82004-02-20 22:56:43 +00001359 int ret;
1360
1361 if (ia32)
1362 ret = upeek (tcp->pid, PT_R9, valp);
1363 else
1364 ret = umoven (tcp,
1365 (unsigned long) ia64_rse_skip_regs(*state, 1),
1366 sizeof(long), (void *) valp);
1367 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001368}
1369#endif
1370
1371static int
1372set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1373{
Roland McGrath08267b82004-02-20 22:56:43 +00001374 int req = PTRACE_POKEDATA;
1375 void *ap;
1376
1377 if (ia32) {
1378 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1379 req = PTRACE_POKEUSER;
1380 } else
1381 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001382 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001383 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001384 return errno ? -1 : 0;
1385}
1386
1387static int
1388set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1389{
Roland McGrath08267b82004-02-20 22:56:43 +00001390 int req = PTRACE_POKEDATA;
1391 void *ap;
1392
1393 if (ia32) {
1394 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1395 req = PTRACE_POKEUSER;
1396 } else
1397 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001398 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001399 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001400 return errno ? -1 : 0;
1401}
1402
Roland McGrathb659f872008-07-18 01:19:36 +00001403/* ia64 does not return the input arguments from functions (and syscalls)
1404 according to ia64 RSE (Register Stack Engine) behavior. */
1405
1406# define restore_arg0(tcp, state, val) ((void) (state), 0)
1407# define restore_arg1(tcp, state, val) ((void) (state), 0)
1408
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001409#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001410
1411typedef struct regs arg_setup_state;
1412
1413# define arg_setup(tcp, state) \
1414 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1415# define arg_finish_change(tcp, state) \
1416 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1417
1418# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1419# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1420# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1421# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001422# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423
1424#else
1425
1426# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001427/* Note: this is only true for the `clone' system call, which handles
1428 arguments specially. We could as well say that its first two arguments
1429 are swapped relative to other architectures, but that would just be
1430 another #ifdef in the calls. */
1431# define arg0_offset PT_GPR3
1432# define arg1_offset PT_ORIGGPR2
1433# define restore_arg0(tcp, state, val) ((void) (state), 0)
1434# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001435# define arg0_index 1
1436# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437# elif defined (ALPHA) || defined (MIPS)
1438# define arg0_offset REG_A0
1439# define arg1_offset (REG_A0+1)
1440# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001441# define arg0_offset (sizeof(unsigned long)*PT_R3)
1442# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001443# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444# elif defined (HPPA)
1445# define arg0_offset PT_GR26
1446# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001447# elif defined (X86_64)
1448# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1449# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001450# elif defined (SH)
1451# define arg0_offset (4*(REG_REG0+4))
1452# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001453# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001454 /* ABI defines arg0 & 1 in r2 & r3 */
1455# define arg0_offset (REG_OFFSET+16)
1456# define arg1_offset (REG_OFFSET+24)
1457# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001458# else
1459# define arg0_offset 0
1460# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001461# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001462# define restore_arg0(tcp, state, val) 0
1463# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001464# endif
1465
1466typedef int arg_setup_state;
1467
1468# define arg_setup(tcp, state) (0)
1469# define arg_finish_change(tcp, state) 0
1470# define get_arg0(tcp, cookie, valp) \
1471 (upeek ((tcp)->pid, arg0_offset, (valp)))
1472# define get_arg1(tcp, cookie, valp) \
1473 (upeek ((tcp)->pid, arg1_offset, (valp)))
1474
1475static int
1476set_arg0 (struct tcb *tcp, void *cookie, long val)
1477{
Roland McGrathca85b972005-06-07 23:22:08 +00001478 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479}
1480
1481static int
1482set_arg1 (struct tcb *tcp, void *cookie, long val)
1483{
1484 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1485}
1486
1487#endif
1488
Roland McGrathe1df47f2003-01-14 09:46:15 +00001489#ifndef restore_arg0
1490# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1491#endif
1492#ifndef restore_arg1
1493# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1494#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001495
Roland McGrath90d0afd2004-03-01 21:05:16 +00001496#ifndef arg0_index
1497# define arg0_index 0
1498# define arg1_index 1
1499#endif
1500
Roland McGrathd81f1d92003-01-09 06:53:34 +00001501int
1502setbpt(tcp)
1503struct tcb *tcp;
1504{
Roland McGrath3291ef22008-05-20 00:34:34 +00001505 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001506 extern int change_syscall(struct tcb *, int);
1507 arg_setup_state state;
1508
1509 if (tcp->flags & TCB_BPTSET) {
1510 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1511 return -1;
1512 }
1513
Roland McGrath3291ef22008-05-20 00:34:34 +00001514 /*
1515 * It's a silly kludge to initialize this with a search at runtime.
1516 * But it's better than maintaining another magic thing in the
1517 * godforsaken tables.
1518 */
1519 if (clone_scno[current_personality] == 0) {
1520 int i;
1521 for (i = 0; i < nsyscalls; ++i)
1522 if (sysent[i].sys_func == sys_clone) {
1523 clone_scno[current_personality] = i;
1524 break;
1525 }
1526 }
1527
Roland McGrath76989d72005-06-07 23:21:31 +00001528 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001529#ifdef SYS_vfork
1530 case SYS_vfork:
1531#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001532#ifdef SYS_fork
1533 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001534#endif
1535#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001536 if (arg_setup (tcp, &state) < 0
1537 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1538 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001539 || change_syscall(tcp, clone_scno[current_personality]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001540 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1541 || set_arg1 (tcp, &state, 0) < 0
1542 || arg_finish_change (tcp, &state) < 0)
1543 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001544 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1545 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001546 tcp->flags |= TCB_BPTSET;
1547 return 0;
1548#endif
1549
1550 case SYS_clone:
1551#ifdef SYS_clone2
1552 case SYS_clone2:
1553#endif
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001554 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1555 contrary to x86 SYS_vfork above. Even on x86 we turn the
1556 vfork semantics into plain fork - each application must not
1557 depend on the vfork specifics according to POSIX. We would
1558 hang waiting for the parent resume otherwise. We need to
1559 clear also CLONE_VM but only in the CLONE_VFORK case as
1560 otherwise we would break pthread_create. */
1561
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001562 if ((arg_setup (tcp, &state) < 0
1563 || set_arg0 (tcp, &state,
1564 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001565 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
1566 ? CLONE_VFORK | CLONE_VM : 0)) < 0
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001567 || arg_finish_change (tcp, &state) < 0))
1568 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001569 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001570 tcp->inst[0] = tcp->u_arg[arg0_index];
1571 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001572 return 0;
1573
1574 default:
1575 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1576 tcp->scno, tcp->pid);
1577 break;
1578 }
1579
1580 return -1;
1581}
1582
1583int
1584clearbpt(tcp)
1585struct tcb *tcp;
1586{
1587 arg_setup_state state;
1588 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001589 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1590 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001591 || arg_finish_change (tcp, &state))
1592 return -1;
1593 tcp->flags &= ~TCB_BPTSET;
1594 return 0;
1595}
1596
1597#else
1598
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599int
1600setbpt(tcp)
1601struct tcb *tcp;
1602{
1603
1604#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001605#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606 /* We simply use the SunOS breakpoint code. */
1607
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001608 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001609 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610#define LOOPA 0x30800000 /* ba,a 0 */
1611
1612 if (tcp->flags & TCB_BPTSET) {
1613 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1614 return -1;
1615 }
1616 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1617 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1618 return -1;
1619 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001620 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 errno = 0;
1622 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1623 if(errno) {
1624 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1625 return -1;
1626 }
1627
1628 /*
1629 * XXX - BRUTAL MODE ON
1630 * We cannot set a real BPT in the child, since it will not be
1631 * traced at the moment it will reach the trap and would probably
1632 * die with a core dump.
1633 * Thus, we are force our way in by taking out two instructions
1634 * and insert an eternal loop instead, in expectance of the SIGSTOP
1635 * generated by out PTRACE_ATTACH.
1636 * Of cause, if we evaporate ourselves in the middle of all this...
1637 */
1638 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001639 inst = LOOPA;
1640#if defined (SPARC64)
1641 inst <<= 32;
1642 inst |= (tcp->inst[0] & 0xffffffffUL);
1643#endif
1644 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 if(errno) {
1646 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1647 return -1;
1648 }
1649 tcp->flags |= TCB_BPTSET;
1650
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001651#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001652#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001653 if (ia32) {
1654# define LOOP 0x0000feeb
1655 if (tcp->flags & TCB_BPTSET) {
1656 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1657 tcp->pid);
1658 return -1;
1659 }
1660 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1661 return -1;
1662 if (debug)
1663 fprintf(stderr, "[%d] setting bpt at %lx\n",
1664 tcp->pid, tcp->baddr);
1665 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1666 (char *) tcp->baddr, 0);
1667 if (errno) {
1668 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1669 return -1;
1670 }
1671 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1672 if (errno) {
1673 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1674 return -1;
1675 }
1676 tcp->flags |= TCB_BPTSET;
1677 } else {
1678 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001679 * Our strategy here is to replace the bundle that
1680 * contained the clone() syscall with a bundle of the
1681 * form:
1682 *
1683 * { 1: br 1b; br 1b; br 1b }
1684 *
1685 * This ensures that the newly forked child will loop
1686 * endlessly until we've got a chance to attach to it.
1687 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001688# define LOOP0 0x0000100000000017
1689# define LOOP1 0x4000000000200000
1690 unsigned long addr, ipsr;
1691 pid_t pid;
1692
1693 pid = tcp->pid;
1694 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1695 return -1;
1696 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1697 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001698 /* store "ri" in low two bits */
1699 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001700
1701 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001702 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1703 0);
1704 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1705 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001706 if (errno) {
1707 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1708 return -1;
1709 }
1710
1711 errno = 0;
1712 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1713 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1714 if (errno) {
1715 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1716 return -1;
1717 }
1718 tcp->flags |= TCB_BPTSET;
1719 }
1720#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721
Michal Ludvig0e035502002-09-23 15:41:01 +00001722#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723#define LOOP 0x0000feeb
1724#elif defined (M68K)
1725#define LOOP 0x60fe0000
1726#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001727#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001729#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001731#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001732#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001733#define LOOP 0x1000ffff
1734#elif defined(S390)
1735#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001736#elif defined(S390X)
1737#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001738#elif defined(HPPA)
1739#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001740#elif defined(SH)
1741#ifdef __LITTLE_ENDIAN__
1742#define LOOP 0x0000affe
1743#else
1744#define LOOP 0xfeaf0000
1745#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746#else
1747#error unknown architecture
1748#endif
1749
1750 if (tcp->flags & TCB_BPTSET) {
1751 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1752 return -1;
1753 }
1754#if defined (I386)
1755 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1756 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001757#elif defined (X86_64)
1758 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1759 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760#elif defined (M68K)
1761 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1762 return -1;
1763#elif defined (ALPHA)
1764 return -1;
1765#elif defined (ARM)
1766 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001767#elif defined (MIPS)
1768 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001770 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001772#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001773 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1774 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001775#elif defined(HPPA)
1776 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1777 return -1;
1778 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001779#elif defined(SH)
1780 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1781 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782#else
1783#error unknown architecture
1784#endif
1785 if (debug)
1786 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1787 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1788 if (errno) {
1789 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1790 return -1;
1791 }
1792 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1793 if (errno) {
1794 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1795 return -1;
1796 }
1797 tcp->flags |= TCB_BPTSET;
1798
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001799#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001800#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801#endif /* LINUX */
1802
1803#ifdef SUNOS4
1804#ifdef SPARC /* This code is slightly sparc specific */
1805
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001806 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807#define BPT 0x91d02001 /* ta 1 */
1808#define LOOP 0x10800000 /* ba 0 */
1809#define LOOPA 0x30800000 /* ba,a 0 */
1810#define NOP 0x01000000
1811#if LOOPA
1812 static int loopdeloop[1] = {LOOPA};
1813#else
1814 static int loopdeloop[2] = {LOOP, NOP};
1815#endif
1816
1817 if (tcp->flags & TCB_BPTSET) {
1818 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1819 return -1;
1820 }
1821 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1822 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1823 return -1;
1824 }
1825 tcp->baddr = regs.r_o7 + 8;
1826 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1827 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1828 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1829 return -1;
1830 }
1831
1832 /*
1833 * XXX - BRUTAL MODE ON
1834 * We cannot set a real BPT in the child, since it will not be
1835 * traced at the moment it will reach the trap and would probably
1836 * die with a core dump.
1837 * Thus, we are force our way in by taking out two instructions
1838 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1839 * generated by out PTRACE_ATTACH.
1840 * Of cause, if we evaporate ourselves in the middle of all this...
1841 */
1842 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1843 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1844 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1845 return -1;
1846 }
1847 tcp->flags |= TCB_BPTSET;
1848
1849#endif /* SPARC */
1850#endif /* SUNOS4 */
1851
1852 return 0;
1853}
1854
1855int
1856clearbpt(tcp)
1857struct tcb *tcp;
1858{
1859
1860#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001861#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001863#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001865#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001867#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001869#elif defined(HPPA)
1870 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001871#elif defined(SH)
1872 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001873#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001875#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876 /* Again, we borrow the SunOS breakpoint code. */
1877 if (!(tcp->flags & TCB_BPTSET)) {
1878 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1879 return -1;
1880 }
1881 errno = 0;
1882 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1883 if(errno) {
1884 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1885 return -1;
1886 }
1887 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001888#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001889 if (ia32) {
1890 unsigned long addr;
1891
1892 if (debug)
1893 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1894 if (!(tcp->flags & TCB_BPTSET)) {
1895 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1896 return -1;
1897 }
1898 errno = 0;
1899 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1900 if (errno) {
1901 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1902 return -1;
1903 }
1904 tcp->flags &= ~TCB_BPTSET;
1905
1906 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1907 return -1;
1908 if (addr != tcp->baddr) {
1909 /* The breakpoint has not been reached yet. */
1910 if (debug)
1911 fprintf(stderr,
1912 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1913 addr, tcp->baddr);
1914 return 0;
1915 }
1916 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001917 unsigned long addr, ipsr;
1918 pid_t pid;
1919
1920 pid = tcp->pid;
1921
1922 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1923 return -1;
1924 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1925 return -1;
1926
1927 /* restore original bundle: */
1928 errno = 0;
1929 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1930 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1931 if (errno) {
1932 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1933 return -1;
1934 }
1935
1936 /* restore original "ri" in ipsr: */
1937 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1938 errno = 0;
1939 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1940 if (errno) {
1941 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1942 return -1;
1943 }
1944
1945 tcp->flags &= ~TCB_BPTSET;
1946
1947 if (addr != (tcp->baddr & ~0x3)) {
1948 /* the breakpoint has not been reached yet. */
1949 if (debug)
1950 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1951 addr, tcp->baddr);
1952 return 0;
1953 }
1954 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001955#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956
1957 if (debug)
1958 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1959 if (!(tcp->flags & TCB_BPTSET)) {
1960 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1961 return -1;
1962 }
1963 errno = 0;
1964 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1965 if (errno) {
1966 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1967 return -1;
1968 }
1969 tcp->flags &= ~TCB_BPTSET;
1970
1971#ifdef I386
1972 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1973 return -1;
1974 if (eip != tcp->baddr) {
1975 /* The breakpoint has not been reached yet. */
1976 if (debug)
1977 fprintf(stderr,
1978 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1979 eip, tcp->baddr);
1980 return 0;
1981 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001982#elif defined(X86_64)
1983 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1984 return -1;
1985 if (eip != tcp->baddr) {
1986 /* The breakpoint has not been reached yet. */
1987 if (debug)
1988 fprintf(stderr,
1989 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1990 eip, tcp->baddr);
1991 return 0;
1992 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001993#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001994 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 return -1;
1996 if (pc != tcp->baddr) {
1997 /* The breakpoint has not been reached yet. */
1998 if (debug)
1999 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2000 pc, tcp->baddr);
2001 return 0;
2002 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002003#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
2005 return -1;
2006 if (pc != tcp->baddr) {
2007 /* The breakpoint has not been reached yet. */
2008 if (debug)
2009 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2010 pc, tcp->baddr);
2011 return 0;
2012 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002013#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014 if (upeek(tcp->pid, REG_PC, &pc) < 0)
2015 return -1;
2016 if (pc != tcp->baddr) {
2017 /* The breakpoint has not been reached yet. */
2018 if (debug)
2019 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2020 pc, tcp->baddr);
2021 return 0;
2022 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002023#elif defined(HPPA)
2024 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
2025 return -1;
2026 iaoq &= ~0x03;
2027 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2028 /* The breakpoint has not been reached yet. */
2029 if (debug)
2030 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2031 iaoq, tcp->baddr);
2032 return 0;
2033 }
2034 iaoq = tcp->baddr | 3;
2035 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2036 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2037 * has no significant effect.
2038 */
2039 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2040 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00002041#elif defined(SH)
2042 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
2043 return -1;
2044 if (pc != tcp->baddr) {
2045 /* The breakpoint has not been reached yet. */
2046 if (debug)
2047 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2048 pc, tcp->baddr);
2049 return 0;
2050 }
2051
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002052#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002053#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054#endif /* LINUX */
2055
2056#ifdef SUNOS4
2057#ifdef SPARC
2058
2059#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00002060 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002061#endif
2062
2063 if (!(tcp->flags & TCB_BPTSET)) {
2064 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2065 return -1;
2066 }
2067 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
2068 sizeof tcp->inst, (char *) tcp->inst) < 0) {
2069 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
2070 return -1;
2071 }
2072 tcp->flags &= ~TCB_BPTSET;
2073
2074#if !LOOPA
2075 /*
2076 * Since we don't have a single instruction breakpoint, we may have
2077 * to adjust the program counter after removing the our `breakpoint'.
2078 */
2079 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2080 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2081 return -1;
2082 }
2083 if ((regs.r_pc < tcp->baddr) ||
2084 (regs.r_pc > tcp->baddr + 4)) {
2085 /* The breakpoint has not been reached yet */
2086 if (debug)
2087 fprintf(stderr,
2088 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2089 regs.r_pc, tcp->parent->baddr);
2090 return 0;
2091 }
2092 if (regs.r_pc != tcp->baddr)
2093 if (debug)
2094 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2095 regs.r_pc, tcp->baddr);
2096
2097 regs.r_pc = tcp->baddr;
2098 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2099 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2100 return -1;
2101 }
2102#endif /* LOOPA */
2103#endif /* SPARC */
2104#endif /* SUNOS4 */
2105
2106 return 0;
2107}
2108
Roland McGrathd81f1d92003-01-09 06:53:34 +00002109#endif
2110
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002111#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112
2113#ifdef SUNOS4
2114
2115static int
2116getex(pid, hdr)
2117int pid;
2118struct exec *hdr;
2119{
2120 int n;
2121
2122 for (n = 0; n < sizeof *hdr; n += 4) {
2123 long res;
2124 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2125 return -1;
2126 memcpy(((char *) hdr) + n, &res, 4);
2127 }
2128 if (debug) {
2129 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2130 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2131 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2132 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2133 }
2134 return 0;
2135}
2136
2137int
2138fixvfork(tcp)
2139struct tcb *tcp;
2140{
2141 int pid = tcp->pid;
2142 /*
2143 * Change `vfork' in a freshly exec'ed dynamically linked
2144 * executable's (internal) symbol table to plain old `fork'
2145 */
2146
2147 struct exec hdr;
2148 struct link_dynamic dyn;
2149 struct link_dynamic_2 ld;
2150 char *strtab, *cp;
2151
2152 if (getex(pid, &hdr) < 0)
2153 return -1;
2154 if (!hdr.a_dynamic)
2155 return -1;
2156
2157 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2158 fprintf(stderr, "Cannot read DYNAMIC\n");
2159 return -1;
2160 }
2161 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2162 fprintf(stderr, "Cannot read link_dynamic_2\n");
2163 return -1;
2164 }
2165 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002166 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002167 return -1;
2168 }
2169 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2170 (int)ld.ld_symb_size, strtab) < 0)
2171 goto err;
2172
2173#if 0
2174 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2175 fprintf(stderr, "[symbol: %s]\n", cp);
2176 cp += strlen(cp)+1;
2177 }
2178 return 0;
2179#endif
2180 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2181 if (strcmp(cp, "_vfork") == 0) {
2182 if (debug)
2183 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2184 strcpy(cp, "_fork");
2185 break;
2186 }
2187 cp += strlen(cp)+1;
2188 }
2189 if (cp < strtab + ld.ld_symb_size)
2190 /*
2191 * Write entire symbol table back to avoid
2192 * memory alignment bugs in ptrace
2193 */
2194 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2195 (int)ld.ld_symb_size, strtab) < 0)
2196 goto err;
2197
2198 free(strtab);
2199 return 0;
2200
2201err:
2202 free(strtab);
2203 return -1;
2204}
2205
2206#endif /* SUNOS4 */