blob: 5855c10acb92ca63bec141f63c0e7023eea6b3a0 [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
283int
Roland McGrathb2dee132005-06-01 19:02:36 +0000284printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000285const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000287const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000288{
289 int n;
290 char *sep;
291
292 if (flags == 0 && xlat->val == 0) {
293 tprintf("%s", xlat->str);
294 return 1;
295 }
296
297 sep = "";
298 for (n = 0; xlat->str; xlat++) {
299 if (xlat->val && (flags & xlat->val) == xlat->val) {
300 tprintf("%s%s", sep, xlat->str);
301 flags &= ~xlat->val;
302 sep = "|";
303 n++;
304 }
305 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000306
307 if (n) {
308 if (flags) {
309 tprintf("%s%#x", sep, flags);
310 n++;
311 }
312 } else {
313 if (flags) {
314 tprintf("%#x", flags);
315 if (dflt)
316 tprintf(" /* %s */", dflt);
317 } else {
318 if (dflt)
319 tprintf("0");
320 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000322
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000323 return n;
324}
325
326void
327printnum(tcp, addr, fmt)
328struct tcb *tcp;
329long addr;
330char *fmt;
331{
Roland McGratheb285352003-01-14 09:59:00 +0000332 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333
334 if (!addr) {
335 tprintf("NULL");
336 return;
337 }
338 if (umove(tcp, addr, &num) < 0) {
339 tprintf("%#lx", addr);
340 return;
341 }
342 tprintf("[");
343 tprintf(fmt, num);
344 tprintf("]");
345}
346
Roland McGrath6bc12202003-11-13 22:32:27 +0000347void
Roland McGrath9814a942005-07-04 23:28:10 +0000348printnum_int(tcp, addr, fmt)
349struct tcb *tcp;
350long addr;
351char *fmt;
352{
353 int num;
354
355 if (!addr) {
356 tprintf("NULL");
357 return;
358 }
359 if (umove(tcp, addr, &num) < 0) {
360 tprintf("%#lx", addr);
361 return;
362 }
363 tprintf("[");
364 tprintf(fmt, num);
365 tprintf("]");
366}
367
368void
Roland McGrath6bc12202003-11-13 22:32:27 +0000369printuid(text, uid)
370const char *text;
371unsigned long uid;
372{
373 tprintf("%s", text);
374 tprintf((uid == -1) ? "%ld" : "%lu", uid);
375}
376
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377static char path[MAXPATHLEN + 1];
378
Roland McGratha4d48532005-06-08 20:45:28 +0000379static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380string_quote(str)
Roland McGratha4d48532005-06-08 20:45:28 +0000381const char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382{
383 char buf[2 * MAXPATHLEN + 1];
384 char *s;
385
386 if (!strpbrk(str, "\"\'\\")) {
387 tprintf("\"%s\"", str);
388 return;
389 }
390 for (s = buf; *str; str++) {
391 switch (*str) {
392 case '\"': case '\'': case '\\':
393 *s++ = '\\'; *s++ = *str; break;
394 default:
395 *s++ = *str; break;
396 }
397 }
398 *s = '\0';
399 tprintf("\"%s\"", buf);
400}
401
402void
403printpath(tcp, addr)
404struct tcb *tcp;
405long addr;
406{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000407 if (addr == 0)
408 tprintf("NULL");
409 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410 tprintf("%#lx", addr);
411 else
412 string_quote(path);
413 return;
414}
415
416void
417printpathn(tcp, addr, n)
418struct tcb *tcp;
419long addr;
420int n;
421{
Roland McGrathb15c4e42005-10-21 22:06:46 +0000422 if (n >= sizeof path)
423 n = sizeof path - 1;
424
Roland McGrath371ed8f2005-02-06 01:55:07 +0000425 if (addr == 0)
426 tprintf("NULL");
427 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000428 tprintf("%#lx", addr);
429 else {
430 path[n] = '\0';
431 string_quote(path);
432 }
433}
434
435void
436printstr(tcp, addr, len)
437struct tcb *tcp;
438long addr;
439int len;
440{
441 static unsigned char *str = NULL;
442 static char *outstr;
443 int i, n, c, usehex;
444 char *s, *outend;
Roland McGratha503dcf2007-08-02 02:06:26 +0000445 int trunc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000446
447 if (!addr) {
448 tprintf("NULL");
449 return;
450 }
451 if (!str) {
Roland McGratha503dcf2007-08-02 02:06:26 +0000452 if ((str = malloc(max_strlen + 1)) == NULL
Roland McGrath779c4662007-07-11 07:23:40 +0000453 || (outstr = malloc(4*max_strlen
454 + sizeof "\"\"...")) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000455 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000456 tprintf("%#lx", addr);
457 return;
458 }
459 }
Roland McGrath779c4662007-07-11 07:23:40 +0000460 outend = outstr + max_strlen * 4;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000461 if (len < 0) {
Roland McGratha503dcf2007-08-02 02:06:26 +0000462 n = max_strlen + 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463 if (umovestr(tcp, addr, n, (char *) str) < 0) {
464 tprintf("%#lx", addr);
465 return;
466 }
467 }
468 else {
Roland McGratha503dcf2007-08-02 02:06:26 +0000469 n = MIN(len, max_strlen + 1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000470 if (umoven(tcp, addr, n, (char *) str) < 0) {
471 tprintf("%#lx", addr);
472 return;
473 }
474 }
475
Roland McGratha503dcf2007-08-02 02:06:26 +0000476 trunc = n > max_strlen && str[--n] != 0;
477
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 usehex = 0;
479 if (xflag > 1)
480 usehex = 1;
481 else if (xflag) {
482 for (i = 0; i < n; i++) {
483 c = str[i];
484 if (len < 0 && c == '\0')
485 break;
486 if (!isprint(c) && !isspace(c)) {
487 usehex = 1;
488 break;
489 }
490 }
491 }
492
493 s = outstr;
494 *s++ = '\"';
495
496 if (usehex) {
497 for (i = 0; i < n; i++) {
498 c = str[i];
499 if (len < 0 && c == '\0')
500 break;
501 sprintf(s, "\\x%02x", c);
502 s += 4;
503 if (s > outend)
504 break;
505 }
506 }
507 else {
508 for (i = 0; i < n; i++) {
509 c = str[i];
510 if (len < 0 && c == '\0')
511 break;
512 switch (c) {
513 case '\"': case '\'': case '\\':
514 *s++ = '\\'; *s++ = c; break;
515 case '\f':
516 *s++ = '\\'; *s++ = 'f'; break;
517 case '\n':
518 *s++ = '\\'; *s++ = 'n'; break;
519 case '\r':
520 *s++ = '\\'; *s++ = 'r'; break;
521 case '\t':
522 *s++ = '\\'; *s++ = 't'; break;
523 case '\v':
524 *s++ = '\\'; *s++ = 'v'; break;
525 default:
526 if (isprint(c))
527 *s++ = c;
528 else if (i < n - 1 && isdigit(str[i + 1])) {
529 sprintf(s, "\\%03o", c);
530 s += 4;
531 }
532 else {
533 sprintf(s, "\\%o", c);
534 s += strlen(s);
535 }
536 break;
537 }
538 if (s > outend)
539 break;
540 }
541 }
542
543 *s++ = '\"';
Roland McGratha503dcf2007-08-02 02:06:26 +0000544 if (i < len || (len < 0 && (trunc || s > outend))) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 *s++ = '.'; *s++ = '.'; *s++ = '.';
546 }
547 *s = '\0';
548 tprintf("%s", outstr);
549}
550
John Hughes1d08dcf2001-07-10 13:48:44 +0000551#if HAVE_SYS_UIO_H
552void
553dumpiov(tcp, len, addr)
554struct tcb * tcp;
555int len;
556long addr;
557{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000558#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
559 union {
560 struct { u_int32_t base; u_int32_t len; } *iov32;
561 struct { u_int64_t base; u_int64_t len; } *iov64;
562 } iovu;
563#define iov iovu.iov64
564#define sizeof_iov \
565 (personality_wordsize[current_personality] == 4 \
566 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
567#define iov_iov_base(i) \
568 (personality_wordsize[current_personality] == 4 \
569 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
570#define iov_iov_len(i) \
571 (personality_wordsize[current_personality] == 4 \
572 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
573#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000574 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000575#define sizeof_iov sizeof(*iov)
576#define iov_iov_base(i) iov[i].iov_base
577#define iov_iov_len(i) iov[i].iov_len
578#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000579 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000580 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000581
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000582 size = sizeof_iov * (unsigned long) len;
583 if (size / sizeof_iov != len
584 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000585 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000586 return;
587 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000588 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000589 for (i = 0; i < len; i++) {
590 /* include the buffer number to make it easy to
591 * match up the trace with the source */
592 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000593 (unsigned long)iov_iov_len(i), i);
594 dumpstr(tcp, (long) iov_iov_base(i),
595 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000596 }
597 }
598 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000599#undef sizeof_iov
600#undef iov_iov_base
601#undef iov_iov_len
602#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000603}
604#endif
605
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606void
607dumpstr(tcp, addr, len)
608struct tcb *tcp;
609long addr;
610int len;
611{
612 static int strsize = -1;
613 static unsigned char *str;
614 static char outstr[80];
615 char *s;
616 int i, j;
617
618 if (strsize < len) {
619 if (str)
620 free(str);
621 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000622 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000623 return;
624 }
625 strsize = len;
626 }
627
628 if (umoven(tcp, addr, len, (char *) str) < 0)
629 return;
630
631 for (i = 0; i < len; i += 16) {
632 s = outstr;
633 sprintf(s, " | %05x ", i);
634 s += 9;
635 for (j = 0; j < 16; j++) {
636 if (j == 8)
637 *s++ = ' ';
638 if (i + j < len) {
639 sprintf(s, " %02x", str[i + j]);
640 s += 3;
641 }
642 else {
643 *s++ = ' '; *s++ = ' '; *s++ = ' ';
644 }
645 }
646 *s++ = ' '; *s++ = ' ';
647 for (j = 0; j < 16; j++) {
648 if (j == 8)
649 *s++ = ' ';
650 if (i + j < len) {
651 if (isprint(str[i + j]))
652 *s++ = str[i + j];
653 else
654 *s++ = '.';
655 }
656 else
657 *s++ = ' ';
658 }
659 tprintf("%s |\n", outstr);
660 }
661}
662
663#define PAGMASK (~(PAGSIZ - 1))
664/*
665 * move `len' bytes of data from process `pid'
666 * at address `addr' to our space at `laddr'
667 */
668int
669umoven(tcp, addr, len, laddr)
670struct tcb *tcp;
671long addr;
672int len;
673char *laddr;
674{
675
676#ifdef LINUX
677 int pid = tcp->pid;
678 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000679 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680 union {
681 long val;
682 char x[sizeof(long)];
683 } u;
684
685 if (addr & (sizeof(long) - 1)) {
686 /* addr not a multiple of sizeof(long) */
687 n = addr - (addr & -sizeof(long)); /* residue */
688 addr &= -sizeof(long); /* residue */
689 errno = 0;
690 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
691 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000692 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 /* Ran into 'end of memory' - stupid "printpath" */
694 return 0;
695 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000696 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 perror("ptrace: umoven");
698 return -1;
699 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000700 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
702 addr += sizeof(long), laddr += m, len -= m;
703 }
704 while (len) {
705 errno = 0;
706 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
707 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000708 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709 /* Ran into 'end of memory' - stupid "printpath" */
710 return 0;
711 }
Roland McGrath4db26242003-01-30 20:15:19 +0000712 if (addr != 0)
713 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 return -1;
715 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000716 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
718 addr += sizeof(long), laddr += m, len -= m;
719 }
720#endif /* LINUX */
721
722#ifdef SUNOS4
723 int pid = tcp->pid;
724#if 0
725 int n, m;
726 union {
727 long val;
728 char x[sizeof(long)];
729 } u;
730
731 if (addr & (sizeof(long) - 1)) {
732 /* addr not a multiple of sizeof(long) */
733 n = addr - (addr & -sizeof(long)); /* residue */
734 addr &= -sizeof(long); /* residue */
735 errno = 0;
736 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
737 if (errno) {
738 perror("umoven");
739 return -1;
740 }
741 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
742 addr += sizeof(long), laddr += m, len -= m;
743 }
744 while (len) {
745 errno = 0;
746 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
747 if (errno) {
748 perror("umoven");
749 return -1;
750 }
751 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
752 addr += sizeof(long), laddr += m, len -= m;
753 }
754#else /* !oldway */
755 int n;
756
757 while (len) {
758 n = MIN(len, PAGSIZ);
759 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
760 if (ptrace(PTRACE_READDATA, pid,
761 (char *) addr, len, laddr) < 0) {
762 perror("umoven: ptrace(PTRACE_READDATA, ...)");
763 abort();
764 return -1;
765 }
766 len -= n;
767 addr += n;
768 laddr += n;
769 }
770#endif /* !oldway */
771#endif /* SUNOS4 */
772
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000773#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000774#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000775 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000776#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000777 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000779 lseek(fd, addr, SEEK_SET);
780 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000782#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783
784 return 0;
785}
786
787/*
788 * like `umove' but make the additional effort of looking
789 * for a terminating zero byte.
790 */
791int
792umovestr(tcp, addr, len, laddr)
793struct tcb *tcp;
794long addr;
795int len;
796char *laddr;
797{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000798#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000799#ifdef HAVE_MP_PROCFS
800 int fd = tcp->pfd_as;
801#else
802 int fd = tcp->pfd;
803#endif
804 /* Some systems (e.g. FreeBSD) can be upset if we read off the
805 end of valid memory, avoid this by trying to read up
806 to page boundaries. But we don't know what a page is (and
807 getpagesize(2) (if it exists) doesn't necessarily return
808 hardware page size). Assume all pages >= 1024 (a-historical
809 I know) */
810
811 int page = 1024; /* How to find this? */
812 int move = page - (addr & (page - 1));
813 int left = len;
814
815 lseek(fd, addr, SEEK_SET);
816
817 while (left) {
818 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000819 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000820 return left != len ? 0 : -1;
821 if (memchr (laddr, 0, move)) break;
822 left -= move;
823 laddr += move;
824 addr += move;
825 move = page;
826 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000827#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000828 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829 int pid = tcp->pid;
830 int i, n, m;
831 union {
832 long val;
833 char x[sizeof(long)];
834 } u;
835
836 if (addr & (sizeof(long) - 1)) {
837 /* addr not a multiple of sizeof(long) */
838 n = addr - (addr & -sizeof(long)); /* residue */
839 addr &= -sizeof(long); /* residue */
840 errno = 0;
841 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
842 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000843 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000844 /* Ran into 'end of memory' - stupid "printpath" */
845 return 0;
846 }
847 perror("umovestr");
848 return -1;
849 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000850 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
852 while (n & (sizeof(long) - 1))
853 if (u.x[n++] == '\0')
854 return 0;
855 addr += sizeof(long), laddr += m, len -= m;
856 }
857 while (len) {
858 errno = 0;
859 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
860 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000861 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000862 /* Ran into 'end of memory' - stupid "printpath" */
863 return 0;
864 }
865 perror("umovestr");
866 return -1;
867 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000868 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000869 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
870 for (i = 0; i < sizeof(long); i++)
871 if (u.x[i] == '\0')
872 return 0;
873
874 addr += sizeof(long), laddr += m, len -= m;
875 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000876#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000877 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878}
879
880#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000881#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882#define PTRACE_WRITETEXT 101
883#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000884#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885#endif /* LINUX */
886
887#ifdef SUNOS4
888
889static int
890uload(cmd, pid, addr, len, laddr)
891int cmd;
892int pid;
893long addr;
894int len;
895char *laddr;
896{
897#if 0
898 int n;
899
900 while (len) {
901 n = MIN(len, PAGSIZ);
902 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
903 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
904 perror("uload: ptrace(PTRACE_WRITE, ...)");
905 return -1;
906 }
907 len -= n;
908 addr += n;
909 laddr += n;
910 }
911#else
912 int peek, poke;
913 int n, m;
914 union {
915 long val;
916 char x[sizeof(long)];
917 } u;
918
919 if (cmd == PTRACE_WRITETEXT) {
920 peek = PTRACE_PEEKTEXT;
921 poke = PTRACE_POKETEXT;
922 }
923 else {
924 peek = PTRACE_PEEKDATA;
925 poke = PTRACE_POKEDATA;
926 }
927 if (addr & (sizeof(long) - 1)) {
928 /* addr not a multiple of sizeof(long) */
929 n = addr - (addr & -sizeof(long)); /* residue */
930 addr &= -sizeof(long);
931 errno = 0;
932 u.val = ptrace(peek, pid, (char *) addr, 0);
933 if (errno) {
934 perror("uload: POKE");
935 return -1;
936 }
937 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
938 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
939 perror("uload: POKE");
940 return -1;
941 }
942 addr += sizeof(long), laddr += m, len -= m;
943 }
944 while (len) {
945 if (len < sizeof(long))
946 u.val = ptrace(peek, pid, (char *) addr, 0);
947 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
948 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
949 perror("uload: POKE");
950 return -1;
951 }
952 addr += sizeof(long), laddr += m, len -= m;
953 }
954#endif
955 return 0;
956}
957
958int
959tload(pid, addr, len, laddr)
960int pid;
961int addr, len;
962char *laddr;
963{
964 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
965}
966
967int
968dload(pid, addr, len, laddr)
969int pid;
970int addr;
971int len;
972char *laddr;
973{
974 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
975}
976
977#endif /* SUNOS4 */
978
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000979#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980
981int
982upeek(pid, off, res)
983int pid;
984long off;
985long *res;
986{
987 long val;
988
989#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
990 {
991 static int is_sun4m = -1;
992 struct utsname name;
993
994 /* Round up the usual suspects. */
995 if (is_sun4m == -1) {
996 if (uname(&name) < 0) {
997 perror("upeek: uname?");
998 exit(1);
999 }
1000 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1001 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001002 extern const struct xlat struct_user_offsets[];
1003 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004
1005 for (x = struct_user_offsets; x->str; x++)
1006 x->val += 1024;
1007 }
1008 }
1009 if (is_sun4m)
1010 off += 1024;
1011 }
1012#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1013 errno = 0;
1014 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1015 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001016 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001017 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001018 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 return -1;
1020 }
1021 *res = val;
1022 return 0;
1023}
1024
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001025#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026
Roland McGratha4d48532005-06-08 20:45:28 +00001027#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028long
1029getpc(tcp)
1030struct tcb *tcp;
1031{
1032
1033#ifdef LINUX
1034 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001035#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1037 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001038#elif defined(X86_64)
1039 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1040 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001041#elif defined(IA64)
1042 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1043 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001044#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 if (upeek(tcp->pid, 4*15, &pc) < 0)
1046 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001047#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001048 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001050#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1052 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001053#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1055 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001056#elif defined(MIPS)
1057 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1058 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001059#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001060 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1062 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001063 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001064#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001065 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001066 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001067#elif defined(HPPA)
1068 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1069 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001070#elif defined(SH)
1071 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1072 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001073#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001074 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1075 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001076#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 return pc;
1078#endif /* LINUX */
1079
1080#ifdef SUNOS4
1081 /*
1082 * Return current program counter for `pid'
1083 * Assumes PC is never 0xffffffff
1084 */
1085 struct regs regs;
1086
1087 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1088 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1089 return -1;
1090 }
1091 return regs.r_pc;
1092#endif /* SUNOS4 */
1093
1094#ifdef SVR4
1095 /* XXX */
1096 return 0;
1097#endif /* SVR4 */
1098
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001099#ifdef FREEBSD
1100 struct reg regs;
1101 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1102 return regs.r_eip;
1103#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104}
Roland McGratha4d48532005-06-08 20:45:28 +00001105#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106
1107void
1108printcall(tcp)
1109struct tcb *tcp;
1110{
Roland McGrath7a918832005-02-02 20:55:23 +00001111#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1112 sizeof(long) == 8 ? "[????????????????] " : \
1113 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114
1115#ifdef LINUX
1116#ifdef I386
1117 long eip;
1118
1119 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001120 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 return;
1122 }
1123 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001124
1125#elif defined(S390) || defined(S390X)
1126 long psw;
1127 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001128 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001129 return;
1130 }
1131#ifdef S390
1132 tprintf("[%08lx] ", psw);
1133#elif S390X
1134 tprintf("[%16lx] ", psw);
1135#endif
1136
Michal Ludvig0e035502002-09-23 15:41:01 +00001137#elif defined(X86_64)
1138 long rip;
1139
1140 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001141 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001142 return;
1143 }
1144 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001145#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001146 long ip;
1147
1148 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001149 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001150 return;
1151 }
1152 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001153#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 long pc;
1155
Roland McGratheb285352003-01-14 09:59:00 +00001156 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 tprintf ("[????????] ");
1158 return;
1159 }
1160 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001161#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 long pc;
1163
1164 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1165 tprintf ("[????????] ");
1166 return;
1167 }
1168 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001169#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 long pc;
1171
1172 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001173 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 return;
1175 }
1176 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001177#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001178 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001180 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 return;
1182 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001183 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001184#elif defined(HPPA)
1185 long pc;
1186
1187 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1188 tprintf ("[????????] ");
1189 return;
1190 }
1191 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001192#elif defined(MIPS)
1193 long pc;
1194
1195 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1196 tprintf ("[????????] ");
1197 return;
1198 }
1199 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001200#elif defined(SH)
1201 long pc;
1202
1203 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1204 tprintf ("[????????] ");
1205 return;
1206 }
1207 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001208#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001209 long pc;
1210
1211 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001212 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001213 return;
1214 }
1215 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001216#elif defined(ARM)
1217 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001218
Roland McGrathef388682003-06-03 23:28:59 +00001219 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001220 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001221 return;
1222 }
1223 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001224#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225#endif /* LINUX */
1226
1227#ifdef SUNOS4
1228 struct regs regs;
1229
1230 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1231 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001232 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 return;
1234 }
1235 tprintf("[%08x] ", regs.r_o7);
1236#endif /* SUNOS4 */
1237
1238#ifdef SVR4
1239 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001240 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241#endif
1242
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001243#ifdef FREEBSD
1244 struct reg regs;
1245 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1246 tprintf("[%08x] ", regs.r_eip);
1247#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248}
1249
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001250#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252#if defined LINUX
1253
1254#include <sys/syscall.h>
1255#ifndef CLONE_PTRACE
1256# define CLONE_PTRACE 0x00002000
1257#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001258#ifndef CLONE_STOPPED
1259# define CLONE_STOPPED 0x02000000
1260#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261
1262#ifdef IA64
1263
Roland McGrath08267b82004-02-20 22:56:43 +00001264/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1265 subsystem has them for x86... */
1266#define SYS_fork 2
1267#define SYS_vfork 190
1268
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269typedef unsigned long *arg_setup_state;
1270
1271static int
1272arg_setup(struct tcb *tcp, arg_setup_state *state)
1273{
1274 unsigned long *bsp, cfm, sof, sol;
1275
Roland McGrath08267b82004-02-20 22:56:43 +00001276 if (ia32)
1277 return 0;
1278
Roland McGrathd81f1d92003-01-09 06:53:34 +00001279 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1280 return -1;
1281 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1282 return -1;
1283
1284 sof = (cfm >> 0) & 0x7f;
1285 sol = (cfm >> 7) & 0x7f;
1286 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1287
1288 *state = bsp;
1289 return 0;
1290}
1291
1292# define arg_finish_change(tcp, state) 0
1293
1294#ifdef SYS_fork
1295static int
1296get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1297{
Roland McGrath08267b82004-02-20 22:56:43 +00001298 int ret;
1299
1300 if (ia32)
1301 ret = upeek (tcp->pid, PT_R11, valp);
1302 else
1303 ret = umoven (tcp,
1304 (unsigned long) ia64_rse_skip_regs(*state, 0),
1305 sizeof(long), (void *) valp);
1306 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307}
1308
1309static int
1310get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1311{
Roland McGrath08267b82004-02-20 22:56:43 +00001312 int ret;
1313
1314 if (ia32)
1315 ret = upeek (tcp->pid, PT_R9, valp);
1316 else
1317 ret = umoven (tcp,
1318 (unsigned long) ia64_rse_skip_regs(*state, 1),
1319 sizeof(long), (void *) valp);
1320 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001321}
1322#endif
1323
1324static int
1325set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1326{
Roland McGrath08267b82004-02-20 22:56:43 +00001327 int req = PTRACE_POKEDATA;
1328 void *ap;
1329
1330 if (ia32) {
1331 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1332 req = PTRACE_POKEUSER;
1333 } else
1334 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001335 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001336 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337 return errno ? -1 : 0;
1338}
1339
1340static int
1341set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1342{
Roland McGrath08267b82004-02-20 22:56:43 +00001343 int req = PTRACE_POKEDATA;
1344 void *ap;
1345
1346 if (ia32) {
1347 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1348 req = PTRACE_POKEUSER;
1349 } else
1350 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001352 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001353 return errno ? -1 : 0;
1354}
1355
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001356#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357
1358typedef struct regs arg_setup_state;
1359
1360# define arg_setup(tcp, state) \
1361 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1362# define arg_finish_change(tcp, state) \
1363 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1364
1365# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1366# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1367# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1368# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001369# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001370
1371#else
1372
1373# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001374/* Note: this is only true for the `clone' system call, which handles
1375 arguments specially. We could as well say that its first two arguments
1376 are swapped relative to other architectures, but that would just be
1377 another #ifdef in the calls. */
1378# define arg0_offset PT_GPR3
1379# define arg1_offset PT_ORIGGPR2
1380# define restore_arg0(tcp, state, val) ((void) (state), 0)
1381# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001382# define arg0_index 1
1383# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001384# elif defined (ALPHA) || defined (MIPS)
1385# define arg0_offset REG_A0
1386# define arg1_offset (REG_A0+1)
1387# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001388# define arg0_offset (sizeof(unsigned long)*PT_R3)
1389# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001390# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001391# elif defined (HPPA)
1392# define arg0_offset PT_GR26
1393# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001394# elif defined (X86_64)
1395# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1396# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001397# elif defined (SH)
1398# define arg0_offset (4*(REG_REG0+4))
1399# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001400# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001401 /* ABI defines arg0 & 1 in r2 & r3 */
1402# define arg0_offset (REG_OFFSET+16)
1403# define arg1_offset (REG_OFFSET+24)
1404# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001405# else
1406# define arg0_offset 0
1407# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001408# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001409# define restore_arg0(tcp, state, val) 0
1410# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411# endif
1412
1413typedef int arg_setup_state;
1414
1415# define arg_setup(tcp, state) (0)
1416# define arg_finish_change(tcp, state) 0
1417# define get_arg0(tcp, cookie, valp) \
1418 (upeek ((tcp)->pid, arg0_offset, (valp)))
1419# define get_arg1(tcp, cookie, valp) \
1420 (upeek ((tcp)->pid, arg1_offset, (valp)))
1421
1422static int
1423set_arg0 (struct tcb *tcp, void *cookie, long val)
1424{
Roland McGrathca85b972005-06-07 23:22:08 +00001425 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001426}
1427
1428static int
1429set_arg1 (struct tcb *tcp, void *cookie, long val)
1430{
1431 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1432}
1433
1434#endif
1435
Roland McGrathe1df47f2003-01-14 09:46:15 +00001436#ifndef restore_arg0
1437# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1438#endif
1439#ifndef restore_arg1
1440# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1441#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001442
Roland McGrath90d0afd2004-03-01 21:05:16 +00001443#ifndef arg0_index
1444# define arg0_index 0
1445# define arg1_index 1
1446#endif
1447
Roland McGrathd81f1d92003-01-09 06:53:34 +00001448int
1449setbpt(tcp)
1450struct tcb *tcp;
1451{
1452 extern int change_syscall(struct tcb *, int);
1453 arg_setup_state state;
1454
1455 if (tcp->flags & TCB_BPTSET) {
1456 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1457 return -1;
1458 }
1459
Roland McGrath76989d72005-06-07 23:21:31 +00001460 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001461#ifdef SYS_vfork
1462 case SYS_vfork:
1463#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001464#ifdef SYS_fork
1465 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001466#endif
1467#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468 if (arg_setup (tcp, &state) < 0
1469 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1470 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1471 || change_syscall(tcp, SYS_clone) < 0
1472 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1473 || set_arg1 (tcp, &state, 0) < 0
1474 || arg_finish_change (tcp, &state) < 0)
1475 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001476 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1477 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001478 tcp->flags |= TCB_BPTSET;
1479 return 0;
1480#endif
1481
1482 case SYS_clone:
1483#ifdef SYS_clone2
1484 case SYS_clone2:
1485#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001486 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001487 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001488 || set_arg0 (tcp, &state,
1489 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001490 || arg_finish_change (tcp, &state) < 0))
1491 return -1;
1492 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001493 tcp->inst[0] = tcp->u_arg[arg0_index];
1494 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001495 return 0;
1496
1497 default:
1498 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1499 tcp->scno, tcp->pid);
1500 break;
1501 }
1502
1503 return -1;
1504}
1505
1506int
1507clearbpt(tcp)
1508struct tcb *tcp;
1509{
1510 arg_setup_state state;
1511 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001512 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1513 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001514 || arg_finish_change (tcp, &state))
1515 return -1;
1516 tcp->flags &= ~TCB_BPTSET;
1517 return 0;
1518}
1519
1520#else
1521
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522int
1523setbpt(tcp)
1524struct tcb *tcp;
1525{
1526
1527#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001528#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 /* We simply use the SunOS breakpoint code. */
1530
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001531 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001532 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533#define LOOPA 0x30800000 /* ba,a 0 */
1534
1535 if (tcp->flags & TCB_BPTSET) {
1536 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1537 return -1;
1538 }
1539 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1540 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1541 return -1;
1542 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001543 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 errno = 0;
1545 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1546 if(errno) {
1547 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1548 return -1;
1549 }
1550
1551 /*
1552 * XXX - BRUTAL MODE ON
1553 * We cannot set a real BPT in the child, since it will not be
1554 * traced at the moment it will reach the trap and would probably
1555 * die with a core dump.
1556 * Thus, we are force our way in by taking out two instructions
1557 * and insert an eternal loop instead, in expectance of the SIGSTOP
1558 * generated by out PTRACE_ATTACH.
1559 * Of cause, if we evaporate ourselves in the middle of all this...
1560 */
1561 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001562 inst = LOOPA;
1563#if defined (SPARC64)
1564 inst <<= 32;
1565 inst |= (tcp->inst[0] & 0xffffffffUL);
1566#endif
1567 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568 if(errno) {
1569 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1570 return -1;
1571 }
1572 tcp->flags |= TCB_BPTSET;
1573
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001574#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001575#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001576 if (ia32) {
1577# define LOOP 0x0000feeb
1578 if (tcp->flags & TCB_BPTSET) {
1579 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1580 tcp->pid);
1581 return -1;
1582 }
1583 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1584 return -1;
1585 if (debug)
1586 fprintf(stderr, "[%d] setting bpt at %lx\n",
1587 tcp->pid, tcp->baddr);
1588 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1589 (char *) tcp->baddr, 0);
1590 if (errno) {
1591 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1592 return -1;
1593 }
1594 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1595 if (errno) {
1596 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1597 return -1;
1598 }
1599 tcp->flags |= TCB_BPTSET;
1600 } else {
1601 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001602 * Our strategy here is to replace the bundle that
1603 * contained the clone() syscall with a bundle of the
1604 * form:
1605 *
1606 * { 1: br 1b; br 1b; br 1b }
1607 *
1608 * This ensures that the newly forked child will loop
1609 * endlessly until we've got a chance to attach to it.
1610 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001611# define LOOP0 0x0000100000000017
1612# define LOOP1 0x4000000000200000
1613 unsigned long addr, ipsr;
1614 pid_t pid;
1615
1616 pid = tcp->pid;
1617 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1618 return -1;
1619 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1620 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001621 /* store "ri" in low two bits */
1622 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001623
1624 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001625 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1626 0);
1627 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1628 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001629 if (errno) {
1630 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1631 return -1;
1632 }
1633
1634 errno = 0;
1635 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1636 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1637 if (errno) {
1638 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1639 return -1;
1640 }
1641 tcp->flags |= TCB_BPTSET;
1642 }
1643#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644
Michal Ludvig0e035502002-09-23 15:41:01 +00001645#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646#define LOOP 0x0000feeb
1647#elif defined (M68K)
1648#define LOOP 0x60fe0000
1649#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001650#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001652#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001654#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001655#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001656#define LOOP 0x1000ffff
1657#elif defined(S390)
1658#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001659#elif defined(S390X)
1660#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001661#elif defined(HPPA)
1662#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001663#elif defined(SH)
1664#ifdef __LITTLE_ENDIAN__
1665#define LOOP 0x0000affe
1666#else
1667#define LOOP 0xfeaf0000
1668#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669#else
1670#error unknown architecture
1671#endif
1672
1673 if (tcp->flags & TCB_BPTSET) {
1674 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1675 return -1;
1676 }
1677#if defined (I386)
1678 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1679 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001680#elif defined (X86_64)
1681 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1682 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683#elif defined (M68K)
1684 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1685 return -1;
1686#elif defined (ALPHA)
1687 return -1;
1688#elif defined (ARM)
1689 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001690#elif defined (MIPS)
1691 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001693 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001695#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001696 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1697 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001698#elif defined(HPPA)
1699 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1700 return -1;
1701 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001702#elif defined(SH)
1703 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1704 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705#else
1706#error unknown architecture
1707#endif
1708 if (debug)
1709 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1710 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1711 if (errno) {
1712 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1713 return -1;
1714 }
1715 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1716 if (errno) {
1717 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1718 return -1;
1719 }
1720 tcp->flags |= TCB_BPTSET;
1721
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001722#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001723#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724#endif /* LINUX */
1725
1726#ifdef SUNOS4
1727#ifdef SPARC /* This code is slightly sparc specific */
1728
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001729 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730#define BPT 0x91d02001 /* ta 1 */
1731#define LOOP 0x10800000 /* ba 0 */
1732#define LOOPA 0x30800000 /* ba,a 0 */
1733#define NOP 0x01000000
1734#if LOOPA
1735 static int loopdeloop[1] = {LOOPA};
1736#else
1737 static int loopdeloop[2] = {LOOP, NOP};
1738#endif
1739
1740 if (tcp->flags & TCB_BPTSET) {
1741 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1742 return -1;
1743 }
1744 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1745 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1746 return -1;
1747 }
1748 tcp->baddr = regs.r_o7 + 8;
1749 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1750 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1751 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1752 return -1;
1753 }
1754
1755 /*
1756 * XXX - BRUTAL MODE ON
1757 * We cannot set a real BPT in the child, since it will not be
1758 * traced at the moment it will reach the trap and would probably
1759 * die with a core dump.
1760 * Thus, we are force our way in by taking out two instructions
1761 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1762 * generated by out PTRACE_ATTACH.
1763 * Of cause, if we evaporate ourselves in the middle of all this...
1764 */
1765 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1766 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1767 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1768 return -1;
1769 }
1770 tcp->flags |= TCB_BPTSET;
1771
1772#endif /* SPARC */
1773#endif /* SUNOS4 */
1774
1775 return 0;
1776}
1777
1778int
1779clearbpt(tcp)
1780struct tcb *tcp;
1781{
1782
1783#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001784#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001786#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001788#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001790#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001792#elif defined(HPPA)
1793 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001794#elif defined(SH)
1795 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001796#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001798#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799 /* Again, we borrow the SunOS breakpoint code. */
1800 if (!(tcp->flags & TCB_BPTSET)) {
1801 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1802 return -1;
1803 }
1804 errno = 0;
1805 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1806 if(errno) {
1807 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1808 return -1;
1809 }
1810 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001811#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001812 if (ia32) {
1813 unsigned long addr;
1814
1815 if (debug)
1816 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1817 if (!(tcp->flags & TCB_BPTSET)) {
1818 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1819 return -1;
1820 }
1821 errno = 0;
1822 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1823 if (errno) {
1824 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1825 return -1;
1826 }
1827 tcp->flags &= ~TCB_BPTSET;
1828
1829 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1830 return -1;
1831 if (addr != tcp->baddr) {
1832 /* The breakpoint has not been reached yet. */
1833 if (debug)
1834 fprintf(stderr,
1835 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1836 addr, tcp->baddr);
1837 return 0;
1838 }
1839 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001840 unsigned long addr, ipsr;
1841 pid_t pid;
1842
1843 pid = tcp->pid;
1844
1845 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1846 return -1;
1847 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1848 return -1;
1849
1850 /* restore original bundle: */
1851 errno = 0;
1852 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1853 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1854 if (errno) {
1855 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1856 return -1;
1857 }
1858
1859 /* restore original "ri" in ipsr: */
1860 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1861 errno = 0;
1862 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1863 if (errno) {
1864 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1865 return -1;
1866 }
1867
1868 tcp->flags &= ~TCB_BPTSET;
1869
1870 if (addr != (tcp->baddr & ~0x3)) {
1871 /* the breakpoint has not been reached yet. */
1872 if (debug)
1873 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1874 addr, tcp->baddr);
1875 return 0;
1876 }
1877 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001878#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879
1880 if (debug)
1881 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1882 if (!(tcp->flags & TCB_BPTSET)) {
1883 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1884 return -1;
1885 }
1886 errno = 0;
1887 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1888 if (errno) {
1889 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1890 return -1;
1891 }
1892 tcp->flags &= ~TCB_BPTSET;
1893
1894#ifdef I386
1895 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1896 return -1;
1897 if (eip != tcp->baddr) {
1898 /* The breakpoint has not been reached yet. */
1899 if (debug)
1900 fprintf(stderr,
1901 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1902 eip, tcp->baddr);
1903 return 0;
1904 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001905#elif defined(X86_64)
1906 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1907 return -1;
1908 if (eip != 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 eip, tcp->baddr);
1914 return 0;
1915 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001916#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001917 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001918 return -1;
1919 if (pc != tcp->baddr) {
1920 /* The breakpoint has not been reached yet. */
1921 if (debug)
1922 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1923 pc, tcp->baddr);
1924 return 0;
1925 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001926#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1928 return -1;
1929 if (pc != tcp->baddr) {
1930 /* The breakpoint has not been reached yet. */
1931 if (debug)
1932 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1933 pc, tcp->baddr);
1934 return 0;
1935 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001936#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1938 return -1;
1939 if (pc != tcp->baddr) {
1940 /* The breakpoint has not been reached yet. */
1941 if (debug)
1942 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1943 pc, tcp->baddr);
1944 return 0;
1945 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001946#elif defined(HPPA)
1947 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1948 return -1;
1949 iaoq &= ~0x03;
1950 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1951 /* The breakpoint has not been reached yet. */
1952 if (debug)
1953 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1954 iaoq, tcp->baddr);
1955 return 0;
1956 }
1957 iaoq = tcp->baddr | 3;
1958 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1959 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1960 * has no significant effect.
1961 */
1962 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1963 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001964#elif defined(SH)
1965 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1966 return -1;
1967 if (pc != tcp->baddr) {
1968 /* The breakpoint has not been reached yet. */
1969 if (debug)
1970 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1971 pc, tcp->baddr);
1972 return 0;
1973 }
1974
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001975#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001976#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977#endif /* LINUX */
1978
1979#ifdef SUNOS4
1980#ifdef SPARC
1981
1982#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001983 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984#endif
1985
1986 if (!(tcp->flags & TCB_BPTSET)) {
1987 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1988 return -1;
1989 }
1990 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1991 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1992 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1993 return -1;
1994 }
1995 tcp->flags &= ~TCB_BPTSET;
1996
1997#if !LOOPA
1998 /*
1999 * Since we don't have a single instruction breakpoint, we may have
2000 * to adjust the program counter after removing the our `breakpoint'.
2001 */
2002 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2003 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2004 return -1;
2005 }
2006 if ((regs.r_pc < tcp->baddr) ||
2007 (regs.r_pc > tcp->baddr + 4)) {
2008 /* The breakpoint has not been reached yet */
2009 if (debug)
2010 fprintf(stderr,
2011 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2012 regs.r_pc, tcp->parent->baddr);
2013 return 0;
2014 }
2015 if (regs.r_pc != tcp->baddr)
2016 if (debug)
2017 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2018 regs.r_pc, tcp->baddr);
2019
2020 regs.r_pc = tcp->baddr;
2021 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2022 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2023 return -1;
2024 }
2025#endif /* LOOPA */
2026#endif /* SPARC */
2027#endif /* SUNOS4 */
2028
2029 return 0;
2030}
2031
Roland McGrathd81f1d92003-01-09 06:53:34 +00002032#endif
2033
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002034#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035
2036#ifdef SUNOS4
2037
2038static int
2039getex(pid, hdr)
2040int pid;
2041struct exec *hdr;
2042{
2043 int n;
2044
2045 for (n = 0; n < sizeof *hdr; n += 4) {
2046 long res;
2047 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2048 return -1;
2049 memcpy(((char *) hdr) + n, &res, 4);
2050 }
2051 if (debug) {
2052 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2053 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2054 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2055 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2056 }
2057 return 0;
2058}
2059
2060int
2061fixvfork(tcp)
2062struct tcb *tcp;
2063{
2064 int pid = tcp->pid;
2065 /*
2066 * Change `vfork' in a freshly exec'ed dynamically linked
2067 * executable's (internal) symbol table to plain old `fork'
2068 */
2069
2070 struct exec hdr;
2071 struct link_dynamic dyn;
2072 struct link_dynamic_2 ld;
2073 char *strtab, *cp;
2074
2075 if (getex(pid, &hdr) < 0)
2076 return -1;
2077 if (!hdr.a_dynamic)
2078 return -1;
2079
2080 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2081 fprintf(stderr, "Cannot read DYNAMIC\n");
2082 return -1;
2083 }
2084 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2085 fprintf(stderr, "Cannot read link_dynamic_2\n");
2086 return -1;
2087 }
2088 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002089 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 return -1;
2091 }
2092 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2093 (int)ld.ld_symb_size, strtab) < 0)
2094 goto err;
2095
2096#if 0
2097 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2098 fprintf(stderr, "[symbol: %s]\n", cp);
2099 cp += strlen(cp)+1;
2100 }
2101 return 0;
2102#endif
2103 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2104 if (strcmp(cp, "_vfork") == 0) {
2105 if (debug)
2106 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2107 strcpy(cp, "_fork");
2108 break;
2109 }
2110 cp += strlen(cp)+1;
2111 }
2112 if (cp < strtab + ld.ld_symb_size)
2113 /*
2114 * Write entire symbol table back to avoid
2115 * memory alignment bugs in ptrace
2116 */
2117 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2118 (int)ld.ld_symb_size, strtab) < 0)
2119 goto err;
2120
2121 free(strtab);
2122 return 0;
2123
2124err:
2125 free(strtab);
2126 return -1;
2127}
2128
2129#endif /* SUNOS4 */