blob: 461b9dac80ffc25f9cb33d6053cda63fdcb3be6c [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
Roland McGratha4d48532005-06-08 20:45:28 +0000151#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152void
153tv_tv(tv, a, b)
154struct timeval *tv;
155int a;
156int b;
157{
158 tv->tv_sec = a;
159 tv->tv_usec = b;
160}
Roland McGratha4d48532005-06-08 20:45:28 +0000161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163int
164tv_nz(a)
165struct timeval *a;
166{
167 return a->tv_sec || a->tv_usec;
168}
169
170int
171tv_cmp(a, b)
172struct timeval *a, *b;
173{
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
176 return -1;
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
179 return 1;
180 return 0;
181}
182
183double
184tv_float(tv)
185struct timeval *tv;
186{
187 return tv->tv_sec + tv->tv_usec/1000000.0;
188}
189
190void
191tv_add(tv, a, b)
192struct timeval *tv, *a, *b;
193{
194 tv->tv_sec = a->tv_sec + b->tv_sec;
195 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000196 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197 tv->tv_sec++;
198 tv->tv_usec -= 1000000;
199 }
200}
201
202void
203tv_sub(tv, a, b)
204struct timeval *tv, *a, *b;
205{
206 tv->tv_sec = a->tv_sec - b->tv_sec;
207 tv->tv_usec = a->tv_usec - b->tv_usec;
208 if (((long) tv->tv_usec) < 0) {
209 tv->tv_sec--;
210 tv->tv_usec += 1000000;
211 }
212}
213
214void
215tv_div(tv, a, n)
216struct timeval *tv, *a;
217int n;
218{
219 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
220 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
221 tv->tv_usec %= 1000000;
222}
223
224void
225tv_mul(tv, a, n)
226struct timeval *tv, *a;
227int n;
228{
229 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000230 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 tv->tv_usec %= 1000000;
232}
233
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000234const char *
235xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
244 * Print entry in struct xlat table, if there.
245 */
246void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000247printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000249 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251 if (str)
252 tprintf("%s", str);
253 else
254 tprintf("%#x /* %s */", val, dflt);
255}
256
257/*
258 * Interpret `xlat' as an array of flags
259 * print the entries whose bits are on in `flags'
260 * return # of flags printed.
261 */
262int
263addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000264const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265int flags;
266{
267 int n;
268
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("|%s", xlat->str);
272 flags &= ~xlat->val;
273 n++;
274 }
275 }
276 if (flags) {
277 tprintf("|%#x", flags);
278 n++;
279 }
280 return n;
281}
282
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000283/*
284 * Interpret `xlat' as an array of flags/
285 * Print to static string the entries whose bits are on in `flags'
286 * Return static string.
287 */
288const char *
289sprintflags(const char *prefix, const struct xlat *xlat, int flags)
290{
291 static char outstr[1024];
292 int found = 0;
293
294 strcpy(outstr, prefix);
295
296 for (; xlat->str; xlat++) {
297 if ((flags & xlat->val) == xlat->val) {
298 if (found)
299 strcat(outstr, "|");
300 strcat(outstr, xlat->str);
301 flags &= ~xlat->val;
302 found = 1;
303 }
304 }
305 if (flags) {
306 if (found)
307 strcat(outstr, "|");
308 sprintf(outstr + strlen(outstr), "%#x", flags);
309 }
310
311 return outstr;
312}
313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314int
Roland McGrathb2dee132005-06-01 19:02:36 +0000315printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000316const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000318const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
320 int n;
321 char *sep;
322
323 if (flags == 0 && xlat->val == 0) {
324 tprintf("%s", xlat->str);
325 return 1;
326 }
327
328 sep = "";
329 for (n = 0; xlat->str; xlat++) {
330 if (xlat->val && (flags & xlat->val) == xlat->val) {
331 tprintf("%s%s", sep, xlat->str);
332 flags &= ~xlat->val;
333 sep = "|";
334 n++;
335 }
336 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000337
338 if (n) {
339 if (flags) {
340 tprintf("%s%#x", sep, flags);
341 n++;
342 }
343 } else {
344 if (flags) {
345 tprintf("%#x", flags);
346 if (dflt)
347 tprintf(" /* %s */", dflt);
348 } else {
349 if (dflt)
350 tprintf("0");
351 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000354 return n;
355}
356
357void
358printnum(tcp, addr, fmt)
359struct tcb *tcp;
360long addr;
361char *fmt;
362{
Roland McGratheb285352003-01-14 09:59:00 +0000363 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364
365 if (!addr) {
366 tprintf("NULL");
367 return;
368 }
369 if (umove(tcp, addr, &num) < 0) {
370 tprintf("%#lx", addr);
371 return;
372 }
373 tprintf("[");
374 tprintf(fmt, num);
375 tprintf("]");
376}
377
Roland McGrath6bc12202003-11-13 22:32:27 +0000378void
Roland McGrath9814a942005-07-04 23:28:10 +0000379printnum_int(tcp, addr, fmt)
380struct tcb *tcp;
381long addr;
382char *fmt;
383{
384 int num;
385
386 if (!addr) {
387 tprintf("NULL");
388 return;
389 }
390 if (umove(tcp, addr, &num) < 0) {
391 tprintf("%#lx", addr);
392 return;
393 }
394 tprintf("[");
395 tprintf(fmt, num);
396 tprintf("]");
397}
398
399void
Roland McGrath6bc12202003-11-13 22:32:27 +0000400printuid(text, uid)
401const char *text;
402unsigned long uid;
403{
404 tprintf("%s", text);
405 tprintf((uid == -1) ? "%ld" : "%lu", uid);
406}
407
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408static char path[MAXPATHLEN + 1];
409
Roland McGratha4d48532005-06-08 20:45:28 +0000410static void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000411string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000412{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000413 const unsigned char *ustr = (const unsigned char *) instr;
414 char *s = outstr;
415 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000417 if (xflag > 1)
418 usehex = 1;
419 else if (xflag) {
420 for (i = 0; i < size; ++i) {
421 c = ustr[i];
422 if (len < 0 && c == '\0')
423 break;
424 if (!isprint(c) && !isspace(c)) {
425 usehex = 1;
426 break;
427 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000428 }
429 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000430
431 *s++ = '\"';
432
433 if (usehex) {
434 for (i = 0; i < size; ++i) {
435 c = ustr[i];
436 if (len < 0 && c == '\0')
437 break;
438 sprintf(s, "\\x%02x", c);
439 s += 4;
440 }
441 } else {
442 for (i = 0; i < size; ++i) {
443 c = ustr[i];
444 if (len < 0 && c == '\0')
445 break;
446 switch (c) {
447 case '\"': case '\\':
448 *s++ = '\\';
449 *s++ = c;
450 break;
451 case '\f':
452 *s++ = '\\';
453 *s++ = 'f';
454 break;
455 case '\n':
456 *s++ = '\\';
457 *s++ = 'n';
458 break;
459 case '\r':
460 *s++ = '\\';
461 *s++ = 'r';
462 break;
463 case '\t':
464 *s++ = '\\';
465 *s++ = 't';
466 break;
467 case '\v':
468 *s++ = '\\';
469 *s++ = 'v';
470 break;
471 default:
472 if (isprint(c))
473 *s++ = c;
474 else if (i + 1 < size
475 && isdigit(ustr[i + 1])) {
476 sprintf(s, "\\%03o", c);
477 s += 4;
478 } else {
479 sprintf(s, "\\%o", c);
480 s += strlen(s);
481 }
482 break;
483 }
484 }
485 }
486
487 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488 *s = '\0';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489}
490
491void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000492printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000494 if (n > sizeof path - 1)
Roland McGrathb15c4e42005-10-21 22:06:46 +0000495 n = sizeof path - 1;
496
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000497 if (addr == 0) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000498 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000499 return;
500 }
501
502 path[n] = '\0';
503 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 tprintf("%#lx", addr);
505 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000506 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
507 int trunc = (path[n] != '\0');
508
509 if (trunc)
510 path[n] = '\0';
511 string_quote(path, outstr, -1, n);
512 if (trunc)
513 strcat(outstr, "...");
514 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 }
516}
517
518void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000519printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000521 printpathn(tcp, addr, sizeof path - 1);
522}
523
524void
525printstr(struct tcb *tcp, long addr, int len)
526{
527 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528 static char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000529 int size, trunc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530
531 if (!addr) {
532 tprintf("NULL");
533 return;
534 }
535 if (!str) {
Roland McGratha503dcf2007-08-02 02:06:26 +0000536 if ((str = malloc(max_strlen + 1)) == NULL
Roland McGrath779c4662007-07-11 07:23:40 +0000537 || (outstr = malloc(4*max_strlen
538 + sizeof "\"\"...")) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000539 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 tprintf("%#lx", addr);
541 return;
542 }
543 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000544
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 if (len < 0) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000546 size = max_strlen + 1;
547 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 tprintf("%#lx", addr);
549 return;
550 }
551 }
552 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553 size = MIN(len, max_strlen + 1);
554 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555 tprintf("%#lx", addr);
556 return;
557 }
558 }
559
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000560 trunc = size > max_strlen && str[--size] != 0;
561 string_quote(str, outstr, len, size);
562 if (size < len || (len < 0 && trunc))
563 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000564
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000565 tprintf("%s", outstr);
566}
567
John Hughes1d08dcf2001-07-10 13:48:44 +0000568#if HAVE_SYS_UIO_H
569void
570dumpiov(tcp, len, addr)
571struct tcb * tcp;
572int len;
573long addr;
574{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000575#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
576 union {
577 struct { u_int32_t base; u_int32_t len; } *iov32;
578 struct { u_int64_t base; u_int64_t len; } *iov64;
579 } iovu;
580#define iov iovu.iov64
581#define sizeof_iov \
582 (personality_wordsize[current_personality] == 4 \
583 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
584#define iov_iov_base(i) \
585 (personality_wordsize[current_personality] == 4 \
586 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
587#define iov_iov_len(i) \
588 (personality_wordsize[current_personality] == 4 \
589 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
590#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000591 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000592#define sizeof_iov sizeof(*iov)
593#define iov_iov_base(i) iov[i].iov_base
594#define iov_iov_len(i) iov[i].iov_len
595#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000596 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000597 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000598
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000599 size = sizeof_iov * (unsigned long) len;
600 if (size / sizeof_iov != len
601 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000602 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000603 return;
604 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000605 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000606 for (i = 0; i < len; i++) {
607 /* include the buffer number to make it easy to
608 * match up the trace with the source */
609 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000610 (unsigned long)iov_iov_len(i), i);
611 dumpstr(tcp, (long) iov_iov_base(i),
612 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000613 }
614 }
615 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000616#undef sizeof_iov
617#undef iov_iov_base
618#undef iov_iov_len
619#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000620}
621#endif
622
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000623void
624dumpstr(tcp, addr, len)
625struct tcb *tcp;
626long addr;
627int len;
628{
629 static int strsize = -1;
630 static unsigned char *str;
631 static char outstr[80];
632 char *s;
633 int i, j;
634
635 if (strsize < len) {
636 if (str)
637 free(str);
638 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000639 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640 return;
641 }
642 strsize = len;
643 }
644
645 if (umoven(tcp, addr, len, (char *) str) < 0)
646 return;
647
648 for (i = 0; i < len; i += 16) {
649 s = outstr;
650 sprintf(s, " | %05x ", i);
651 s += 9;
652 for (j = 0; j < 16; j++) {
653 if (j == 8)
654 *s++ = ' ';
655 if (i + j < len) {
656 sprintf(s, " %02x", str[i + j]);
657 s += 3;
658 }
659 else {
660 *s++ = ' '; *s++ = ' '; *s++ = ' ';
661 }
662 }
663 *s++ = ' '; *s++ = ' ';
664 for (j = 0; j < 16; j++) {
665 if (j == 8)
666 *s++ = ' ';
667 if (i + j < len) {
668 if (isprint(str[i + j]))
669 *s++ = str[i + j];
670 else
671 *s++ = '.';
672 }
673 else
674 *s++ = ' ';
675 }
676 tprintf("%s |\n", outstr);
677 }
678}
679
680#define PAGMASK (~(PAGSIZ - 1))
681/*
682 * move `len' bytes of data from process `pid'
683 * at address `addr' to our space at `laddr'
684 */
685int
686umoven(tcp, addr, len, laddr)
687struct tcb *tcp;
688long addr;
689int len;
690char *laddr;
691{
692
693#ifdef LINUX
694 int pid = tcp->pid;
695 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000696 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 union {
698 long val;
699 char x[sizeof(long)];
700 } u;
701
702 if (addr & (sizeof(long) - 1)) {
703 /* addr not a multiple of sizeof(long) */
704 n = addr - (addr & -sizeof(long)); /* residue */
705 addr &= -sizeof(long); /* residue */
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 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000713 /* But if not started, we had a bogus address. */
Roland McGrath1c459762007-08-02 02:22:06 +0000714 if (addr != 0 && errno != EIO)
715 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716 return -1;
717 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000718 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
720 addr += sizeof(long), laddr += m, len -= m;
721 }
722 while (len) {
723 errno = 0;
724 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
725 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000726 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727 /* Ran into 'end of memory' - stupid "printpath" */
728 return 0;
729 }
Roland McGrath1c459762007-08-02 02:22:06 +0000730 if (addr != 0 && errno != EIO)
Roland McGrath4db26242003-01-30 20:15:19 +0000731 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732 return -1;
733 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000734 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
736 addr += sizeof(long), laddr += m, len -= m;
737 }
738#endif /* LINUX */
739
740#ifdef SUNOS4
741 int pid = tcp->pid;
742#if 0
743 int n, m;
744 union {
745 long val;
746 char x[sizeof(long)];
747 } u;
748
749 if (addr & (sizeof(long) - 1)) {
750 /* addr not a multiple of sizeof(long) */
751 n = addr - (addr & -sizeof(long)); /* residue */
752 addr &= -sizeof(long); /* residue */
753 errno = 0;
754 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
755 if (errno) {
756 perror("umoven");
757 return -1;
758 }
759 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
760 addr += sizeof(long), laddr += m, len -= m;
761 }
762 while (len) {
763 errno = 0;
764 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
765 if (errno) {
766 perror("umoven");
767 return -1;
768 }
769 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
770 addr += sizeof(long), laddr += m, len -= m;
771 }
772#else /* !oldway */
773 int n;
774
775 while (len) {
776 n = MIN(len, PAGSIZ);
777 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
778 if (ptrace(PTRACE_READDATA, pid,
779 (char *) addr, len, laddr) < 0) {
780 perror("umoven: ptrace(PTRACE_READDATA, ...)");
781 abort();
782 return -1;
783 }
784 len -= n;
785 addr += n;
786 laddr += n;
787 }
788#endif /* !oldway */
789#endif /* SUNOS4 */
790
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000791#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000792#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000793 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000794#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000795 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000797 lseek(fd, addr, SEEK_SET);
798 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000800#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801
802 return 0;
803}
804
805/*
806 * like `umove' but make the additional effort of looking
807 * for a terminating zero byte.
808 */
809int
810umovestr(tcp, addr, len, laddr)
811struct tcb *tcp;
812long addr;
813int len;
814char *laddr;
815{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000816#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000817#ifdef HAVE_MP_PROCFS
818 int fd = tcp->pfd_as;
819#else
820 int fd = tcp->pfd;
821#endif
822 /* Some systems (e.g. FreeBSD) can be upset if we read off the
823 end of valid memory, avoid this by trying to read up
824 to page boundaries. But we don't know what a page is (and
825 getpagesize(2) (if it exists) doesn't necessarily return
826 hardware page size). Assume all pages >= 1024 (a-historical
827 I know) */
828
829 int page = 1024; /* How to find this? */
830 int move = page - (addr & (page - 1));
831 int left = len;
832
833 lseek(fd, addr, SEEK_SET);
834
835 while (left) {
836 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000837 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000838 return left != len ? 0 : -1;
839 if (memchr (laddr, 0, move)) break;
840 left -= move;
841 laddr += move;
842 addr += move;
843 move = page;
844 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000845#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000846 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 int pid = tcp->pid;
848 int i, n, m;
849 union {
850 long val;
851 char x[sizeof(long)];
852 } u;
853
854 if (addr & (sizeof(long) - 1)) {
855 /* addr not a multiple of sizeof(long) */
856 n = addr - (addr & -sizeof(long)); /* residue */
857 addr &= -sizeof(long); /* residue */
858 errno = 0;
859 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
860 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000861 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000862 /* Ran into 'end of memory' - stupid "printpath" */
863 return 0;
864 }
Roland McGrath1c459762007-08-02 02:22:06 +0000865 if (addr != 0 && errno != EIO)
866 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000867 return -1;
868 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000869 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
871 while (n & (sizeof(long) - 1))
872 if (u.x[n++] == '\0')
873 return 0;
874 addr += sizeof(long), laddr += m, len -= m;
875 }
876 while (len) {
877 errno = 0;
878 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
879 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000880 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 /* Ran into 'end of memory' - stupid "printpath" */
882 return 0;
883 }
Roland McGrath1c459762007-08-02 02:22:06 +0000884 if (addr != 0 && errno != EIO)
885 perror("umovestr");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 return -1;
887 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000888 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
890 for (i = 0; i < sizeof(long); i++)
891 if (u.x[i] == '\0')
892 return 0;
893
894 addr += sizeof(long), laddr += m, len -= m;
895 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000896#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000897 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898}
899
900#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000901#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902#define PTRACE_WRITETEXT 101
903#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000904#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905#endif /* LINUX */
906
907#ifdef SUNOS4
908
909static int
910uload(cmd, pid, addr, len, laddr)
911int cmd;
912int pid;
913long addr;
914int len;
915char *laddr;
916{
917#if 0
918 int n;
919
920 while (len) {
921 n = MIN(len, PAGSIZ);
922 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
923 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
924 perror("uload: ptrace(PTRACE_WRITE, ...)");
925 return -1;
926 }
927 len -= n;
928 addr += n;
929 laddr += n;
930 }
931#else
932 int peek, poke;
933 int n, m;
934 union {
935 long val;
936 char x[sizeof(long)];
937 } u;
938
939 if (cmd == PTRACE_WRITETEXT) {
940 peek = PTRACE_PEEKTEXT;
941 poke = PTRACE_POKETEXT;
942 }
943 else {
944 peek = PTRACE_PEEKDATA;
945 poke = PTRACE_POKEDATA;
946 }
947 if (addr & (sizeof(long) - 1)) {
948 /* addr not a multiple of sizeof(long) */
949 n = addr - (addr & -sizeof(long)); /* residue */
950 addr &= -sizeof(long);
951 errno = 0;
952 u.val = ptrace(peek, pid, (char *) addr, 0);
953 if (errno) {
954 perror("uload: POKE");
955 return -1;
956 }
957 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
958 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
959 perror("uload: POKE");
960 return -1;
961 }
962 addr += sizeof(long), laddr += m, len -= m;
963 }
964 while (len) {
965 if (len < sizeof(long))
966 u.val = ptrace(peek, pid, (char *) addr, 0);
967 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
968 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
969 perror("uload: POKE");
970 return -1;
971 }
972 addr += sizeof(long), laddr += m, len -= m;
973 }
974#endif
975 return 0;
976}
977
978int
979tload(pid, addr, len, laddr)
980int pid;
981int addr, len;
982char *laddr;
983{
984 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
985}
986
987int
988dload(pid, addr, len, laddr)
989int pid;
990int addr;
991int len;
992char *laddr;
993{
994 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
995}
996
997#endif /* SUNOS4 */
998
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000999#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000
1001int
1002upeek(pid, off, res)
1003int pid;
1004long off;
1005long *res;
1006{
1007 long val;
1008
1009#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
1010 {
1011 static int is_sun4m = -1;
1012 struct utsname name;
1013
1014 /* Round up the usual suspects. */
1015 if (is_sun4m == -1) {
1016 if (uname(&name) < 0) {
1017 perror("upeek: uname?");
1018 exit(1);
1019 }
1020 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1021 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001022 extern const struct xlat struct_user_offsets[];
1023 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024
1025 for (x = struct_user_offsets; x->str; x++)
1026 x->val += 1024;
1027 }
1028 }
1029 if (is_sun4m)
1030 off += 1024;
1031 }
1032#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1033 errno = 0;
1034 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1035 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001036 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001037 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001038 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 return -1;
1040 }
1041 *res = val;
1042 return 0;
1043}
1044
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001045#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046
Roland McGratha4d48532005-06-08 20:45:28 +00001047#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048long
1049getpc(tcp)
1050struct tcb *tcp;
1051{
1052
1053#ifdef LINUX
1054 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001055#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1057 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001058#elif defined(X86_64)
1059 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1060 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001061#elif defined(IA64)
1062 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1063 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001064#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 if (upeek(tcp->pid, 4*15, &pc) < 0)
1066 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001067#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001068 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001070#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1072 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001073#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1075 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001076#elif defined(MIPS)
1077 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1078 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001079#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001080 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1082 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001083 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001084#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001085 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001086 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001087#elif defined(HPPA)
1088 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1089 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001090#elif defined(SH)
1091 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1092 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001093#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001094 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1095 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001096#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 return pc;
1098#endif /* LINUX */
1099
1100#ifdef SUNOS4
1101 /*
1102 * Return current program counter for `pid'
1103 * Assumes PC is never 0xffffffff
1104 */
1105 struct regs regs;
1106
1107 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1108 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1109 return -1;
1110 }
1111 return regs.r_pc;
1112#endif /* SUNOS4 */
1113
1114#ifdef SVR4
1115 /* XXX */
1116 return 0;
1117#endif /* SVR4 */
1118
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001119#ifdef FREEBSD
1120 struct reg regs;
1121 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1122 return regs.r_eip;
1123#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124}
Roland McGratha4d48532005-06-08 20:45:28 +00001125#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126
1127void
1128printcall(tcp)
1129struct tcb *tcp;
1130{
Roland McGrath7a918832005-02-02 20:55:23 +00001131#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1132 sizeof(long) == 8 ? "[????????????????] " : \
1133 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134
1135#ifdef LINUX
1136#ifdef I386
1137 long eip;
1138
1139 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001140 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141 return;
1142 }
1143 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001144
1145#elif defined(S390) || defined(S390X)
1146 long psw;
1147 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001148 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001149 return;
1150 }
1151#ifdef S390
1152 tprintf("[%08lx] ", psw);
1153#elif S390X
1154 tprintf("[%16lx] ", psw);
1155#endif
1156
Michal Ludvig0e035502002-09-23 15:41:01 +00001157#elif defined(X86_64)
1158 long rip;
1159
1160 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001161 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001162 return;
1163 }
1164 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001165#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001166 long ip;
1167
1168 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001169 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001170 return;
1171 }
1172 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001173#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 long pc;
1175
Roland McGratheb285352003-01-14 09:59:00 +00001176 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 tprintf ("[????????] ");
1178 return;
1179 }
1180 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001181#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 long pc;
1183
1184 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1185 tprintf ("[????????] ");
1186 return;
1187 }
1188 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001189#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 long pc;
1191
1192 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001193 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 return;
1195 }
1196 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001197#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001198 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001200 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 return;
1202 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001203 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001204#elif defined(HPPA)
1205 long pc;
1206
1207 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1208 tprintf ("[????????] ");
1209 return;
1210 }
1211 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001212#elif defined(MIPS)
1213 long pc;
1214
1215 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1216 tprintf ("[????????] ");
1217 return;
1218 }
1219 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001220#elif defined(SH)
1221 long pc;
1222
1223 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1224 tprintf ("[????????] ");
1225 return;
1226 }
1227 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001228#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001229 long pc;
1230
1231 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001232 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001233 return;
1234 }
1235 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001236#elif defined(ARM)
1237 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001238
Roland McGrathef388682003-06-03 23:28:59 +00001239 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001240 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001241 return;
1242 }
1243 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001244#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245#endif /* LINUX */
1246
1247#ifdef SUNOS4
1248 struct regs regs;
1249
1250 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1251 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001252 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 return;
1254 }
1255 tprintf("[%08x] ", regs.r_o7);
1256#endif /* SUNOS4 */
1257
1258#ifdef SVR4
1259 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001260 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261#endif
1262
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#ifdef FREEBSD
1264 struct reg regs;
1265 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1266 tprintf("[%08x] ", regs.r_eip);
1267#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268}
1269
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271
Roland McGrathd81f1d92003-01-09 06:53:34 +00001272#if defined LINUX
1273
1274#include <sys/syscall.h>
1275#ifndef CLONE_PTRACE
1276# define CLONE_PTRACE 0x00002000
1277#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001278#ifndef CLONE_STOPPED
1279# define CLONE_STOPPED 0x02000000
1280#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001281
1282#ifdef IA64
1283
Roland McGrath08267b82004-02-20 22:56:43 +00001284/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1285 subsystem has them for x86... */
1286#define SYS_fork 2
1287#define SYS_vfork 190
1288
Roland McGrathd81f1d92003-01-09 06:53:34 +00001289typedef unsigned long *arg_setup_state;
1290
1291static int
1292arg_setup(struct tcb *tcp, arg_setup_state *state)
1293{
1294 unsigned long *bsp, cfm, sof, sol;
1295
Roland McGrath08267b82004-02-20 22:56:43 +00001296 if (ia32)
1297 return 0;
1298
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1300 return -1;
1301 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1302 return -1;
1303
1304 sof = (cfm >> 0) & 0x7f;
1305 sol = (cfm >> 7) & 0x7f;
1306 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1307
1308 *state = bsp;
1309 return 0;
1310}
1311
1312# define arg_finish_change(tcp, state) 0
1313
1314#ifdef SYS_fork
1315static int
1316get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1317{
Roland McGrath08267b82004-02-20 22:56:43 +00001318 int ret;
1319
1320 if (ia32)
1321 ret = upeek (tcp->pid, PT_R11, valp);
1322 else
1323 ret = umoven (tcp,
1324 (unsigned long) ia64_rse_skip_regs(*state, 0),
1325 sizeof(long), (void *) valp);
1326 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327}
1328
1329static int
1330get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1331{
Roland McGrath08267b82004-02-20 22:56:43 +00001332 int ret;
1333
1334 if (ia32)
1335 ret = upeek (tcp->pid, PT_R9, valp);
1336 else
1337 ret = umoven (tcp,
1338 (unsigned long) ia64_rse_skip_regs(*state, 1),
1339 sizeof(long), (void *) valp);
1340 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001341}
1342#endif
1343
1344static int
1345set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1346{
Roland McGrath08267b82004-02-20 22:56:43 +00001347 int req = PTRACE_POKEDATA;
1348 void *ap;
1349
1350 if (ia32) {
1351 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1352 req = PTRACE_POKEUSER;
1353 } else
1354 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001356 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357 return errno ? -1 : 0;
1358}
1359
1360static int
1361set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1362{
Roland McGrath08267b82004-02-20 22:56:43 +00001363 int req = PTRACE_POKEDATA;
1364 void *ap;
1365
1366 if (ia32) {
1367 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1368 req = PTRACE_POKEUSER;
1369 } else
1370 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001372 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001373 return errno ? -1 : 0;
1374}
1375
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001376#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001377
1378typedef struct regs arg_setup_state;
1379
1380# define arg_setup(tcp, state) \
1381 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1382# define arg_finish_change(tcp, state) \
1383 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1384
1385# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1386# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1387# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1388# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001389# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001390
1391#else
1392
1393# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001394/* Note: this is only true for the `clone' system call, which handles
1395 arguments specially. We could as well say that its first two arguments
1396 are swapped relative to other architectures, but that would just be
1397 another #ifdef in the calls. */
1398# define arg0_offset PT_GPR3
1399# define arg1_offset PT_ORIGGPR2
1400# define restore_arg0(tcp, state, val) ((void) (state), 0)
1401# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001402# define arg0_index 1
1403# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001404# elif defined (ALPHA) || defined (MIPS)
1405# define arg0_offset REG_A0
1406# define arg1_offset (REG_A0+1)
1407# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001408# define arg0_offset (sizeof(unsigned long)*PT_R3)
1409# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001410# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411# elif defined (HPPA)
1412# define arg0_offset PT_GR26
1413# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001414# elif defined (X86_64)
1415# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1416# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001417# elif defined (SH)
1418# define arg0_offset (4*(REG_REG0+4))
1419# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001420# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001421 /* ABI defines arg0 & 1 in r2 & r3 */
1422# define arg0_offset (REG_OFFSET+16)
1423# define arg1_offset (REG_OFFSET+24)
1424# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001425# else
1426# define arg0_offset 0
1427# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001428# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001429# define restore_arg0(tcp, state, val) 0
1430# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001431# endif
1432
1433typedef int arg_setup_state;
1434
1435# define arg_setup(tcp, state) (0)
1436# define arg_finish_change(tcp, state) 0
1437# define get_arg0(tcp, cookie, valp) \
1438 (upeek ((tcp)->pid, arg0_offset, (valp)))
1439# define get_arg1(tcp, cookie, valp) \
1440 (upeek ((tcp)->pid, arg1_offset, (valp)))
1441
1442static int
1443set_arg0 (struct tcb *tcp, void *cookie, long val)
1444{
Roland McGrathca85b972005-06-07 23:22:08 +00001445 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001446}
1447
1448static int
1449set_arg1 (struct tcb *tcp, void *cookie, long val)
1450{
1451 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1452}
1453
1454#endif
1455
Roland McGrathe1df47f2003-01-14 09:46:15 +00001456#ifndef restore_arg0
1457# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1458#endif
1459#ifndef restore_arg1
1460# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1461#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462
Roland McGrath90d0afd2004-03-01 21:05:16 +00001463#ifndef arg0_index
1464# define arg0_index 0
1465# define arg1_index 1
1466#endif
1467
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468int
1469setbpt(tcp)
1470struct tcb *tcp;
1471{
1472 extern int change_syscall(struct tcb *, int);
1473 arg_setup_state state;
1474
1475 if (tcp->flags & TCB_BPTSET) {
1476 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1477 return -1;
1478 }
1479
Roland McGrath76989d72005-06-07 23:21:31 +00001480 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001481#ifdef SYS_vfork
1482 case SYS_vfork:
1483#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001484#ifdef SYS_fork
1485 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001486#endif
1487#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001488 if (arg_setup (tcp, &state) < 0
1489 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1490 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1491 || change_syscall(tcp, SYS_clone) < 0
1492 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1493 || set_arg1 (tcp, &state, 0) < 0
1494 || arg_finish_change (tcp, &state) < 0)
1495 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001496 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1497 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001498 tcp->flags |= TCB_BPTSET;
1499 return 0;
1500#endif
1501
1502 case SYS_clone:
1503#ifdef SYS_clone2
1504 case SYS_clone2:
1505#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001506 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001507 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001508 || set_arg0 (tcp, &state,
1509 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001510 || arg_finish_change (tcp, &state) < 0))
1511 return -1;
1512 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001513 tcp->inst[0] = tcp->u_arg[arg0_index];
1514 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001515 return 0;
1516
1517 default:
1518 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1519 tcp->scno, tcp->pid);
1520 break;
1521 }
1522
1523 return -1;
1524}
1525
1526int
1527clearbpt(tcp)
1528struct tcb *tcp;
1529{
1530 arg_setup_state state;
1531 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001532 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1533 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001534 || arg_finish_change (tcp, &state))
1535 return -1;
1536 tcp->flags &= ~TCB_BPTSET;
1537 return 0;
1538}
1539
1540#else
1541
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542int
1543setbpt(tcp)
1544struct tcb *tcp;
1545{
1546
1547#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001548#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549 /* We simply use the SunOS breakpoint code. */
1550
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001551 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001552 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553#define LOOPA 0x30800000 /* ba,a 0 */
1554
1555 if (tcp->flags & TCB_BPTSET) {
1556 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1557 return -1;
1558 }
1559 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1560 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1561 return -1;
1562 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001563 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 errno = 0;
1565 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1566 if(errno) {
1567 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1568 return -1;
1569 }
1570
1571 /*
1572 * XXX - BRUTAL MODE ON
1573 * We cannot set a real BPT in the child, since it will not be
1574 * traced at the moment it will reach the trap and would probably
1575 * die with a core dump.
1576 * Thus, we are force our way in by taking out two instructions
1577 * and insert an eternal loop instead, in expectance of the SIGSTOP
1578 * generated by out PTRACE_ATTACH.
1579 * Of cause, if we evaporate ourselves in the middle of all this...
1580 */
1581 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001582 inst = LOOPA;
1583#if defined (SPARC64)
1584 inst <<= 32;
1585 inst |= (tcp->inst[0] & 0xffffffffUL);
1586#endif
1587 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 if(errno) {
1589 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1590 return -1;
1591 }
1592 tcp->flags |= TCB_BPTSET;
1593
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001594#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001595#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001596 if (ia32) {
1597# define LOOP 0x0000feeb
1598 if (tcp->flags & TCB_BPTSET) {
1599 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1600 tcp->pid);
1601 return -1;
1602 }
1603 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1604 return -1;
1605 if (debug)
1606 fprintf(stderr, "[%d] setting bpt at %lx\n",
1607 tcp->pid, tcp->baddr);
1608 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1609 (char *) tcp->baddr, 0);
1610 if (errno) {
1611 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1612 return -1;
1613 }
1614 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1615 if (errno) {
1616 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1617 return -1;
1618 }
1619 tcp->flags |= TCB_BPTSET;
1620 } else {
1621 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001622 * Our strategy here is to replace the bundle that
1623 * contained the clone() syscall with a bundle of the
1624 * form:
1625 *
1626 * { 1: br 1b; br 1b; br 1b }
1627 *
1628 * This ensures that the newly forked child will loop
1629 * endlessly until we've got a chance to attach to it.
1630 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001631# define LOOP0 0x0000100000000017
1632# define LOOP1 0x4000000000200000
1633 unsigned long addr, ipsr;
1634 pid_t pid;
1635
1636 pid = tcp->pid;
1637 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1638 return -1;
1639 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1640 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001641 /* store "ri" in low two bits */
1642 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001643
1644 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001645 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1646 0);
1647 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1648 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001649 if (errno) {
1650 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1651 return -1;
1652 }
1653
1654 errno = 0;
1655 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1656 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1657 if (errno) {
1658 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1659 return -1;
1660 }
1661 tcp->flags |= TCB_BPTSET;
1662 }
1663#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664
Michal Ludvig0e035502002-09-23 15:41:01 +00001665#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666#define LOOP 0x0000feeb
1667#elif defined (M68K)
1668#define LOOP 0x60fe0000
1669#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001670#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001672#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001674#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001675#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001676#define LOOP 0x1000ffff
1677#elif defined(S390)
1678#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001679#elif defined(S390X)
1680#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001681#elif defined(HPPA)
1682#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001683#elif defined(SH)
1684#ifdef __LITTLE_ENDIAN__
1685#define LOOP 0x0000affe
1686#else
1687#define LOOP 0xfeaf0000
1688#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689#else
1690#error unknown architecture
1691#endif
1692
1693 if (tcp->flags & TCB_BPTSET) {
1694 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1695 return -1;
1696 }
1697#if defined (I386)
1698 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1699 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001700#elif defined (X86_64)
1701 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1702 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703#elif defined (M68K)
1704 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1705 return -1;
1706#elif defined (ALPHA)
1707 return -1;
1708#elif defined (ARM)
1709 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001710#elif defined (MIPS)
1711 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001713 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001715#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001716 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1717 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001718#elif defined(HPPA)
1719 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1720 return -1;
1721 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001722#elif defined(SH)
1723 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1724 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725#else
1726#error unknown architecture
1727#endif
1728 if (debug)
1729 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1730 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1731 if (errno) {
1732 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1733 return -1;
1734 }
1735 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1736 if (errno) {
1737 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1738 return -1;
1739 }
1740 tcp->flags |= TCB_BPTSET;
1741
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001742#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001743#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744#endif /* LINUX */
1745
1746#ifdef SUNOS4
1747#ifdef SPARC /* This code is slightly sparc specific */
1748
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001749 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750#define BPT 0x91d02001 /* ta 1 */
1751#define LOOP 0x10800000 /* ba 0 */
1752#define LOOPA 0x30800000 /* ba,a 0 */
1753#define NOP 0x01000000
1754#if LOOPA
1755 static int loopdeloop[1] = {LOOPA};
1756#else
1757 static int loopdeloop[2] = {LOOP, NOP};
1758#endif
1759
1760 if (tcp->flags & TCB_BPTSET) {
1761 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1762 return -1;
1763 }
1764 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1765 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1766 return -1;
1767 }
1768 tcp->baddr = regs.r_o7 + 8;
1769 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1770 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1771 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1772 return -1;
1773 }
1774
1775 /*
1776 * XXX - BRUTAL MODE ON
1777 * We cannot set a real BPT in the child, since it will not be
1778 * traced at the moment it will reach the trap and would probably
1779 * die with a core dump.
1780 * Thus, we are force our way in by taking out two instructions
1781 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1782 * generated by out PTRACE_ATTACH.
1783 * Of cause, if we evaporate ourselves in the middle of all this...
1784 */
1785 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1786 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1787 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1788 return -1;
1789 }
1790 tcp->flags |= TCB_BPTSET;
1791
1792#endif /* SPARC */
1793#endif /* SUNOS4 */
1794
1795 return 0;
1796}
1797
1798int
1799clearbpt(tcp)
1800struct tcb *tcp;
1801{
1802
1803#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001804#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001806#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001808#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001810#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001812#elif defined(HPPA)
1813 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001814#elif defined(SH)
1815 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001816#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001818#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819 /* Again, we borrow the SunOS breakpoint code. */
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;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001831#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001832 if (ia32) {
1833 unsigned long addr;
1834
1835 if (debug)
1836 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1837 if (!(tcp->flags & TCB_BPTSET)) {
1838 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1839 return -1;
1840 }
1841 errno = 0;
1842 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1843 if (errno) {
1844 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1845 return -1;
1846 }
1847 tcp->flags &= ~TCB_BPTSET;
1848
1849 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1850 return -1;
1851 if (addr != tcp->baddr) {
1852 /* The breakpoint has not been reached yet. */
1853 if (debug)
1854 fprintf(stderr,
1855 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856 addr, tcp->baddr);
1857 return 0;
1858 }
1859 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001860 unsigned long addr, ipsr;
1861 pid_t pid;
1862
1863 pid = tcp->pid;
1864
1865 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1866 return -1;
1867 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1868 return -1;
1869
1870 /* restore original bundle: */
1871 errno = 0;
1872 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1873 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1874 if (errno) {
1875 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1876 return -1;
1877 }
1878
1879 /* restore original "ri" in ipsr: */
1880 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1881 errno = 0;
1882 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1883 if (errno) {
1884 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1885 return -1;
1886 }
1887
1888 tcp->flags &= ~TCB_BPTSET;
1889
1890 if (addr != (tcp->baddr & ~0x3)) {
1891 /* the breakpoint has not been reached yet. */
1892 if (debug)
1893 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1894 addr, tcp->baddr);
1895 return 0;
1896 }
1897 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001898#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899
1900 if (debug)
1901 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1902 if (!(tcp->flags & TCB_BPTSET)) {
1903 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1904 return -1;
1905 }
1906 errno = 0;
1907 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1908 if (errno) {
1909 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1910 return -1;
1911 }
1912 tcp->flags &= ~TCB_BPTSET;
1913
1914#ifdef I386
1915 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1916 return -1;
1917 if (eip != tcp->baddr) {
1918 /* The breakpoint has not been reached yet. */
1919 if (debug)
1920 fprintf(stderr,
1921 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1922 eip, tcp->baddr);
1923 return 0;
1924 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001925#elif defined(X86_64)
1926 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1927 return -1;
1928 if (eip != tcp->baddr) {
1929 /* The breakpoint has not been reached yet. */
1930 if (debug)
1931 fprintf(stderr,
1932 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1933 eip, tcp->baddr);
1934 return 0;
1935 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001936#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001937 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 return -1;
1939 if (pc != tcp->baddr) {
1940 /* The breakpoint has not been reached yet. */
1941 if (debug)
1942 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1943 pc, tcp->baddr);
1944 return 0;
1945 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001946#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1948 return -1;
1949 if (pc != tcp->baddr) {
1950 /* The breakpoint has not been reached yet. */
1951 if (debug)
1952 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1953 pc, tcp->baddr);
1954 return 0;
1955 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001956#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1958 return -1;
1959 if (pc != tcp->baddr) {
1960 /* The breakpoint has not been reached yet. */
1961 if (debug)
1962 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1963 pc, tcp->baddr);
1964 return 0;
1965 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001966#elif defined(HPPA)
1967 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1968 return -1;
1969 iaoq &= ~0x03;
1970 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1971 /* The breakpoint has not been reached yet. */
1972 if (debug)
1973 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1974 iaoq, tcp->baddr);
1975 return 0;
1976 }
1977 iaoq = tcp->baddr | 3;
1978 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1979 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1980 * has no significant effect.
1981 */
1982 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1983 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001984#elif defined(SH)
1985 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1986 return -1;
1987 if (pc != tcp->baddr) {
1988 /* The breakpoint has not been reached yet. */
1989 if (debug)
1990 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1991 pc, tcp->baddr);
1992 return 0;
1993 }
1994
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001995#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001996#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997#endif /* LINUX */
1998
1999#ifdef SUNOS4
2000#ifdef SPARC
2001
2002#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00002003 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004#endif
2005
2006 if (!(tcp->flags & TCB_BPTSET)) {
2007 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2008 return -1;
2009 }
2010 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
2011 sizeof tcp->inst, (char *) tcp->inst) < 0) {
2012 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
2013 return -1;
2014 }
2015 tcp->flags &= ~TCB_BPTSET;
2016
2017#if !LOOPA
2018 /*
2019 * Since we don't have a single instruction breakpoint, we may have
2020 * to adjust the program counter after removing the our `breakpoint'.
2021 */
2022 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2023 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2024 return -1;
2025 }
2026 if ((regs.r_pc < tcp->baddr) ||
2027 (regs.r_pc > tcp->baddr + 4)) {
2028 /* The breakpoint has not been reached yet */
2029 if (debug)
2030 fprintf(stderr,
2031 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2032 regs.r_pc, tcp->parent->baddr);
2033 return 0;
2034 }
2035 if (regs.r_pc != tcp->baddr)
2036 if (debug)
2037 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2038 regs.r_pc, tcp->baddr);
2039
2040 regs.r_pc = tcp->baddr;
2041 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2042 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2043 return -1;
2044 }
2045#endif /* LOOPA */
2046#endif /* SPARC */
2047#endif /* SUNOS4 */
2048
2049 return 0;
2050}
2051
Roland McGrathd81f1d92003-01-09 06:53:34 +00002052#endif
2053
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002054#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055
2056#ifdef SUNOS4
2057
2058static int
2059getex(pid, hdr)
2060int pid;
2061struct exec *hdr;
2062{
2063 int n;
2064
2065 for (n = 0; n < sizeof *hdr; n += 4) {
2066 long res;
2067 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2068 return -1;
2069 memcpy(((char *) hdr) + n, &res, 4);
2070 }
2071 if (debug) {
2072 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2073 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2074 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2075 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2076 }
2077 return 0;
2078}
2079
2080int
2081fixvfork(tcp)
2082struct tcb *tcp;
2083{
2084 int pid = tcp->pid;
2085 /*
2086 * Change `vfork' in a freshly exec'ed dynamically linked
2087 * executable's (internal) symbol table to plain old `fork'
2088 */
2089
2090 struct exec hdr;
2091 struct link_dynamic dyn;
2092 struct link_dynamic_2 ld;
2093 char *strtab, *cp;
2094
2095 if (getex(pid, &hdr) < 0)
2096 return -1;
2097 if (!hdr.a_dynamic)
2098 return -1;
2099
2100 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2101 fprintf(stderr, "Cannot read DYNAMIC\n");
2102 return -1;
2103 }
2104 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2105 fprintf(stderr, "Cannot read link_dynamic_2\n");
2106 return -1;
2107 }
2108 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002109 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 return -1;
2111 }
2112 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2113 (int)ld.ld_symb_size, strtab) < 0)
2114 goto err;
2115
2116#if 0
2117 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2118 fprintf(stderr, "[symbol: %s]\n", cp);
2119 cp += strlen(cp)+1;
2120 }
2121 return 0;
2122#endif
2123 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2124 if (strcmp(cp, "_vfork") == 0) {
2125 if (debug)
2126 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2127 strcpy(cp, "_fork");
2128 break;
2129 }
2130 cp += strlen(cp)+1;
2131 }
2132 if (cp < strtab + ld.ld_symb_size)
2133 /*
2134 * Write entire symbol table back to avoid
2135 * memory alignment bugs in ptrace
2136 */
2137 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2138 (int)ld.ld_symb_size, strtab) < 0)
2139 goto err;
2140
2141 free(strtab);
2142 return 0;
2143
2144err:
2145 free(strtab);
2146 return -1;
2147}
2148
2149#endif /* SUNOS4 */