blob: cfe975590bf77fa5fd6406e46588e1f838e44058 [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. */
Roland McGrath1c459762007-08-02 02:22:06 +0000697 if (addr != 0 && errno != EIO)
698 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699 return -1;
700 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000701 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000702 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
703 addr += sizeof(long), laddr += m, len -= m;
704 }
705 while (len) {
706 errno = 0;
707 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
708 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000709 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000710 /* Ran into 'end of memory' - stupid "printpath" */
711 return 0;
712 }
Roland McGrath1c459762007-08-02 02:22:06 +0000713 if (addr != 0 && errno != EIO)
Roland McGrath4db26242003-01-30 20:15:19 +0000714 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 return -1;
716 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000717 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
719 addr += sizeof(long), laddr += m, len -= m;
720 }
721#endif /* LINUX */
722
723#ifdef SUNOS4
724 int pid = tcp->pid;
725#if 0
726 int n, m;
727 union {
728 long val;
729 char x[sizeof(long)];
730 } u;
731
732 if (addr & (sizeof(long) - 1)) {
733 /* addr not a multiple of sizeof(long) */
734 n = addr - (addr & -sizeof(long)); /* residue */
735 addr &= -sizeof(long); /* residue */
736 errno = 0;
737 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
738 if (errno) {
739 perror("umoven");
740 return -1;
741 }
742 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
743 addr += sizeof(long), laddr += m, len -= m;
744 }
745 while (len) {
746 errno = 0;
747 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
748 if (errno) {
749 perror("umoven");
750 return -1;
751 }
752 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
753 addr += sizeof(long), laddr += m, len -= m;
754 }
755#else /* !oldway */
756 int n;
757
758 while (len) {
759 n = MIN(len, PAGSIZ);
760 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
761 if (ptrace(PTRACE_READDATA, pid,
762 (char *) addr, len, laddr) < 0) {
763 perror("umoven: ptrace(PTRACE_READDATA, ...)");
764 abort();
765 return -1;
766 }
767 len -= n;
768 addr += n;
769 laddr += n;
770 }
771#endif /* !oldway */
772#endif /* SUNOS4 */
773
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000774#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000775#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000776 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000777#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000778 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000780 lseek(fd, addr, SEEK_SET);
781 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000783#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784
785 return 0;
786}
787
788/*
789 * like `umove' but make the additional effort of looking
790 * for a terminating zero byte.
791 */
792int
793umovestr(tcp, addr, len, laddr)
794struct tcb *tcp;
795long addr;
796int len;
797char *laddr;
798{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000799#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000800#ifdef HAVE_MP_PROCFS
801 int fd = tcp->pfd_as;
802#else
803 int fd = tcp->pfd;
804#endif
805 /* Some systems (e.g. FreeBSD) can be upset if we read off the
806 end of valid memory, avoid this by trying to read up
807 to page boundaries. But we don't know what a page is (and
808 getpagesize(2) (if it exists) doesn't necessarily return
809 hardware page size). Assume all pages >= 1024 (a-historical
810 I know) */
811
812 int page = 1024; /* How to find this? */
813 int move = page - (addr & (page - 1));
814 int left = len;
815
816 lseek(fd, addr, SEEK_SET);
817
818 while (left) {
819 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000820 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000821 return left != len ? 0 : -1;
822 if (memchr (laddr, 0, move)) break;
823 left -= move;
824 laddr += move;
825 addr += move;
826 move = page;
827 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000828#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000829 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830 int pid = tcp->pid;
831 int i, n, m;
832 union {
833 long val;
834 char x[sizeof(long)];
835 } u;
836
837 if (addr & (sizeof(long) - 1)) {
838 /* addr not a multiple of sizeof(long) */
839 n = addr - (addr & -sizeof(long)); /* residue */
840 addr &= -sizeof(long); /* residue */
841 errno = 0;
842 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
843 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000844 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 /* Ran into 'end of memory' - stupid "printpath" */
846 return 0;
847 }
Roland McGrath1c459762007-08-02 02:22:06 +0000848 if (addr != 0 && errno != EIO)
849 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 return -1;
851 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000852 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
854 while (n & (sizeof(long) - 1))
855 if (u.x[n++] == '\0')
856 return 0;
857 addr += sizeof(long), laddr += m, len -= m;
858 }
859 while (len) {
860 errno = 0;
861 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
862 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000863 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 /* Ran into 'end of memory' - stupid "printpath" */
865 return 0;
866 }
Roland McGrath1c459762007-08-02 02:22:06 +0000867 if (addr != 0 && errno != EIO)
868 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000869 return -1;
870 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000871 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
873 for (i = 0; i < sizeof(long); i++)
874 if (u.x[i] == '\0')
875 return 0;
876
877 addr += sizeof(long), laddr += m, len -= m;
878 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000879#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000880 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881}
882
883#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000884#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885#define PTRACE_WRITETEXT 101
886#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000887#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888#endif /* LINUX */
889
890#ifdef SUNOS4
891
892static int
893uload(cmd, pid, addr, len, laddr)
894int cmd;
895int pid;
896long addr;
897int len;
898char *laddr;
899{
900#if 0
901 int n;
902
903 while (len) {
904 n = MIN(len, PAGSIZ);
905 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
906 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
907 perror("uload: ptrace(PTRACE_WRITE, ...)");
908 return -1;
909 }
910 len -= n;
911 addr += n;
912 laddr += n;
913 }
914#else
915 int peek, poke;
916 int n, m;
917 union {
918 long val;
919 char x[sizeof(long)];
920 } u;
921
922 if (cmd == PTRACE_WRITETEXT) {
923 peek = PTRACE_PEEKTEXT;
924 poke = PTRACE_POKETEXT;
925 }
926 else {
927 peek = PTRACE_PEEKDATA;
928 poke = PTRACE_POKEDATA;
929 }
930 if (addr & (sizeof(long) - 1)) {
931 /* addr not a multiple of sizeof(long) */
932 n = addr - (addr & -sizeof(long)); /* residue */
933 addr &= -sizeof(long);
934 errno = 0;
935 u.val = ptrace(peek, pid, (char *) addr, 0);
936 if (errno) {
937 perror("uload: POKE");
938 return -1;
939 }
940 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
941 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
942 perror("uload: POKE");
943 return -1;
944 }
945 addr += sizeof(long), laddr += m, len -= m;
946 }
947 while (len) {
948 if (len < sizeof(long))
949 u.val = ptrace(peek, pid, (char *) addr, 0);
950 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
951 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
952 perror("uload: POKE");
953 return -1;
954 }
955 addr += sizeof(long), laddr += m, len -= m;
956 }
957#endif
958 return 0;
959}
960
961int
962tload(pid, addr, len, laddr)
963int pid;
964int addr, len;
965char *laddr;
966{
967 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
968}
969
970int
971dload(pid, addr, len, laddr)
972int pid;
973int addr;
974int len;
975char *laddr;
976{
977 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
978}
979
980#endif /* SUNOS4 */
981
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000982#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983
984int
985upeek(pid, off, res)
986int pid;
987long off;
988long *res;
989{
990 long val;
991
992#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
993 {
994 static int is_sun4m = -1;
995 struct utsname name;
996
997 /* Round up the usual suspects. */
998 if (is_sun4m == -1) {
999 if (uname(&name) < 0) {
1000 perror("upeek: uname?");
1001 exit(1);
1002 }
1003 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1004 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001005 extern const struct xlat struct_user_offsets[];
1006 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007
1008 for (x = struct_user_offsets; x->str; x++)
1009 x->val += 1024;
1010 }
1011 }
1012 if (is_sun4m)
1013 off += 1024;
1014 }
1015#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1016 errno = 0;
1017 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1018 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001019 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001020 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001021 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 return -1;
1023 }
1024 *res = val;
1025 return 0;
1026}
1027
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001028#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029
Roland McGratha4d48532005-06-08 20:45:28 +00001030#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031long
1032getpc(tcp)
1033struct tcb *tcp;
1034{
1035
1036#ifdef LINUX
1037 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001038#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1040 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001041#elif defined(X86_64)
1042 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1043 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001044#elif defined(IA64)
1045 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1046 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001047#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 if (upeek(tcp->pid, 4*15, &pc) < 0)
1049 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001050#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001051 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001053#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1055 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001056#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1058 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001059#elif defined(MIPS)
1060 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1061 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001062#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001063 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1065 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001066 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001067#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001068 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001069 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001070#elif defined(HPPA)
1071 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1072 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001073#elif defined(SH)
1074 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1075 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001076#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001077 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1078 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001079#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080 return pc;
1081#endif /* LINUX */
1082
1083#ifdef SUNOS4
1084 /*
1085 * Return current program counter for `pid'
1086 * Assumes PC is never 0xffffffff
1087 */
1088 struct regs regs;
1089
1090 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1091 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1092 return -1;
1093 }
1094 return regs.r_pc;
1095#endif /* SUNOS4 */
1096
1097#ifdef SVR4
1098 /* XXX */
1099 return 0;
1100#endif /* SVR4 */
1101
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001102#ifdef FREEBSD
1103 struct reg regs;
1104 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1105 return regs.r_eip;
1106#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107}
Roland McGratha4d48532005-06-08 20:45:28 +00001108#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109
1110void
1111printcall(tcp)
1112struct tcb *tcp;
1113{
Roland McGrath7a918832005-02-02 20:55:23 +00001114#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1115 sizeof(long) == 8 ? "[????????????????] " : \
1116 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117
1118#ifdef LINUX
1119#ifdef I386
1120 long eip;
1121
1122 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001123 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 return;
1125 }
1126 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001127
1128#elif defined(S390) || defined(S390X)
1129 long psw;
1130 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001131 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001132 return;
1133 }
1134#ifdef S390
1135 tprintf("[%08lx] ", psw);
1136#elif S390X
1137 tprintf("[%16lx] ", psw);
1138#endif
1139
Michal Ludvig0e035502002-09-23 15:41:01 +00001140#elif defined(X86_64)
1141 long rip;
1142
1143 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001144 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001145 return;
1146 }
1147 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001148#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001149 long ip;
1150
1151 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001152 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001153 return;
1154 }
1155 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001156#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 long pc;
1158
Roland McGratheb285352003-01-14 09:59:00 +00001159 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160 tprintf ("[????????] ");
1161 return;
1162 }
1163 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001164#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 long pc;
1166
1167 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1168 tprintf ("[????????] ");
1169 return;
1170 }
1171 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001172#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 long pc;
1174
1175 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001176 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 return;
1178 }
1179 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001180#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001181 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001183 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 return;
1185 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001186 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001187#elif defined(HPPA)
1188 long pc;
1189
1190 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1191 tprintf ("[????????] ");
1192 return;
1193 }
1194 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001195#elif defined(MIPS)
1196 long pc;
1197
1198 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1199 tprintf ("[????????] ");
1200 return;
1201 }
1202 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001203#elif defined(SH)
1204 long pc;
1205
1206 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1207 tprintf ("[????????] ");
1208 return;
1209 }
1210 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001211#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001212 long pc;
1213
1214 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001215 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001216 return;
1217 }
1218 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001219#elif defined(ARM)
1220 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001221
Roland McGrathef388682003-06-03 23:28:59 +00001222 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001223 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001224 return;
1225 }
1226 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001227#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228#endif /* LINUX */
1229
1230#ifdef SUNOS4
1231 struct regs regs;
1232
1233 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1234 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001235 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 return;
1237 }
1238 tprintf("[%08x] ", regs.r_o7);
1239#endif /* SUNOS4 */
1240
1241#ifdef SVR4
1242 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001243 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244#endif
1245
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001246#ifdef FREEBSD
1247 struct reg regs;
1248 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1249 tprintf("[%08x] ", regs.r_eip);
1250#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251}
1252
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001253#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254
Roland McGrathd81f1d92003-01-09 06:53:34 +00001255#if defined LINUX
1256
1257#include <sys/syscall.h>
1258#ifndef CLONE_PTRACE
1259# define CLONE_PTRACE 0x00002000
1260#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001261#ifndef CLONE_STOPPED
1262# define CLONE_STOPPED 0x02000000
1263#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001264
1265#ifdef IA64
1266
Roland McGrath08267b82004-02-20 22:56:43 +00001267/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1268 subsystem has them for x86... */
1269#define SYS_fork 2
1270#define SYS_vfork 190
1271
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272typedef unsigned long *arg_setup_state;
1273
1274static int
1275arg_setup(struct tcb *tcp, arg_setup_state *state)
1276{
1277 unsigned long *bsp, cfm, sof, sol;
1278
Roland McGrath08267b82004-02-20 22:56:43 +00001279 if (ia32)
1280 return 0;
1281
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1283 return -1;
1284 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1285 return -1;
1286
1287 sof = (cfm >> 0) & 0x7f;
1288 sol = (cfm >> 7) & 0x7f;
1289 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1290
1291 *state = bsp;
1292 return 0;
1293}
1294
1295# define arg_finish_change(tcp, state) 0
1296
1297#ifdef SYS_fork
1298static int
1299get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1300{
Roland McGrath08267b82004-02-20 22:56:43 +00001301 int ret;
1302
1303 if (ia32)
1304 ret = upeek (tcp->pid, PT_R11, valp);
1305 else
1306 ret = umoven (tcp,
1307 (unsigned long) ia64_rse_skip_regs(*state, 0),
1308 sizeof(long), (void *) valp);
1309 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310}
1311
1312static int
1313get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1314{
Roland McGrath08267b82004-02-20 22:56:43 +00001315 int ret;
1316
1317 if (ia32)
1318 ret = upeek (tcp->pid, PT_R9, valp);
1319 else
1320 ret = umoven (tcp,
1321 (unsigned long) ia64_rse_skip_regs(*state, 1),
1322 sizeof(long), (void *) valp);
1323 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324}
1325#endif
1326
1327static int
1328set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1329{
Roland McGrath08267b82004-02-20 22:56:43 +00001330 int req = PTRACE_POKEDATA;
1331 void *ap;
1332
1333 if (ia32) {
1334 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1335 req = PTRACE_POKEUSER;
1336 } else
1337 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001339 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340 return errno ? -1 : 0;
1341}
1342
1343static int
1344set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1345{
Roland McGrath08267b82004-02-20 22:56:43 +00001346 int req = PTRACE_POKEDATA;
1347 void *ap;
1348
1349 if (ia32) {
1350 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1351 req = PTRACE_POKEUSER;
1352 } else
1353 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001354 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001355 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001356 return errno ? -1 : 0;
1357}
1358
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001359#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001360
1361typedef struct regs arg_setup_state;
1362
1363# define arg_setup(tcp, state) \
1364 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1365# define arg_finish_change(tcp, state) \
1366 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1367
1368# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1369# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1370# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1371# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001372# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001373
1374#else
1375
1376# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001377/* Note: this is only true for the `clone' system call, which handles
1378 arguments specially. We could as well say that its first two arguments
1379 are swapped relative to other architectures, but that would just be
1380 another #ifdef in the calls. */
1381# define arg0_offset PT_GPR3
1382# define arg1_offset PT_ORIGGPR2
1383# define restore_arg0(tcp, state, val) ((void) (state), 0)
1384# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001385# define arg0_index 1
1386# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001387# elif defined (ALPHA) || defined (MIPS)
1388# define arg0_offset REG_A0
1389# define arg1_offset (REG_A0+1)
1390# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001391# define arg0_offset (sizeof(unsigned long)*PT_R3)
1392# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001393# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001394# elif defined (HPPA)
1395# define arg0_offset PT_GR26
1396# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001397# elif defined (X86_64)
1398# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1399# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001400# elif defined (SH)
1401# define arg0_offset (4*(REG_REG0+4))
1402# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001403# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001404 /* ABI defines arg0 & 1 in r2 & r3 */
1405# define arg0_offset (REG_OFFSET+16)
1406# define arg1_offset (REG_OFFSET+24)
1407# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001408# else
1409# define arg0_offset 0
1410# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001411# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001412# define restore_arg0(tcp, state, val) 0
1413# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001414# endif
1415
1416typedef int arg_setup_state;
1417
1418# define arg_setup(tcp, state) (0)
1419# define arg_finish_change(tcp, state) 0
1420# define get_arg0(tcp, cookie, valp) \
1421 (upeek ((tcp)->pid, arg0_offset, (valp)))
1422# define get_arg1(tcp, cookie, valp) \
1423 (upeek ((tcp)->pid, arg1_offset, (valp)))
1424
1425static int
1426set_arg0 (struct tcb *tcp, void *cookie, long val)
1427{
Roland McGrathca85b972005-06-07 23:22:08 +00001428 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001429}
1430
1431static int
1432set_arg1 (struct tcb *tcp, void *cookie, long val)
1433{
1434 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1435}
1436
1437#endif
1438
Roland McGrathe1df47f2003-01-14 09:46:15 +00001439#ifndef restore_arg0
1440# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1441#endif
1442#ifndef restore_arg1
1443# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1444#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001445
Roland McGrath90d0afd2004-03-01 21:05:16 +00001446#ifndef arg0_index
1447# define arg0_index 0
1448# define arg1_index 1
1449#endif
1450
Roland McGrathd81f1d92003-01-09 06:53:34 +00001451int
1452setbpt(tcp)
1453struct tcb *tcp;
1454{
1455 extern int change_syscall(struct tcb *, int);
1456 arg_setup_state state;
1457
1458 if (tcp->flags & TCB_BPTSET) {
1459 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1460 return -1;
1461 }
1462
Roland McGrath76989d72005-06-07 23:21:31 +00001463 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001464#ifdef SYS_vfork
1465 case SYS_vfork:
1466#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001467#ifdef SYS_fork
1468 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001469#endif
1470#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001471 if (arg_setup (tcp, &state) < 0
1472 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1473 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1474 || change_syscall(tcp, SYS_clone) < 0
1475 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1476 || set_arg1 (tcp, &state, 0) < 0
1477 || arg_finish_change (tcp, &state) < 0)
1478 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001479 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1480 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001481 tcp->flags |= TCB_BPTSET;
1482 return 0;
1483#endif
1484
1485 case SYS_clone:
1486#ifdef SYS_clone2
1487 case SYS_clone2:
1488#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001489 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001490 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001491 || set_arg0 (tcp, &state,
1492 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001493 || arg_finish_change (tcp, &state) < 0))
1494 return -1;
1495 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001496 tcp->inst[0] = tcp->u_arg[arg0_index];
1497 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001498 return 0;
1499
1500 default:
1501 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1502 tcp->scno, tcp->pid);
1503 break;
1504 }
1505
1506 return -1;
1507}
1508
1509int
1510clearbpt(tcp)
1511struct tcb *tcp;
1512{
1513 arg_setup_state state;
1514 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001515 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1516 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001517 || arg_finish_change (tcp, &state))
1518 return -1;
1519 tcp->flags &= ~TCB_BPTSET;
1520 return 0;
1521}
1522
1523#else
1524
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525int
1526setbpt(tcp)
1527struct tcb *tcp;
1528{
1529
1530#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001531#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 /* We simply use the SunOS breakpoint code. */
1533
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001534 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001535 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536#define LOOPA 0x30800000 /* ba,a 0 */
1537
1538 if (tcp->flags & TCB_BPTSET) {
1539 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1540 return -1;
1541 }
1542 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1543 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1544 return -1;
1545 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001546 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 errno = 0;
1548 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1549 if(errno) {
1550 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1551 return -1;
1552 }
1553
1554 /*
1555 * XXX - BRUTAL MODE ON
1556 * We cannot set a real BPT in the child, since it will not be
1557 * traced at the moment it will reach the trap and would probably
1558 * die with a core dump.
1559 * Thus, we are force our way in by taking out two instructions
1560 * and insert an eternal loop instead, in expectance of the SIGSTOP
1561 * generated by out PTRACE_ATTACH.
1562 * Of cause, if we evaporate ourselves in the middle of all this...
1563 */
1564 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001565 inst = LOOPA;
1566#if defined (SPARC64)
1567 inst <<= 32;
1568 inst |= (tcp->inst[0] & 0xffffffffUL);
1569#endif
1570 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571 if(errno) {
1572 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1573 return -1;
1574 }
1575 tcp->flags |= TCB_BPTSET;
1576
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001577#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001578#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001579 if (ia32) {
1580# define LOOP 0x0000feeb
1581 if (tcp->flags & TCB_BPTSET) {
1582 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1583 tcp->pid);
1584 return -1;
1585 }
1586 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1587 return -1;
1588 if (debug)
1589 fprintf(stderr, "[%d] setting bpt at %lx\n",
1590 tcp->pid, tcp->baddr);
1591 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1592 (char *) tcp->baddr, 0);
1593 if (errno) {
1594 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1595 return -1;
1596 }
1597 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1598 if (errno) {
1599 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1600 return -1;
1601 }
1602 tcp->flags |= TCB_BPTSET;
1603 } else {
1604 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001605 * Our strategy here is to replace the bundle that
1606 * contained the clone() syscall with a bundle of the
1607 * form:
1608 *
1609 * { 1: br 1b; br 1b; br 1b }
1610 *
1611 * This ensures that the newly forked child will loop
1612 * endlessly until we've got a chance to attach to it.
1613 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001614# define LOOP0 0x0000100000000017
1615# define LOOP1 0x4000000000200000
1616 unsigned long addr, ipsr;
1617 pid_t pid;
1618
1619 pid = tcp->pid;
1620 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1621 return -1;
1622 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1623 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001624 /* store "ri" in low two bits */
1625 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001626
1627 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001628 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1629 0);
1630 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1631 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001632 if (errno) {
1633 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1634 return -1;
1635 }
1636
1637 errno = 0;
1638 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1639 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1640 if (errno) {
1641 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1642 return -1;
1643 }
1644 tcp->flags |= TCB_BPTSET;
1645 }
1646#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647
Michal Ludvig0e035502002-09-23 15:41:01 +00001648#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649#define LOOP 0x0000feeb
1650#elif defined (M68K)
1651#define LOOP 0x60fe0000
1652#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001653#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001655#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001657#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001658#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001659#define LOOP 0x1000ffff
1660#elif defined(S390)
1661#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001662#elif defined(S390X)
1663#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001664#elif defined(HPPA)
1665#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001666#elif defined(SH)
1667#ifdef __LITTLE_ENDIAN__
1668#define LOOP 0x0000affe
1669#else
1670#define LOOP 0xfeaf0000
1671#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672#else
1673#error unknown architecture
1674#endif
1675
1676 if (tcp->flags & TCB_BPTSET) {
1677 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1678 return -1;
1679 }
1680#if defined (I386)
1681 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1682 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001683#elif defined (X86_64)
1684 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1685 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686#elif defined (M68K)
1687 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1688 return -1;
1689#elif defined (ALPHA)
1690 return -1;
1691#elif defined (ARM)
1692 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001693#elif defined (MIPS)
1694 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001696 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001698#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001699 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1700 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001701#elif defined(HPPA)
1702 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1703 return -1;
1704 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001705#elif defined(SH)
1706 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1707 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708#else
1709#error unknown architecture
1710#endif
1711 if (debug)
1712 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1713 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1714 if (errno) {
1715 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1716 return -1;
1717 }
1718 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1719 if (errno) {
1720 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1721 return -1;
1722 }
1723 tcp->flags |= TCB_BPTSET;
1724
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001725#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001726#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727#endif /* LINUX */
1728
1729#ifdef SUNOS4
1730#ifdef SPARC /* This code is slightly sparc specific */
1731
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001732 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733#define BPT 0x91d02001 /* ta 1 */
1734#define LOOP 0x10800000 /* ba 0 */
1735#define LOOPA 0x30800000 /* ba,a 0 */
1736#define NOP 0x01000000
1737#if LOOPA
1738 static int loopdeloop[1] = {LOOPA};
1739#else
1740 static int loopdeloop[2] = {LOOP, NOP};
1741#endif
1742
1743 if (tcp->flags & TCB_BPTSET) {
1744 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1745 return -1;
1746 }
1747 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1748 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1749 return -1;
1750 }
1751 tcp->baddr = regs.r_o7 + 8;
1752 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1753 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1754 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1755 return -1;
1756 }
1757
1758 /*
1759 * XXX - BRUTAL MODE ON
1760 * We cannot set a real BPT in the child, since it will not be
1761 * traced at the moment it will reach the trap and would probably
1762 * die with a core dump.
1763 * Thus, we are force our way in by taking out two instructions
1764 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1765 * generated by out PTRACE_ATTACH.
1766 * Of cause, if we evaporate ourselves in the middle of all this...
1767 */
1768 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1769 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1770 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1771 return -1;
1772 }
1773 tcp->flags |= TCB_BPTSET;
1774
1775#endif /* SPARC */
1776#endif /* SUNOS4 */
1777
1778 return 0;
1779}
1780
1781int
1782clearbpt(tcp)
1783struct tcb *tcp;
1784{
1785
1786#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001787#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001789#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001791#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001793#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001795#elif defined(HPPA)
1796 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001797#elif defined(SH)
1798 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001799#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001801#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 /* Again, we borrow the SunOS breakpoint code. */
1803 if (!(tcp->flags & TCB_BPTSET)) {
1804 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1805 return -1;
1806 }
1807 errno = 0;
1808 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1809 if(errno) {
1810 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1811 return -1;
1812 }
1813 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001814#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001815 if (ia32) {
1816 unsigned long addr;
1817
1818 if (debug)
1819 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1820 if (!(tcp->flags & TCB_BPTSET)) {
1821 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1822 return -1;
1823 }
1824 errno = 0;
1825 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1826 if (errno) {
1827 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1828 return -1;
1829 }
1830 tcp->flags &= ~TCB_BPTSET;
1831
1832 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1833 return -1;
1834 if (addr != tcp->baddr) {
1835 /* The breakpoint has not been reached yet. */
1836 if (debug)
1837 fprintf(stderr,
1838 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1839 addr, tcp->baddr);
1840 return 0;
1841 }
1842 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001843 unsigned long addr, ipsr;
1844 pid_t pid;
1845
1846 pid = tcp->pid;
1847
1848 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1849 return -1;
1850 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1851 return -1;
1852
1853 /* restore original bundle: */
1854 errno = 0;
1855 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1856 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1857 if (errno) {
1858 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1859 return -1;
1860 }
1861
1862 /* restore original "ri" in ipsr: */
1863 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1864 errno = 0;
1865 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1866 if (errno) {
1867 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1868 return -1;
1869 }
1870
1871 tcp->flags &= ~TCB_BPTSET;
1872
1873 if (addr != (tcp->baddr & ~0x3)) {
1874 /* the breakpoint has not been reached yet. */
1875 if (debug)
1876 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1877 addr, tcp->baddr);
1878 return 0;
1879 }
1880 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001881#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882
1883 if (debug)
1884 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1885 if (!(tcp->flags & TCB_BPTSET)) {
1886 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1887 return -1;
1888 }
1889 errno = 0;
1890 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1891 if (errno) {
1892 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1893 return -1;
1894 }
1895 tcp->flags &= ~TCB_BPTSET;
1896
1897#ifdef I386
1898 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1899 return -1;
1900 if (eip != tcp->baddr) {
1901 /* The breakpoint has not been reached yet. */
1902 if (debug)
1903 fprintf(stderr,
1904 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1905 eip, tcp->baddr);
1906 return 0;
1907 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001908#elif defined(X86_64)
1909 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1910 return -1;
1911 if (eip != tcp->baddr) {
1912 /* The breakpoint has not been reached yet. */
1913 if (debug)
1914 fprintf(stderr,
1915 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1916 eip, tcp->baddr);
1917 return 0;
1918 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001919#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001920 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 return -1;
1922 if (pc != tcp->baddr) {
1923 /* The breakpoint has not been reached yet. */
1924 if (debug)
1925 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1926 pc, tcp->baddr);
1927 return 0;
1928 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001929#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1931 return -1;
1932 if (pc != tcp->baddr) {
1933 /* The breakpoint has not been reached yet. */
1934 if (debug)
1935 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1936 pc, tcp->baddr);
1937 return 0;
1938 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001939#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1941 return -1;
1942 if (pc != tcp->baddr) {
1943 /* The breakpoint has not been reached yet. */
1944 if (debug)
1945 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1946 pc, tcp->baddr);
1947 return 0;
1948 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001949#elif defined(HPPA)
1950 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1951 return -1;
1952 iaoq &= ~0x03;
1953 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1954 /* The breakpoint has not been reached yet. */
1955 if (debug)
1956 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1957 iaoq, tcp->baddr);
1958 return 0;
1959 }
1960 iaoq = tcp->baddr | 3;
1961 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1962 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1963 * has no significant effect.
1964 */
1965 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1966 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001967#elif defined(SH)
1968 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1969 return -1;
1970 if (pc != tcp->baddr) {
1971 /* The breakpoint has not been reached yet. */
1972 if (debug)
1973 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1974 pc, tcp->baddr);
1975 return 0;
1976 }
1977
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001978#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001979#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980#endif /* LINUX */
1981
1982#ifdef SUNOS4
1983#ifdef SPARC
1984
1985#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001986 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001987#endif
1988
1989 if (!(tcp->flags & TCB_BPTSET)) {
1990 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1991 return -1;
1992 }
1993 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1994 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1995 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1996 return -1;
1997 }
1998 tcp->flags &= ~TCB_BPTSET;
1999
2000#if !LOOPA
2001 /*
2002 * Since we don't have a single instruction breakpoint, we may have
2003 * to adjust the program counter after removing the our `breakpoint'.
2004 */
2005 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2006 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2007 return -1;
2008 }
2009 if ((regs.r_pc < tcp->baddr) ||
2010 (regs.r_pc > tcp->baddr + 4)) {
2011 /* The breakpoint has not been reached yet */
2012 if (debug)
2013 fprintf(stderr,
2014 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2015 regs.r_pc, tcp->parent->baddr);
2016 return 0;
2017 }
2018 if (regs.r_pc != tcp->baddr)
2019 if (debug)
2020 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2021 regs.r_pc, tcp->baddr);
2022
2023 regs.r_pc = tcp->baddr;
2024 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2025 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2026 return -1;
2027 }
2028#endif /* LOOPA */
2029#endif /* SPARC */
2030#endif /* SUNOS4 */
2031
2032 return 0;
2033}
2034
Roland McGrathd81f1d92003-01-09 06:53:34 +00002035#endif
2036
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002037#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038
2039#ifdef SUNOS4
2040
2041static int
2042getex(pid, hdr)
2043int pid;
2044struct exec *hdr;
2045{
2046 int n;
2047
2048 for (n = 0; n < sizeof *hdr; n += 4) {
2049 long res;
2050 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2051 return -1;
2052 memcpy(((char *) hdr) + n, &res, 4);
2053 }
2054 if (debug) {
2055 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2056 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2057 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2058 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2059 }
2060 return 0;
2061}
2062
2063int
2064fixvfork(tcp)
2065struct tcb *tcp;
2066{
2067 int pid = tcp->pid;
2068 /*
2069 * Change `vfork' in a freshly exec'ed dynamically linked
2070 * executable's (internal) symbol table to plain old `fork'
2071 */
2072
2073 struct exec hdr;
2074 struct link_dynamic dyn;
2075 struct link_dynamic_2 ld;
2076 char *strtab, *cp;
2077
2078 if (getex(pid, &hdr) < 0)
2079 return -1;
2080 if (!hdr.a_dynamic)
2081 return -1;
2082
2083 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2084 fprintf(stderr, "Cannot read DYNAMIC\n");
2085 return -1;
2086 }
2087 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2088 fprintf(stderr, "Cannot read link_dynamic_2\n");
2089 return -1;
2090 }
2091 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002092 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093 return -1;
2094 }
2095 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2096 (int)ld.ld_symb_size, strtab) < 0)
2097 goto err;
2098
2099#if 0
2100 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2101 fprintf(stderr, "[symbol: %s]\n", cp);
2102 cp += strlen(cp)+1;
2103 }
2104 return 0;
2105#endif
2106 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2107 if (strcmp(cp, "_vfork") == 0) {
2108 if (debug)
2109 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2110 strcpy(cp, "_fork");
2111 break;
2112 }
2113 cp += strlen(cp)+1;
2114 }
2115 if (cp < strtab + ld.ld_symb_size)
2116 /*
2117 * Write entire symbol table back to avoid
2118 * memory alignment bugs in ptrace
2119 */
2120 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2121 (int)ld.ld_symb_size, strtab) < 0)
2122 goto err;
2123
2124 free(strtab);
2125 return 0;
2126
2127err:
2128 free(strtab);
2129 return -1;
2130}
2131
2132#endif /* SUNOS4 */