blob: 7b52df4a9a76e9efee6674a14a2cae73356e1ce7 [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
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000380string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000382 const unsigned char *ustr = (const unsigned char *) instr;
383 char *s = outstr;
384 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000386 if (xflag > 1)
387 usehex = 1;
388 else if (xflag) {
389 for (i = 0; i < size; ++i) {
390 c = ustr[i];
391 if (len < 0 && c == '\0')
392 break;
393 if (!isprint(c) && !isspace(c)) {
394 usehex = 1;
395 break;
396 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 }
398 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000399
400 *s++ = '\"';
401
402 if (usehex) {
403 for (i = 0; i < size; ++i) {
404 c = ustr[i];
405 if (len < 0 && c == '\0')
406 break;
407 sprintf(s, "\\x%02x", c);
408 s += 4;
409 }
410 } else {
411 for (i = 0; i < size; ++i) {
412 c = ustr[i];
413 if (len < 0 && c == '\0')
414 break;
415 switch (c) {
416 case '\"': case '\\':
417 *s++ = '\\';
418 *s++ = c;
419 break;
420 case '\f':
421 *s++ = '\\';
422 *s++ = 'f';
423 break;
424 case '\n':
425 *s++ = '\\';
426 *s++ = 'n';
427 break;
428 case '\r':
429 *s++ = '\\';
430 *s++ = 'r';
431 break;
432 case '\t':
433 *s++ = '\\';
434 *s++ = 't';
435 break;
436 case '\v':
437 *s++ = '\\';
438 *s++ = 'v';
439 break;
440 default:
441 if (isprint(c))
442 *s++ = c;
443 else if (i + 1 < size
444 && isdigit(ustr[i + 1])) {
445 sprintf(s, "\\%03o", c);
446 s += 4;
447 } else {
448 sprintf(s, "\\%o", c);
449 s += strlen(s);
450 }
451 break;
452 }
453 }
454 }
455
456 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457 *s = '\0';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000458}
459
460void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000461printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000463 if (n > sizeof path - 1)
Roland McGrathb15c4e42005-10-21 22:06:46 +0000464 n = sizeof path - 1;
465
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000466 if (addr == 0) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000467 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000468 return;
469 }
470
471 path[n] = '\0';
472 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473 tprintf("%#lx", addr);
474 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000475 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
476 int trunc = (path[n] != '\0');
477
478 if (trunc)
479 path[n] = '\0';
480 string_quote(path, outstr, -1, n);
481 if (trunc)
482 strcat(outstr, "...");
483 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 }
485}
486
487void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000488printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000490 printpathn(tcp, addr, sizeof path - 1);
491}
492
493void
494printstr(struct tcb *tcp, long addr, int len)
495{
496 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 static char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000498 int size, trunc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499
500 if (!addr) {
501 tprintf("NULL");
502 return;
503 }
504 if (!str) {
Roland McGratha503dcf2007-08-02 02:06:26 +0000505 if ((str = malloc(max_strlen + 1)) == NULL
Roland McGrath779c4662007-07-11 07:23:40 +0000506 || (outstr = malloc(4*max_strlen
507 + sizeof "\"\"...")) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000508 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509 tprintf("%#lx", addr);
510 return;
511 }
512 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 if (len < 0) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000515 size = max_strlen + 1;
516 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517 tprintf("%#lx", addr);
518 return;
519 }
520 }
521 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000522 size = MIN(len, max_strlen + 1);
523 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524 tprintf("%#lx", addr);
525 return;
526 }
527 }
528
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000529 trunc = size > max_strlen && str[--size] != 0;
530 string_quote(str, outstr, len, size);
531 if (size < len || (len < 0 && trunc))
532 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000533
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 tprintf("%s", outstr);
535}
536
John Hughes1d08dcf2001-07-10 13:48:44 +0000537#if HAVE_SYS_UIO_H
538void
539dumpiov(tcp, len, addr)
540struct tcb * tcp;
541int len;
542long addr;
543{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000544#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
545 union {
546 struct { u_int32_t base; u_int32_t len; } *iov32;
547 struct { u_int64_t base; u_int64_t len; } *iov64;
548 } iovu;
549#define iov iovu.iov64
550#define sizeof_iov \
551 (personality_wordsize[current_personality] == 4 \
552 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
553#define iov_iov_base(i) \
554 (personality_wordsize[current_personality] == 4 \
555 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
556#define iov_iov_len(i) \
557 (personality_wordsize[current_personality] == 4 \
558 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
559#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000560 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000561#define sizeof_iov sizeof(*iov)
562#define iov_iov_base(i) iov[i].iov_base
563#define iov_iov_len(i) iov[i].iov_len
564#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000565 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000566 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000567
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000568 size = sizeof_iov * (unsigned long) len;
569 if (size / sizeof_iov != len
570 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000571 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000572 return;
573 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000574 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000575 for (i = 0; i < len; i++) {
576 /* include the buffer number to make it easy to
577 * match up the trace with the source */
578 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000579 (unsigned long)iov_iov_len(i), i);
580 dumpstr(tcp, (long) iov_iov_base(i),
581 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000582 }
583 }
584 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000585#undef sizeof_iov
586#undef iov_iov_base
587#undef iov_iov_len
588#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000589}
590#endif
591
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592void
593dumpstr(tcp, addr, len)
594struct tcb *tcp;
595long addr;
596int len;
597{
598 static int strsize = -1;
599 static unsigned char *str;
600 static char outstr[80];
601 char *s;
602 int i, j;
603
604 if (strsize < len) {
605 if (str)
606 free(str);
607 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000608 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000609 return;
610 }
611 strsize = len;
612 }
613
614 if (umoven(tcp, addr, len, (char *) str) < 0)
615 return;
616
617 for (i = 0; i < len; i += 16) {
618 s = outstr;
619 sprintf(s, " | %05x ", i);
620 s += 9;
621 for (j = 0; j < 16; j++) {
622 if (j == 8)
623 *s++ = ' ';
624 if (i + j < len) {
625 sprintf(s, " %02x", str[i + j]);
626 s += 3;
627 }
628 else {
629 *s++ = ' '; *s++ = ' '; *s++ = ' ';
630 }
631 }
632 *s++ = ' '; *s++ = ' ';
633 for (j = 0; j < 16; j++) {
634 if (j == 8)
635 *s++ = ' ';
636 if (i + j < len) {
637 if (isprint(str[i + j]))
638 *s++ = str[i + j];
639 else
640 *s++ = '.';
641 }
642 else
643 *s++ = ' ';
644 }
645 tprintf("%s |\n", outstr);
646 }
647}
648
649#define PAGMASK (~(PAGSIZ - 1))
650/*
651 * move `len' bytes of data from process `pid'
652 * at address `addr' to our space at `laddr'
653 */
654int
655umoven(tcp, addr, len, laddr)
656struct tcb *tcp;
657long addr;
658int len;
659char *laddr;
660{
661
662#ifdef LINUX
663 int pid = tcp->pid;
664 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000665 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 union {
667 long val;
668 char x[sizeof(long)];
669 } u;
670
671 if (addr & (sizeof(long) - 1)) {
672 /* addr not a multiple of sizeof(long) */
673 n = addr - (addr & -sizeof(long)); /* residue */
674 addr &= -sizeof(long); /* residue */
675 errno = 0;
676 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
677 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000678 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 /* Ran into 'end of memory' - stupid "printpath" */
680 return 0;
681 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000682 /* But if not started, we had a bogus address. */
Roland McGrath1c459762007-08-02 02:22:06 +0000683 if (addr != 0 && errno != EIO)
684 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685 return -1;
686 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000687 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
689 addr += sizeof(long), laddr += m, len -= m;
690 }
691 while (len) {
692 errno = 0;
693 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
694 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000695 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696 /* Ran into 'end of memory' - stupid "printpath" */
697 return 0;
698 }
Roland McGrath1c459762007-08-02 02:22:06 +0000699 if (addr != 0 && errno != EIO)
Roland McGrath4db26242003-01-30 20:15:19 +0000700 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701 return -1;
702 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000703 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000704 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
705 addr += sizeof(long), laddr += m, len -= m;
706 }
707#endif /* LINUX */
708
709#ifdef SUNOS4
710 int pid = tcp->pid;
711#if 0
712 int n, m;
713 union {
714 long val;
715 char x[sizeof(long)];
716 } u;
717
718 if (addr & (sizeof(long) - 1)) {
719 /* addr not a multiple of sizeof(long) */
720 n = addr - (addr & -sizeof(long)); /* residue */
721 addr &= -sizeof(long); /* residue */
722 errno = 0;
723 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
724 if (errno) {
725 perror("umoven");
726 return -1;
727 }
728 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
729 addr += sizeof(long), laddr += m, len -= m;
730 }
731 while (len) {
732 errno = 0;
733 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
734 if (errno) {
735 perror("umoven");
736 return -1;
737 }
738 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
739 addr += sizeof(long), laddr += m, len -= m;
740 }
741#else /* !oldway */
742 int n;
743
744 while (len) {
745 n = MIN(len, PAGSIZ);
746 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
747 if (ptrace(PTRACE_READDATA, pid,
748 (char *) addr, len, laddr) < 0) {
749 perror("umoven: ptrace(PTRACE_READDATA, ...)");
750 abort();
751 return -1;
752 }
753 len -= n;
754 addr += n;
755 laddr += n;
756 }
757#endif /* !oldway */
758#endif /* SUNOS4 */
759
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000760#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000761#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000762 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000763#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000764 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000766 lseek(fd, addr, SEEK_SET);
767 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000769#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000770
771 return 0;
772}
773
774/*
775 * like `umove' but make the additional effort of looking
776 * for a terminating zero byte.
777 */
778int
779umovestr(tcp, addr, len, laddr)
780struct tcb *tcp;
781long addr;
782int len;
783char *laddr;
784{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000785#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000786#ifdef HAVE_MP_PROCFS
787 int fd = tcp->pfd_as;
788#else
789 int fd = tcp->pfd;
790#endif
791 /* Some systems (e.g. FreeBSD) can be upset if we read off the
792 end of valid memory, avoid this by trying to read up
793 to page boundaries. But we don't know what a page is (and
794 getpagesize(2) (if it exists) doesn't necessarily return
795 hardware page size). Assume all pages >= 1024 (a-historical
796 I know) */
797
798 int page = 1024; /* How to find this? */
799 int move = page - (addr & (page - 1));
800 int left = len;
801
802 lseek(fd, addr, SEEK_SET);
803
804 while (left) {
805 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000806 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000807 return left != len ? 0 : -1;
808 if (memchr (laddr, 0, move)) break;
809 left -= move;
810 laddr += move;
811 addr += move;
812 move = page;
813 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000814#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000815 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 int pid = tcp->pid;
817 int i, n, m;
818 union {
819 long val;
820 char x[sizeof(long)];
821 } u;
822
823 if (addr & (sizeof(long) - 1)) {
824 /* addr not a multiple of sizeof(long) */
825 n = addr - (addr & -sizeof(long)); /* residue */
826 addr &= -sizeof(long); /* residue */
827 errno = 0;
828 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
829 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000830 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831 /* Ran into 'end of memory' - stupid "printpath" */
832 return 0;
833 }
Roland McGrath1c459762007-08-02 02:22:06 +0000834 if (addr != 0 && errno != EIO)
835 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836 return -1;
837 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000838 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
840 while (n & (sizeof(long) - 1))
841 if (u.x[n++] == '\0')
842 return 0;
843 addr += sizeof(long), laddr += m, len -= m;
844 }
845 while (len) {
846 errno = 0;
847 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
848 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000849 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 /* Ran into 'end of memory' - stupid "printpath" */
851 return 0;
852 }
Roland McGrath1c459762007-08-02 02:22:06 +0000853 if (addr != 0 && errno != EIO)
854 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000855 return -1;
856 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000857 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
859 for (i = 0; i < sizeof(long); i++)
860 if (u.x[i] == '\0')
861 return 0;
862
863 addr += sizeof(long), laddr += m, len -= m;
864 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000865#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000866 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867}
868
869#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000870#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871#define PTRACE_WRITETEXT 101
872#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000873#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000874#endif /* LINUX */
875
876#ifdef SUNOS4
877
878static int
879uload(cmd, pid, addr, len, laddr)
880int cmd;
881int pid;
882long addr;
883int len;
884char *laddr;
885{
886#if 0
887 int n;
888
889 while (len) {
890 n = MIN(len, PAGSIZ);
891 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
892 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
893 perror("uload: ptrace(PTRACE_WRITE, ...)");
894 return -1;
895 }
896 len -= n;
897 addr += n;
898 laddr += n;
899 }
900#else
901 int peek, poke;
902 int n, m;
903 union {
904 long val;
905 char x[sizeof(long)];
906 } u;
907
908 if (cmd == PTRACE_WRITETEXT) {
909 peek = PTRACE_PEEKTEXT;
910 poke = PTRACE_POKETEXT;
911 }
912 else {
913 peek = PTRACE_PEEKDATA;
914 poke = PTRACE_POKEDATA;
915 }
916 if (addr & (sizeof(long) - 1)) {
917 /* addr not a multiple of sizeof(long) */
918 n = addr - (addr & -sizeof(long)); /* residue */
919 addr &= -sizeof(long);
920 errno = 0;
921 u.val = ptrace(peek, pid, (char *) addr, 0);
922 if (errno) {
923 perror("uload: POKE");
924 return -1;
925 }
926 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
927 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
928 perror("uload: POKE");
929 return -1;
930 }
931 addr += sizeof(long), laddr += m, len -= m;
932 }
933 while (len) {
934 if (len < sizeof(long))
935 u.val = ptrace(peek, pid, (char *) addr, 0);
936 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
937 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
938 perror("uload: POKE");
939 return -1;
940 }
941 addr += sizeof(long), laddr += m, len -= m;
942 }
943#endif
944 return 0;
945}
946
947int
948tload(pid, addr, len, laddr)
949int pid;
950int addr, len;
951char *laddr;
952{
953 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
954}
955
956int
957dload(pid, addr, len, laddr)
958int pid;
959int addr;
960int len;
961char *laddr;
962{
963 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
964}
965
966#endif /* SUNOS4 */
967
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000968#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969
970int
971upeek(pid, off, res)
972int pid;
973long off;
974long *res;
975{
976 long val;
977
978#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
979 {
980 static int is_sun4m = -1;
981 struct utsname name;
982
983 /* Round up the usual suspects. */
984 if (is_sun4m == -1) {
985 if (uname(&name) < 0) {
986 perror("upeek: uname?");
987 exit(1);
988 }
989 is_sun4m = strcmp(name.machine, "sun4m") == 0;
990 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000991 extern const struct xlat struct_user_offsets[];
992 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993
994 for (x = struct_user_offsets; x->str; x++)
995 x->val += 1024;
996 }
997 }
998 if (is_sun4m)
999 off += 1024;
1000 }
1001#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1002 errno = 0;
1003 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1004 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001005 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001006 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001007 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 return -1;
1009 }
1010 *res = val;
1011 return 0;
1012}
1013
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001014#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015
Roland McGratha4d48532005-06-08 20:45:28 +00001016#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017long
1018getpc(tcp)
1019struct tcb *tcp;
1020{
1021
1022#ifdef LINUX
1023 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001024#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1026 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001027#elif defined(X86_64)
1028 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1029 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001030#elif defined(IA64)
1031 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1032 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001033#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 if (upeek(tcp->pid, 4*15, &pc) < 0)
1035 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001036#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001037 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001039#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1041 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001042#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1044 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001045#elif defined(MIPS)
1046 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1047 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001048#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001049 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1051 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001052 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001053#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001054 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001055 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001056#elif defined(HPPA)
1057 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1058 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001059#elif defined(SH)
1060 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1061 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001062#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001063 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1064 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001065#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 return pc;
1067#endif /* LINUX */
1068
1069#ifdef SUNOS4
1070 /*
1071 * Return current program counter for `pid'
1072 * Assumes PC is never 0xffffffff
1073 */
1074 struct regs regs;
1075
1076 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1077 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1078 return -1;
1079 }
1080 return regs.r_pc;
1081#endif /* SUNOS4 */
1082
1083#ifdef SVR4
1084 /* XXX */
1085 return 0;
1086#endif /* SVR4 */
1087
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001088#ifdef FREEBSD
1089 struct reg regs;
1090 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1091 return regs.r_eip;
1092#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093}
Roland McGratha4d48532005-06-08 20:45:28 +00001094#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095
1096void
1097printcall(tcp)
1098struct tcb *tcp;
1099{
Roland McGrath7a918832005-02-02 20:55:23 +00001100#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1101 sizeof(long) == 8 ? "[????????????????] " : \
1102 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103
1104#ifdef LINUX
1105#ifdef I386
1106 long eip;
1107
1108 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001109 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 return;
1111 }
1112 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001113
1114#elif defined(S390) || defined(S390X)
1115 long psw;
1116 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001117 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001118 return;
1119 }
1120#ifdef S390
1121 tprintf("[%08lx] ", psw);
1122#elif S390X
1123 tprintf("[%16lx] ", psw);
1124#endif
1125
Michal Ludvig0e035502002-09-23 15:41:01 +00001126#elif defined(X86_64)
1127 long rip;
1128
1129 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001130 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001131 return;
1132 }
1133 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001134#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001135 long ip;
1136
1137 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001138 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001139 return;
1140 }
1141 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001142#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 long pc;
1144
Roland McGratheb285352003-01-14 09:59:00 +00001145 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 tprintf ("[????????] ");
1147 return;
1148 }
1149 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001150#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 long pc;
1152
1153 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1154 tprintf ("[????????] ");
1155 return;
1156 }
1157 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001158#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 long pc;
1160
1161 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001162 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 return;
1164 }
1165 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001166#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001167 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001169 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 return;
1171 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001172 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001173#elif defined(HPPA)
1174 long pc;
1175
1176 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1177 tprintf ("[????????] ");
1178 return;
1179 }
1180 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001181#elif defined(MIPS)
1182 long pc;
1183
1184 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1185 tprintf ("[????????] ");
1186 return;
1187 }
1188 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001189#elif defined(SH)
1190 long pc;
1191
1192 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1193 tprintf ("[????????] ");
1194 return;
1195 }
1196 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001197#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001198 long pc;
1199
1200 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001201 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001202 return;
1203 }
1204 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001205#elif defined(ARM)
1206 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001207
Roland McGrathef388682003-06-03 23:28:59 +00001208 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001209 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001210 return;
1211 }
1212 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001213#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214#endif /* LINUX */
1215
1216#ifdef SUNOS4
1217 struct regs regs;
1218
1219 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1220 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001221 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 return;
1223 }
1224 tprintf("[%08x] ", regs.r_o7);
1225#endif /* SUNOS4 */
1226
1227#ifdef SVR4
1228 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001229 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230#endif
1231
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001232#ifdef FREEBSD
1233 struct reg regs;
1234 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1235 tprintf("[%08x] ", regs.r_eip);
1236#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237}
1238
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001239#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240
Roland McGrathd81f1d92003-01-09 06:53:34 +00001241#if defined LINUX
1242
1243#include <sys/syscall.h>
1244#ifndef CLONE_PTRACE
1245# define CLONE_PTRACE 0x00002000
1246#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001247#ifndef CLONE_STOPPED
1248# define CLONE_STOPPED 0x02000000
1249#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001250
1251#ifdef IA64
1252
Roland McGrath08267b82004-02-20 22:56:43 +00001253/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1254 subsystem has them for x86... */
1255#define SYS_fork 2
1256#define SYS_vfork 190
1257
Roland McGrathd81f1d92003-01-09 06:53:34 +00001258typedef unsigned long *arg_setup_state;
1259
1260static int
1261arg_setup(struct tcb *tcp, arg_setup_state *state)
1262{
1263 unsigned long *bsp, cfm, sof, sol;
1264
Roland McGrath08267b82004-02-20 22:56:43 +00001265 if (ia32)
1266 return 0;
1267
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1269 return -1;
1270 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1271 return -1;
1272
1273 sof = (cfm >> 0) & 0x7f;
1274 sol = (cfm >> 7) & 0x7f;
1275 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1276
1277 *state = bsp;
1278 return 0;
1279}
1280
1281# define arg_finish_change(tcp, state) 0
1282
1283#ifdef SYS_fork
1284static int
1285get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1286{
Roland McGrath08267b82004-02-20 22:56:43 +00001287 int ret;
1288
1289 if (ia32)
1290 ret = upeek (tcp->pid, PT_R11, valp);
1291 else
1292 ret = umoven (tcp,
1293 (unsigned long) ia64_rse_skip_regs(*state, 0),
1294 sizeof(long), (void *) valp);
1295 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296}
1297
1298static int
1299get_arg1 (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_R9, valp);
1305 else
1306 ret = umoven (tcp,
1307 (unsigned long) ia64_rse_skip_regs(*state, 1),
1308 sizeof(long), (void *) valp);
1309 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310}
1311#endif
1312
1313static int
1314set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1315{
Roland McGrath08267b82004-02-20 22:56:43 +00001316 int req = PTRACE_POKEDATA;
1317 void *ap;
1318
1319 if (ia32) {
1320 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1321 req = PTRACE_POKEUSER;
1322 } else
1323 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001325 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001326 return errno ? -1 : 0;
1327}
1328
1329static int
1330set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1331{
Roland McGrath08267b82004-02-20 22:56:43 +00001332 int req = PTRACE_POKEDATA;
1333 void *ap;
1334
1335 if (ia32) {
1336 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1337 req = PTRACE_POKEUSER;
1338 } else
1339 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001341 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342 return errno ? -1 : 0;
1343}
1344
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001345#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001346
1347typedef struct regs arg_setup_state;
1348
1349# define arg_setup(tcp, state) \
1350 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1351# define arg_finish_change(tcp, state) \
1352 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1353
1354# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1355# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1356# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1357# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001358# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001359
1360#else
1361
1362# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001363/* Note: this is only true for the `clone' system call, which handles
1364 arguments specially. We could as well say that its first two arguments
1365 are swapped relative to other architectures, but that would just be
1366 another #ifdef in the calls. */
1367# define arg0_offset PT_GPR3
1368# define arg1_offset PT_ORIGGPR2
1369# define restore_arg0(tcp, state, val) ((void) (state), 0)
1370# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001371# define arg0_index 1
1372# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001373# elif defined (ALPHA) || defined (MIPS)
1374# define arg0_offset REG_A0
1375# define arg1_offset (REG_A0+1)
1376# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001377# define arg0_offset (sizeof(unsigned long)*PT_R3)
1378# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001379# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380# elif defined (HPPA)
1381# define arg0_offset PT_GR26
1382# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001383# elif defined (X86_64)
1384# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1385# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001386# elif defined (SH)
1387# define arg0_offset (4*(REG_REG0+4))
1388# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001389# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001390 /* ABI defines arg0 & 1 in r2 & r3 */
1391# define arg0_offset (REG_OFFSET+16)
1392# define arg1_offset (REG_OFFSET+24)
1393# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001394# else
1395# define arg0_offset 0
1396# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001397# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001398# define restore_arg0(tcp, state, val) 0
1399# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001400# endif
1401
1402typedef int arg_setup_state;
1403
1404# define arg_setup(tcp, state) (0)
1405# define arg_finish_change(tcp, state) 0
1406# define get_arg0(tcp, cookie, valp) \
1407 (upeek ((tcp)->pid, arg0_offset, (valp)))
1408# define get_arg1(tcp, cookie, valp) \
1409 (upeek ((tcp)->pid, arg1_offset, (valp)))
1410
1411static int
1412set_arg0 (struct tcb *tcp, void *cookie, long val)
1413{
Roland McGrathca85b972005-06-07 23:22:08 +00001414 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001415}
1416
1417static int
1418set_arg1 (struct tcb *tcp, void *cookie, long val)
1419{
1420 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1421}
1422
1423#endif
1424
Roland McGrathe1df47f2003-01-14 09:46:15 +00001425#ifndef restore_arg0
1426# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1427#endif
1428#ifndef restore_arg1
1429# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1430#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001431
Roland McGrath90d0afd2004-03-01 21:05:16 +00001432#ifndef arg0_index
1433# define arg0_index 0
1434# define arg1_index 1
1435#endif
1436
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437int
1438setbpt(tcp)
1439struct tcb *tcp;
1440{
1441 extern int change_syscall(struct tcb *, int);
1442 arg_setup_state state;
1443
1444 if (tcp->flags & TCB_BPTSET) {
1445 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1446 return -1;
1447 }
1448
Roland McGrath76989d72005-06-07 23:21:31 +00001449 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001450#ifdef SYS_vfork
1451 case SYS_vfork:
1452#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453#ifdef SYS_fork
1454 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001455#endif
1456#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001457 if (arg_setup (tcp, &state) < 0
1458 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1459 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1460 || change_syscall(tcp, SYS_clone) < 0
1461 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1462 || set_arg1 (tcp, &state, 0) < 0
1463 || arg_finish_change (tcp, &state) < 0)
1464 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001465 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1466 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001467 tcp->flags |= TCB_BPTSET;
1468 return 0;
1469#endif
1470
1471 case SYS_clone:
1472#ifdef SYS_clone2
1473 case SYS_clone2:
1474#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001475 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001476 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001477 || set_arg0 (tcp, &state,
1478 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479 || arg_finish_change (tcp, &state) < 0))
1480 return -1;
1481 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001482 tcp->inst[0] = tcp->u_arg[arg0_index];
1483 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484 return 0;
1485
1486 default:
1487 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1488 tcp->scno, tcp->pid);
1489 break;
1490 }
1491
1492 return -1;
1493}
1494
1495int
1496clearbpt(tcp)
1497struct tcb *tcp;
1498{
1499 arg_setup_state state;
1500 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001501 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1502 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001503 || arg_finish_change (tcp, &state))
1504 return -1;
1505 tcp->flags &= ~TCB_BPTSET;
1506 return 0;
1507}
1508
1509#else
1510
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511int
1512setbpt(tcp)
1513struct tcb *tcp;
1514{
1515
1516#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001517#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 /* We simply use the SunOS breakpoint code. */
1519
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001520 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001521 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522#define LOOPA 0x30800000 /* ba,a 0 */
1523
1524 if (tcp->flags & TCB_BPTSET) {
1525 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1526 return -1;
1527 }
1528 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1529 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1530 return -1;
1531 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001532 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 errno = 0;
1534 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1535 if(errno) {
1536 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1537 return -1;
1538 }
1539
1540 /*
1541 * XXX - BRUTAL MODE ON
1542 * We cannot set a real BPT in the child, since it will not be
1543 * traced at the moment it will reach the trap and would probably
1544 * die with a core dump.
1545 * Thus, we are force our way in by taking out two instructions
1546 * and insert an eternal loop instead, in expectance of the SIGSTOP
1547 * generated by out PTRACE_ATTACH.
1548 * Of cause, if we evaporate ourselves in the middle of all this...
1549 */
1550 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001551 inst = LOOPA;
1552#if defined (SPARC64)
1553 inst <<= 32;
1554 inst |= (tcp->inst[0] & 0xffffffffUL);
1555#endif
1556 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557 if(errno) {
1558 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1559 return -1;
1560 }
1561 tcp->flags |= TCB_BPTSET;
1562
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001563#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001564#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001565 if (ia32) {
1566# define LOOP 0x0000feeb
1567 if (tcp->flags & TCB_BPTSET) {
1568 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1569 tcp->pid);
1570 return -1;
1571 }
1572 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1573 return -1;
1574 if (debug)
1575 fprintf(stderr, "[%d] setting bpt at %lx\n",
1576 tcp->pid, tcp->baddr);
1577 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1578 (char *) tcp->baddr, 0);
1579 if (errno) {
1580 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1581 return -1;
1582 }
1583 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1584 if (errno) {
1585 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1586 return -1;
1587 }
1588 tcp->flags |= TCB_BPTSET;
1589 } else {
1590 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001591 * Our strategy here is to replace the bundle that
1592 * contained the clone() syscall with a bundle of the
1593 * form:
1594 *
1595 * { 1: br 1b; br 1b; br 1b }
1596 *
1597 * This ensures that the newly forked child will loop
1598 * endlessly until we've got a chance to attach to it.
1599 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001600# define LOOP0 0x0000100000000017
1601# define LOOP1 0x4000000000200000
1602 unsigned long addr, ipsr;
1603 pid_t pid;
1604
1605 pid = tcp->pid;
1606 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1607 return -1;
1608 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1609 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001610 /* store "ri" in low two bits */
1611 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001612
1613 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001614 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1615 0);
1616 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1617 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001618 if (errno) {
1619 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1620 return -1;
1621 }
1622
1623 errno = 0;
1624 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1625 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1626 if (errno) {
1627 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1628 return -1;
1629 }
1630 tcp->flags |= TCB_BPTSET;
1631 }
1632#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633
Michal Ludvig0e035502002-09-23 15:41:01 +00001634#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635#define LOOP 0x0000feeb
1636#elif defined (M68K)
1637#define LOOP 0x60fe0000
1638#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001639#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001641#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001643#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001644#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001645#define LOOP 0x1000ffff
1646#elif defined(S390)
1647#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001648#elif defined(S390X)
1649#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001650#elif defined(HPPA)
1651#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001652#elif defined(SH)
1653#ifdef __LITTLE_ENDIAN__
1654#define LOOP 0x0000affe
1655#else
1656#define LOOP 0xfeaf0000
1657#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658#else
1659#error unknown architecture
1660#endif
1661
1662 if (tcp->flags & TCB_BPTSET) {
1663 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1664 return -1;
1665 }
1666#if defined (I386)
1667 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1668 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001669#elif defined (X86_64)
1670 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1671 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672#elif defined (M68K)
1673 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1674 return -1;
1675#elif defined (ALPHA)
1676 return -1;
1677#elif defined (ARM)
1678 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001679#elif defined (MIPS)
1680 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001682 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001684#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001685 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1686 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001687#elif defined(HPPA)
1688 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1689 return -1;
1690 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001691#elif defined(SH)
1692 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1693 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694#else
1695#error unknown architecture
1696#endif
1697 if (debug)
1698 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1699 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1700 if (errno) {
1701 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1702 return -1;
1703 }
1704 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1705 if (errno) {
1706 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1707 return -1;
1708 }
1709 tcp->flags |= TCB_BPTSET;
1710
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001711#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001712#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713#endif /* LINUX */
1714
1715#ifdef SUNOS4
1716#ifdef SPARC /* This code is slightly sparc specific */
1717
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001718 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719#define BPT 0x91d02001 /* ta 1 */
1720#define LOOP 0x10800000 /* ba 0 */
1721#define LOOPA 0x30800000 /* ba,a 0 */
1722#define NOP 0x01000000
1723#if LOOPA
1724 static int loopdeloop[1] = {LOOPA};
1725#else
1726 static int loopdeloop[2] = {LOOP, NOP};
1727#endif
1728
1729 if (tcp->flags & TCB_BPTSET) {
1730 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1731 return -1;
1732 }
1733 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1734 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1735 return -1;
1736 }
1737 tcp->baddr = regs.r_o7 + 8;
1738 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1739 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1740 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1741 return -1;
1742 }
1743
1744 /*
1745 * XXX - BRUTAL MODE ON
1746 * We cannot set a real BPT in the child, since it will not be
1747 * traced at the moment it will reach the trap and would probably
1748 * die with a core dump.
1749 * Thus, we are force our way in by taking out two instructions
1750 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1751 * generated by out PTRACE_ATTACH.
1752 * Of cause, if we evaporate ourselves in the middle of all this...
1753 */
1754 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1755 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1756 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1757 return -1;
1758 }
1759 tcp->flags |= TCB_BPTSET;
1760
1761#endif /* SPARC */
1762#endif /* SUNOS4 */
1763
1764 return 0;
1765}
1766
1767int
1768clearbpt(tcp)
1769struct tcb *tcp;
1770{
1771
1772#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001773#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001775#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001777#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001779#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001781#elif defined(HPPA)
1782 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001783#elif defined(SH)
1784 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001785#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001787#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 /* Again, we borrow the SunOS breakpoint code. */
1789 if (!(tcp->flags & TCB_BPTSET)) {
1790 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1791 return -1;
1792 }
1793 errno = 0;
1794 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1795 if(errno) {
1796 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1797 return -1;
1798 }
1799 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001800#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001801 if (ia32) {
1802 unsigned long addr;
1803
1804 if (debug)
1805 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1806 if (!(tcp->flags & TCB_BPTSET)) {
1807 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1808 return -1;
1809 }
1810 errno = 0;
1811 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1812 if (errno) {
1813 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1814 return -1;
1815 }
1816 tcp->flags &= ~TCB_BPTSET;
1817
1818 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1819 return -1;
1820 if (addr != tcp->baddr) {
1821 /* The breakpoint has not been reached yet. */
1822 if (debug)
1823 fprintf(stderr,
1824 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1825 addr, tcp->baddr);
1826 return 0;
1827 }
1828 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001829 unsigned long addr, ipsr;
1830 pid_t pid;
1831
1832 pid = tcp->pid;
1833
1834 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1835 return -1;
1836 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1837 return -1;
1838
1839 /* restore original bundle: */
1840 errno = 0;
1841 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1842 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1843 if (errno) {
1844 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1845 return -1;
1846 }
1847
1848 /* restore original "ri" in ipsr: */
1849 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1850 errno = 0;
1851 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1852 if (errno) {
1853 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1854 return -1;
1855 }
1856
1857 tcp->flags &= ~TCB_BPTSET;
1858
1859 if (addr != (tcp->baddr & ~0x3)) {
1860 /* the breakpoint has not been reached yet. */
1861 if (debug)
1862 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1863 addr, tcp->baddr);
1864 return 0;
1865 }
1866 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001867#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868
1869 if (debug)
1870 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1871 if (!(tcp->flags & TCB_BPTSET)) {
1872 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1873 return -1;
1874 }
1875 errno = 0;
1876 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1877 if (errno) {
1878 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1879 return -1;
1880 }
1881 tcp->flags &= ~TCB_BPTSET;
1882
1883#ifdef I386
1884 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1885 return -1;
1886 if (eip != tcp->baddr) {
1887 /* The breakpoint has not been reached yet. */
1888 if (debug)
1889 fprintf(stderr,
1890 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1891 eip, tcp->baddr);
1892 return 0;
1893 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001894#elif defined(X86_64)
1895 if (upeek(tcp->pid, 8*RIP, &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 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001905#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001906 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907 return -1;
1908 if (pc != tcp->baddr) {
1909 /* The breakpoint has not been reached yet. */
1910 if (debug)
1911 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1912 pc, tcp->baddr);
1913 return 0;
1914 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001915#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001916 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1917 return -1;
1918 if (pc != tcp->baddr) {
1919 /* The breakpoint has not been reached yet. */
1920 if (debug)
1921 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1922 pc, tcp->baddr);
1923 return 0;
1924 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001925#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1927 return -1;
1928 if (pc != tcp->baddr) {
1929 /* The breakpoint has not been reached yet. */
1930 if (debug)
1931 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1932 pc, tcp->baddr);
1933 return 0;
1934 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001935#elif defined(HPPA)
1936 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1937 return -1;
1938 iaoq &= ~0x03;
1939 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1940 /* The breakpoint has not been reached yet. */
1941 if (debug)
1942 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1943 iaoq, tcp->baddr);
1944 return 0;
1945 }
1946 iaoq = tcp->baddr | 3;
1947 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1948 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1949 * has no significant effect.
1950 */
1951 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1952 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001953#elif defined(SH)
1954 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1955 return -1;
1956 if (pc != tcp->baddr) {
1957 /* The breakpoint has not been reached yet. */
1958 if (debug)
1959 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1960 pc, tcp->baddr);
1961 return 0;
1962 }
1963
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001964#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001965#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966#endif /* LINUX */
1967
1968#ifdef SUNOS4
1969#ifdef SPARC
1970
1971#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001972 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001973#endif
1974
1975 if (!(tcp->flags & TCB_BPTSET)) {
1976 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1977 return -1;
1978 }
1979 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1980 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1981 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1982 return -1;
1983 }
1984 tcp->flags &= ~TCB_BPTSET;
1985
1986#if !LOOPA
1987 /*
1988 * Since we don't have a single instruction breakpoint, we may have
1989 * to adjust the program counter after removing the our `breakpoint'.
1990 */
1991 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1992 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1993 return -1;
1994 }
1995 if ((regs.r_pc < tcp->baddr) ||
1996 (regs.r_pc > tcp->baddr + 4)) {
1997 /* The breakpoint has not been reached yet */
1998 if (debug)
1999 fprintf(stderr,
2000 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2001 regs.r_pc, tcp->parent->baddr);
2002 return 0;
2003 }
2004 if (regs.r_pc != tcp->baddr)
2005 if (debug)
2006 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2007 regs.r_pc, tcp->baddr);
2008
2009 regs.r_pc = tcp->baddr;
2010 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2011 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2012 return -1;
2013 }
2014#endif /* LOOPA */
2015#endif /* SPARC */
2016#endif /* SUNOS4 */
2017
2018 return 0;
2019}
2020
Roland McGrathd81f1d92003-01-09 06:53:34 +00002021#endif
2022
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002023#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024
2025#ifdef SUNOS4
2026
2027static int
2028getex(pid, hdr)
2029int pid;
2030struct exec *hdr;
2031{
2032 int n;
2033
2034 for (n = 0; n < sizeof *hdr; n += 4) {
2035 long res;
2036 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2037 return -1;
2038 memcpy(((char *) hdr) + n, &res, 4);
2039 }
2040 if (debug) {
2041 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2042 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2043 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2044 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2045 }
2046 return 0;
2047}
2048
2049int
2050fixvfork(tcp)
2051struct tcb *tcp;
2052{
2053 int pid = tcp->pid;
2054 /*
2055 * Change `vfork' in a freshly exec'ed dynamically linked
2056 * executable's (internal) symbol table to plain old `fork'
2057 */
2058
2059 struct exec hdr;
2060 struct link_dynamic dyn;
2061 struct link_dynamic_2 ld;
2062 char *strtab, *cp;
2063
2064 if (getex(pid, &hdr) < 0)
2065 return -1;
2066 if (!hdr.a_dynamic)
2067 return -1;
2068
2069 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2070 fprintf(stderr, "Cannot read DYNAMIC\n");
2071 return -1;
2072 }
2073 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2074 fprintf(stderr, "Cannot read link_dynamic_2\n");
2075 return -1;
2076 }
2077 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002078 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 return -1;
2080 }
2081 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2082 (int)ld.ld_symb_size, strtab) < 0)
2083 goto err;
2084
2085#if 0
2086 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2087 fprintf(stderr, "[symbol: %s]\n", cp);
2088 cp += strlen(cp)+1;
2089 }
2090 return 0;
2091#endif
2092 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2093 if (strcmp(cp, "_vfork") == 0) {
2094 if (debug)
2095 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2096 strcpy(cp, "_fork");
2097 break;
2098 }
2099 cp += strlen(cp)+1;
2100 }
2101 if (cp < strtab + ld.ld_symb_size)
2102 /*
2103 * Write entire symbol table back to avoid
2104 * memory alignment bugs in ptrace
2105 */
2106 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2107 (int)ld.ld_symb_size, strtab) < 0)
2108 goto err;
2109
2110 free(strtab);
2111 return 0;
2112
2113err:
2114 free(strtab);
2115 return -1;
2116}
2117
2118#endif /* SUNOS4 */