blob: 2d55f8ed771763fc5aed126f978e358841e00991 [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
38#include <sys/user.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#ifdef SUNOS4
42#include <machine/reg.h>
43#include <a.out.h>
44#include <link.h>
45#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000046
Wichert Akkerman15dea971999-10-06 13:06:34 +000047#if defined(linux)
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#include <linux/ptrace.h>
49#endif
50
51#ifdef HAVE_SYS_REG_H
52#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000053# define PTRACE_PEEKUSR PTRACE_PEEKUSER
54#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000055
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000056#ifdef HAVE_SYS_PTRACE_H
57#include <sys/ptrace.h>
58#endif
59
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000060#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
61#include <sys/utsname.h>
62#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
63
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000064#if defined(LINUX) && defined(SPARC)
65
66#include <asm/reg.h>
67
68#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069
70#include <linux/unistd.h>
71
72#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
73 type5,arg5,syscall) \
74type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
75{ \
76 long __res; \
77\
78__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
79 "or %%g0, %2, %%o1\n\t" \
80 "or %%g0, %3, %%o2\n\t" \
81 "or %%g0, %4, %%o3\n\t" \
82 "or %%g0, %5, %%o4\n\t" \
83 "or %%g0, %6, %%g1\n\t" \
84 "t 0x10\n\t" \
85 "bcc 1f\n\t" \
86 "or %%g0, %%o0, %0\n\t" \
87 "sub %%g0, %%o0, %0\n\t" \
88 "1:\n\t" \
89 : "=r" (__res) \
90 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
91 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
92 "i" (__NR_##syscall) \
93 : "g1", "o0", "o1", "o2", "o3", "o4"); \
94if (__res>=0) \
95 return (type) __res; \
96errno = -__res; \
97return -1; \
98}
99
100static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
101
102#define _ptrace
103
104#endif
105
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000106#endif
107
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108/* macros */
109#ifndef MAX
110#define MAX(a,b) (((a) > (b)) ? (a) : (b))
111#endif
112#ifndef MIN
113#define MIN(a,b) (((a) < (b)) ? (a) : (b))
114#endif
115
116void
117tv_tv(tv, a, b)
118struct timeval *tv;
119int a;
120int b;
121{
122 tv->tv_sec = a;
123 tv->tv_usec = b;
124}
125
126int
127tv_nz(a)
128struct timeval *a;
129{
130 return a->tv_sec || a->tv_usec;
131}
132
133int
134tv_cmp(a, b)
135struct timeval *a, *b;
136{
137 if (a->tv_sec < b->tv_sec
138 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
139 return -1;
140 if (a->tv_sec > b->tv_sec
141 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
142 return 1;
143 return 0;
144}
145
146double
147tv_float(tv)
148struct timeval *tv;
149{
150 return tv->tv_sec + tv->tv_usec/1000000.0;
151}
152
153void
154tv_add(tv, a, b)
155struct timeval *tv, *a, *b;
156{
157 tv->tv_sec = a->tv_sec + b->tv_sec;
158 tv->tv_usec = a->tv_usec + b->tv_usec;
159 if (tv->tv_usec > 1000000) {
160 tv->tv_sec++;
161 tv->tv_usec -= 1000000;
162 }
163}
164
165void
166tv_sub(tv, a, b)
167struct timeval *tv, *a, *b;
168{
169 tv->tv_sec = a->tv_sec - b->tv_sec;
170 tv->tv_usec = a->tv_usec - b->tv_usec;
171 if (((long) tv->tv_usec) < 0) {
172 tv->tv_sec--;
173 tv->tv_usec += 1000000;
174 }
175}
176
177void
178tv_div(tv, a, n)
179struct timeval *tv, *a;
180int n;
181{
182 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
183 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
184 tv->tv_usec %= 1000000;
185}
186
187void
188tv_mul(tv, a, n)
189struct timeval *tv, *a;
190int n;
191{
192 tv->tv_usec = a->tv_usec * n;
193 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
194 tv->tv_usec %= 1000000;
195}
196
197char *
198xlookup(xlat, val)
199struct xlat *xlat;
200int val;
201{
202 for (; xlat->str != NULL; xlat++)
203 if (xlat->val == val)
204 return xlat->str;
205 return NULL;
206}
207
208/*
209 * Print entry in struct xlat table, if there.
210 */
211void
212printxval(xlat, val, dflt)
213struct xlat *xlat;
214int val;
215char *dflt;
216{
217 char *str = xlookup(xlat, val);
218
219 if (str)
220 tprintf("%s", str);
221 else
222 tprintf("%#x /* %s */", val, dflt);
223}
224
225/*
226 * Interpret `xlat' as an array of flags
227 * print the entries whose bits are on in `flags'
228 * return # of flags printed.
229 */
230int
231addflags(xlat, flags)
232struct xlat *xlat;
233int flags;
234{
235 int n;
236
237 for (n = 0; xlat->str; xlat++) {
238 if (xlat->val && (flags & xlat->val) == xlat->val) {
239 tprintf("|%s", xlat->str);
240 flags &= ~xlat->val;
241 n++;
242 }
243 }
244 if (flags) {
245 tprintf("|%#x", flags);
246 n++;
247 }
248 return n;
249}
250
251int
252printflags(xlat, flags)
253struct xlat *xlat;
254int flags;
255{
256 int n;
257 char *sep;
258
259 if (flags == 0 && xlat->val == 0) {
260 tprintf("%s", xlat->str);
261 return 1;
262 }
263
264 sep = "";
265 for (n = 0; xlat->str; xlat++) {
266 if (xlat->val && (flags & xlat->val) == xlat->val) {
267 tprintf("%s%s", sep, xlat->str);
268 flags &= ~xlat->val;
269 sep = "|";
270 n++;
271 }
272 }
273 if (flags) {
274 tprintf("%s%#x", sep, flags);
275 n++;
276 }
277 return n;
278}
279
280void
281printnum(tcp, addr, fmt)
282struct tcb *tcp;
283long addr;
284char *fmt;
285{
286 int num;
287
288 if (!addr) {
289 tprintf("NULL");
290 return;
291 }
292 if (umove(tcp, addr, &num) < 0) {
293 tprintf("%#lx", addr);
294 return;
295 }
296 tprintf("[");
297 tprintf(fmt, num);
298 tprintf("]");
299}
300
301static char path[MAXPATHLEN + 1];
302
303void
304string_quote(str)
305char *str;
306{
307 char buf[2 * MAXPATHLEN + 1];
308 char *s;
309
310 if (!strpbrk(str, "\"\'\\")) {
311 tprintf("\"%s\"", str);
312 return;
313 }
314 for (s = buf; *str; str++) {
315 switch (*str) {
316 case '\"': case '\'': case '\\':
317 *s++ = '\\'; *s++ = *str; break;
318 default:
319 *s++ = *str; break;
320 }
321 }
322 *s = '\0';
323 tprintf("\"%s\"", buf);
324}
325
326void
327printpath(tcp, addr)
328struct tcb *tcp;
329long addr;
330{
331 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
332 tprintf("%#lx", addr);
333 else
334 string_quote(path);
335 return;
336}
337
338void
339printpathn(tcp, addr, n)
340struct tcb *tcp;
341long addr;
342int n;
343{
344 if (umovestr(tcp, addr, n, path) < 0)
345 tprintf("%#lx", addr);
346 else {
347 path[n] = '\0';
348 string_quote(path);
349 }
350}
351
352void
353printstr(tcp, addr, len)
354struct tcb *tcp;
355long addr;
356int len;
357{
358 static unsigned char *str = NULL;
359 static char *outstr;
360 int i, n, c, usehex;
361 char *s, *outend;
362
363 if (!addr) {
364 tprintf("NULL");
365 return;
366 }
367 if (!str) {
368 if ((str = malloc(max_strlen)) == NULL
369 || (outstr = malloc(2*max_strlen)) == NULL) {
370 fprintf(stderr, "printstr: no memory\n");
371 tprintf("%#lx", addr);
372 return;
373 }
374 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000375 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376 if (len < 0) {
377 n = max_strlen;
378 if (umovestr(tcp, addr, n, (char *) str) < 0) {
379 tprintf("%#lx", addr);
380 return;
381 }
382 }
383 else {
384 n = MIN(len, max_strlen);
385 if (umoven(tcp, addr, n, (char *) str) < 0) {
386 tprintf("%#lx", addr);
387 return;
388 }
389 }
390
391 usehex = 0;
392 if (xflag > 1)
393 usehex = 1;
394 else if (xflag) {
395 for (i = 0; i < n; i++) {
396 c = str[i];
397 if (len < 0 && c == '\0')
398 break;
399 if (!isprint(c) && !isspace(c)) {
400 usehex = 1;
401 break;
402 }
403 }
404 }
405
406 s = outstr;
407 *s++ = '\"';
408
409 if (usehex) {
410 for (i = 0; i < n; i++) {
411 c = str[i];
412 if (len < 0 && c == '\0')
413 break;
414 sprintf(s, "\\x%02x", c);
415 s += 4;
416 if (s > outend)
417 break;
418 }
419 }
420 else {
421 for (i = 0; i < n; i++) {
422 c = str[i];
423 if (len < 0 && c == '\0')
424 break;
425 switch (c) {
426 case '\"': case '\'': case '\\':
427 *s++ = '\\'; *s++ = c; break;
428 case '\f':
429 *s++ = '\\'; *s++ = 'f'; break;
430 case '\n':
431 *s++ = '\\'; *s++ = 'n'; break;
432 case '\r':
433 *s++ = '\\'; *s++ = 'r'; break;
434 case '\t':
435 *s++ = '\\'; *s++ = 't'; break;
436 case '\v':
437 *s++ = '\\'; *s++ = 'v'; break;
438 default:
439 if (isprint(c))
440 *s++ = c;
441 else if (i < n - 1 && isdigit(str[i + 1])) {
442 sprintf(s, "\\%03o", c);
443 s += 4;
444 }
445 else {
446 sprintf(s, "\\%o", c);
447 s += strlen(s);
448 }
449 break;
450 }
451 if (s > outend)
452 break;
453 }
454 }
455
456 *s++ = '\"';
457 if (i < len || (len < 0 && (i == n || s > outend))) {
458 *s++ = '.'; *s++ = '.'; *s++ = '.';
459 }
460 *s = '\0';
461 tprintf("%s", outstr);
462}
463
464void
465dumpstr(tcp, addr, len)
466struct tcb *tcp;
467long addr;
468int len;
469{
470 static int strsize = -1;
471 static unsigned char *str;
472 static char outstr[80];
473 char *s;
474 int i, j;
475
476 if (strsize < len) {
477 if (str)
478 free(str);
479 if ((str = malloc(len)) == NULL) {
480 fprintf(stderr, "dump: no memory\n");
481 return;
482 }
483 strsize = len;
484 }
485
486 if (umoven(tcp, addr, len, (char *) str) < 0)
487 return;
488
489 for (i = 0; i < len; i += 16) {
490 s = outstr;
491 sprintf(s, " | %05x ", i);
492 s += 9;
493 for (j = 0; j < 16; j++) {
494 if (j == 8)
495 *s++ = ' ';
496 if (i + j < len) {
497 sprintf(s, " %02x", str[i + j]);
498 s += 3;
499 }
500 else {
501 *s++ = ' '; *s++ = ' '; *s++ = ' ';
502 }
503 }
504 *s++ = ' '; *s++ = ' ';
505 for (j = 0; j < 16; j++) {
506 if (j == 8)
507 *s++ = ' ';
508 if (i + j < len) {
509 if (isprint(str[i + j]))
510 *s++ = str[i + j];
511 else
512 *s++ = '.';
513 }
514 else
515 *s++ = ' ';
516 }
517 tprintf("%s |\n", outstr);
518 }
519}
520
521#define PAGMASK (~(PAGSIZ - 1))
522/*
523 * move `len' bytes of data from process `pid'
524 * at address `addr' to our space at `laddr'
525 */
526int
527umoven(tcp, addr, len, laddr)
528struct tcb *tcp;
529long addr;
530int len;
531char *laddr;
532{
533
534#ifdef LINUX
535 int pid = tcp->pid;
536 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000537 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 union {
539 long val;
540 char x[sizeof(long)];
541 } u;
542
543 if (addr & (sizeof(long) - 1)) {
544 /* addr not a multiple of sizeof(long) */
545 n = addr - (addr & -sizeof(long)); /* residue */
546 addr &= -sizeof(long); /* residue */
547 errno = 0;
548 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
549 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000550 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 /* Ran into 'end of memory' - stupid "printpath" */
552 return 0;
553 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000554 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555 perror("ptrace: umoven");
556 return -1;
557 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000558 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
560 addr += sizeof(long), laddr += m, len -= m;
561 }
562 while (len) {
563 errno = 0;
564 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
565 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000566 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 /* Ran into 'end of memory' - stupid "printpath" */
568 return 0;
569 }
570 perror("ptrace: umoven");
571 return -1;
572 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000573 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
575 addr += sizeof(long), laddr += m, len -= m;
576 }
577#endif /* LINUX */
578
579#ifdef SUNOS4
580 int pid = tcp->pid;
581#if 0
582 int n, m;
583 union {
584 long val;
585 char x[sizeof(long)];
586 } u;
587
588 if (addr & (sizeof(long) - 1)) {
589 /* addr not a multiple of sizeof(long) */
590 n = addr - (addr & -sizeof(long)); /* residue */
591 addr &= -sizeof(long); /* residue */
592 errno = 0;
593 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
594 if (errno) {
595 perror("umoven");
596 return -1;
597 }
598 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
599 addr += sizeof(long), laddr += m, len -= m;
600 }
601 while (len) {
602 errno = 0;
603 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
604 if (errno) {
605 perror("umoven");
606 return -1;
607 }
608 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
609 addr += sizeof(long), laddr += m, len -= m;
610 }
611#else /* !oldway */
612 int n;
613
614 while (len) {
615 n = MIN(len, PAGSIZ);
616 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
617 if (ptrace(PTRACE_READDATA, pid,
618 (char *) addr, len, laddr) < 0) {
619 perror("umoven: ptrace(PTRACE_READDATA, ...)");
620 abort();
621 return -1;
622 }
623 len -= n;
624 addr += n;
625 laddr += n;
626 }
627#endif /* !oldway */
628#endif /* SUNOS4 */
629
630#ifdef SVR4
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000631#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000632 if (pread(tcp->pfd_as, laddr, len, addr) == -1)
633 return -1;
634#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000635/*
636 * We would like to use pread preferentially for speed
637 * but even though SGI has it in their library, it no longer works.
638 */
639#ifdef MIPS
640#undef HAVE_PREAD
641#endif
642#ifdef HAVE_PREAD
643 if (pread(tcp->pfd, laddr, len, addr) == -1)
644 return -1;
645#else /* !HAVE_PREAD */
646 lseek(tcp->pfd, addr, SEEK_SET);
647 if (read(tcp->pfd, laddr, len) == -1)
648 return -1;
649#endif /* !HAVE_PREAD */
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000650#endif /* HAVE_MP_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651#endif /* SVR4 */
652
653 return 0;
654}
655
656/*
657 * like `umove' but make the additional effort of looking
658 * for a terminating zero byte.
659 */
660int
661umovestr(tcp, addr, len, laddr)
662struct tcb *tcp;
663long addr;
664int len;
665char *laddr;
666{
Wichert Akkerman71bdaff1999-05-28 10:28:56 +0000667#ifdef SVR4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000668 return umoven(tcp, addr, len, laddr);
669#else /* !SVR4 */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000670 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671 int pid = tcp->pid;
672 int i, n, m;
673 union {
674 long val;
675 char x[sizeof(long)];
676 } u;
677
678 if (addr & (sizeof(long) - 1)) {
679 /* addr not a multiple of sizeof(long) */
680 n = addr - (addr & -sizeof(long)); /* residue */
681 addr &= -sizeof(long); /* residue */
682 errno = 0;
683 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
684 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000685 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 /* Ran into 'end of memory' - stupid "printpath" */
687 return 0;
688 }
689 perror("umovestr");
690 return -1;
691 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000692 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
694 while (n & (sizeof(long) - 1))
695 if (u.x[n++] == '\0')
696 return 0;
697 addr += sizeof(long), laddr += m, len -= m;
698 }
699 while (len) {
700 errno = 0;
701 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
702 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000703 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000704 /* Ran into 'end of memory' - stupid "printpath" */
705 return 0;
706 }
707 perror("umovestr");
708 return -1;
709 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000710 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000711 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
712 for (i = 0; i < sizeof(long); i++)
713 if (u.x[i] == '\0')
714 return 0;
715
716 addr += sizeof(long), laddr += m, len -= m;
717 }
718 return 0;
719#endif /* !SVR4 */
720}
721
722#ifdef LINUX
723#ifndef SPARC
724#define PTRACE_WRITETEXT 101
725#define PTRACE_WRITEDATA 102
726#endif /* !SPARC */
727#endif /* LINUX */
728
729#ifdef SUNOS4
730
731static int
732uload(cmd, pid, addr, len, laddr)
733int cmd;
734int pid;
735long addr;
736int len;
737char *laddr;
738{
739#if 0
740 int n;
741
742 while (len) {
743 n = MIN(len, PAGSIZ);
744 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
745 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
746 perror("uload: ptrace(PTRACE_WRITE, ...)");
747 return -1;
748 }
749 len -= n;
750 addr += n;
751 laddr += n;
752 }
753#else
754 int peek, poke;
755 int n, m;
756 union {
757 long val;
758 char x[sizeof(long)];
759 } u;
760
761 if (cmd == PTRACE_WRITETEXT) {
762 peek = PTRACE_PEEKTEXT;
763 poke = PTRACE_POKETEXT;
764 }
765 else {
766 peek = PTRACE_PEEKDATA;
767 poke = PTRACE_POKEDATA;
768 }
769 if (addr & (sizeof(long) - 1)) {
770 /* addr not a multiple of sizeof(long) */
771 n = addr - (addr & -sizeof(long)); /* residue */
772 addr &= -sizeof(long);
773 errno = 0;
774 u.val = ptrace(peek, pid, (char *) addr, 0);
775 if (errno) {
776 perror("uload: POKE");
777 return -1;
778 }
779 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
780 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
781 perror("uload: POKE");
782 return -1;
783 }
784 addr += sizeof(long), laddr += m, len -= m;
785 }
786 while (len) {
787 if (len < sizeof(long))
788 u.val = ptrace(peek, pid, (char *) addr, 0);
789 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
790 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
791 perror("uload: POKE");
792 return -1;
793 }
794 addr += sizeof(long), laddr += m, len -= m;
795 }
796#endif
797 return 0;
798}
799
800int
801tload(pid, addr, len, laddr)
802int pid;
803int addr, len;
804char *laddr;
805{
806 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
807}
808
809int
810dload(pid, addr, len, laddr)
811int pid;
812int addr;
813int len;
814char *laddr;
815{
816 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
817}
818
819#endif /* SUNOS4 */
820
821#ifndef SVR4
822
823int
824upeek(pid, off, res)
825int pid;
826long off;
827long *res;
828{
829 long val;
830
831#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
832 {
833 static int is_sun4m = -1;
834 struct utsname name;
835
836 /* Round up the usual suspects. */
837 if (is_sun4m == -1) {
838 if (uname(&name) < 0) {
839 perror("upeek: uname?");
840 exit(1);
841 }
842 is_sun4m = strcmp(name.machine, "sun4m") == 0;
843 if (is_sun4m) {
844 extern struct xlat struct_user_offsets[];
845 struct xlat *x;
846
847 for (x = struct_user_offsets; x->str; x++)
848 x->val += 1024;
849 }
850 }
851 if (is_sun4m)
852 off += 1024;
853 }
854#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
855 errno = 0;
856 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
857 if (val == -1 && errno) {
858 perror("upeek: ptrace(PTRACE_PEEKUSER, ... )");
859 return -1;
860 }
861 *res = val;
862 return 0;
863}
864
865#endif /* !SVR4 */
866
867long
868getpc(tcp)
869struct tcb *tcp;
870{
871
872#ifdef LINUX
873 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000874#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000875 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
876 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000877#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878 if (upeek(tcp->pid, 4*15, &pc) < 0)
879 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000880#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
882 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000883#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
885 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000886#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887 if (upeek(tcp->pid, REG_PC, &pc) < 0)
888 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000889#elif defined(MIPS)
890 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
891 return -1;
892#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000893 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
895 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000896 pc = regs.r_pc;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000897#elif defined(S390)
898 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000899#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 return pc;
901#endif /* LINUX */
902
903#ifdef SUNOS4
904 /*
905 * Return current program counter for `pid'
906 * Assumes PC is never 0xffffffff
907 */
908 struct regs regs;
909
910 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
911 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
912 return -1;
913 }
914 return regs.r_pc;
915#endif /* SUNOS4 */
916
917#ifdef SVR4
918 /* XXX */
919 return 0;
920#endif /* SVR4 */
921
922}
923
924void
925printcall(tcp)
926struct tcb *tcp;
927{
928
929#ifdef LINUX
930#ifdef I386
931 long eip;
932
933 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
934 tprintf("[????????] ");
935 return;
936 }
937 tprintf("[%08lx] ", eip);
938#else /* !I386K */
939#ifdef POWERPC
940 long pc;
941
942 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) {
943 tprintf ("[????????] ");
944 return;
945 }
946 tprintf("[%08lx] ", pc);
947#else /* !POWERPC */
948#ifdef M68K
949 long pc;
950
951 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
952 tprintf ("[????????] ");
953 return;
954 }
955 tprintf("[%08lx] ", pc);
956#else /* !M68K */
957#ifdef ALPHA
958 long pc;
959
960 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
961 tprintf ("[????????] ");
962 return;
963 }
964 tprintf("[%08lx] ", pc);
965#else /* !ALPHA */
966#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000967 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
969 tprintf("[????????] ");
970 return;
971 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000972 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973#endif /* SPARC */
974#endif /* ALPHA */
975#endif /* !M68K */
976#endif /* !POWERPC */
977#endif /* !I386 */
978#endif /* LINUX */
979
980#ifdef SUNOS4
981 struct regs regs;
982
983 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
984 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
985 tprintf("[????????] ");
986 return;
987 }
988 tprintf("[%08x] ", regs.r_o7);
989#endif /* SUNOS4 */
990
991#ifdef SVR4
992 /* XXX */
993 tprintf("[????????] ");
994#endif
995
996}
997
998#ifndef SVR4
999
1000int
1001setbpt(tcp)
1002struct tcb *tcp;
1003{
1004
1005#ifdef LINUX
1006#ifdef SPARC
1007 /* We simply use the SunOS breakpoint code. */
1008
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001009 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010#define LOOPA 0x30800000 /* ba,a 0 */
1011
1012 if (tcp->flags & TCB_BPTSET) {
1013 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1014 return -1;
1015 }
1016 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1017 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1018 return -1;
1019 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001020 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 errno = 0;
1022 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1023 if(errno) {
1024 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1025 return -1;
1026 }
1027
1028 /*
1029 * XXX - BRUTAL MODE ON
1030 * We cannot set a real BPT in the child, since it will not be
1031 * traced at the moment it will reach the trap and would probably
1032 * die with a core dump.
1033 * Thus, we are force our way in by taking out two instructions
1034 * and insert an eternal loop instead, in expectance of the SIGSTOP
1035 * generated by out PTRACE_ATTACH.
1036 * Of cause, if we evaporate ourselves in the middle of all this...
1037 */
1038 errno = 0;
1039 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1040 if(errno) {
1041 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1042 return -1;
1043 }
1044 tcp->flags |= TCB_BPTSET;
1045
1046#else /* !SPARC */
1047
1048#if defined (I386)
1049#define LOOP 0x0000feeb
1050#elif defined (M68K)
1051#define LOOP 0x60fe0000
1052#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001053#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054#elif defined (POWERPC)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001055#define LOOP 0x0000feeb
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056#elif defined(ARM)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001057#define LOOP -1 /* almost certainly wrong, jws */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001058#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001059#define LOOP 0x1000ffff
1060#elif defined(S390)
1061#define LOOP 0xa7f40000 /* BRC 15,0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062#else
1063#error unknown architecture
1064#endif
1065
1066 if (tcp->flags & TCB_BPTSET) {
1067 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1068 return -1;
1069 }
1070#if defined (I386)
1071 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1072 return -1;
1073#elif defined (M68K)
1074 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1075 return -1;
1076#elif defined (ALPHA)
1077 return -1;
1078#elif defined (ARM)
1079 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001080#elif defined (MIPS)
1081 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082#elif defined (POWERPC)
1083 if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)
1084 return -1;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001085#elif defined(S390)
1086 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1087 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088#else
1089#error unknown architecture
1090#endif
1091 if (debug)
1092 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1093 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1094 if (errno) {
1095 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1096 return -1;
1097 }
1098 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1099 if (errno) {
1100 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1101 return -1;
1102 }
1103 tcp->flags |= TCB_BPTSET;
1104
1105#endif /* SPARC */
1106#endif /* LINUX */
1107
1108#ifdef SUNOS4
1109#ifdef SPARC /* This code is slightly sparc specific */
1110
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001111 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112#define BPT 0x91d02001 /* ta 1 */
1113#define LOOP 0x10800000 /* ba 0 */
1114#define LOOPA 0x30800000 /* ba,a 0 */
1115#define NOP 0x01000000
1116#if LOOPA
1117 static int loopdeloop[1] = {LOOPA};
1118#else
1119 static int loopdeloop[2] = {LOOP, NOP};
1120#endif
1121
1122 if (tcp->flags & TCB_BPTSET) {
1123 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1124 return -1;
1125 }
1126 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1127 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1128 return -1;
1129 }
1130 tcp->baddr = regs.r_o7 + 8;
1131 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1132 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1133 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1134 return -1;
1135 }
1136
1137 /*
1138 * XXX - BRUTAL MODE ON
1139 * We cannot set a real BPT in the child, since it will not be
1140 * traced at the moment it will reach the trap and would probably
1141 * die with a core dump.
1142 * Thus, we are force our way in by taking out two instructions
1143 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1144 * generated by out PTRACE_ATTACH.
1145 * Of cause, if we evaporate ourselves in the middle of all this...
1146 */
1147 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1148 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1149 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1150 return -1;
1151 }
1152 tcp->flags |= TCB_BPTSET;
1153
1154#endif /* SPARC */
1155#endif /* SUNOS4 */
1156
1157 return 0;
1158}
1159
1160int
1161clearbpt(tcp)
1162struct tcb *tcp;
1163{
1164
1165#ifdef LINUX
1166#ifdef I386
1167 long eip;
1168#else /* !I386 */
1169#ifdef POWERPC
1170 long pc;
1171#else /* !POWERPC */
1172#ifdef M68K
1173 long pc;
1174#else /* !M68K */
1175#ifdef ALPHA
1176 long pc;
1177#endif /* ALPHA */
1178#endif /* !M68K */
1179#endif /* !POWERPC */
1180#endif /* !I386 */
1181
1182#ifdef SPARC
1183 /* Again, we borrow the SunOS breakpoint code. */
1184 if (!(tcp->flags & TCB_BPTSET)) {
1185 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1186 return -1;
1187 }
1188 errno = 0;
1189 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1190 if(errno) {
1191 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1192 return -1;
1193 }
1194 tcp->flags &= ~TCB_BPTSET;
1195#else /* !SPARC */
1196
1197 if (debug)
1198 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1199 if (!(tcp->flags & TCB_BPTSET)) {
1200 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1201 return -1;
1202 }
1203 errno = 0;
1204 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1205 if (errno) {
1206 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1207 return -1;
1208 }
1209 tcp->flags &= ~TCB_BPTSET;
1210
1211#ifdef I386
1212 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1213 return -1;
1214 if (eip != tcp->baddr) {
1215 /* The breakpoint has not been reached yet. */
1216 if (debug)
1217 fprintf(stderr,
1218 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1219 eip, tcp->baddr);
1220 return 0;
1221 }
1222#else /* !I386 */
1223#ifdef POWERPC
1224 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
1225 return -1;
1226 if (pc != tcp->baddr) {
1227 /* The breakpoint has not been reached yet. */
1228 if (debug)
1229 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1230 pc, tcp->baddr);
1231 return 0;
1232 }
1233#else /* !POWERPC */
1234#ifdef M68K
1235 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1236 return -1;
1237 if (pc != tcp->baddr) {
1238 /* The breakpoint has not been reached yet. */
1239 if (debug)
1240 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1241 pc, tcp->baddr);
1242 return 0;
1243 }
1244#else /* !M68K */
1245#ifdef ALPHA
1246 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1247 return -1;
1248 if (pc != tcp->baddr) {
1249 /* The breakpoint has not been reached yet. */
1250 if (debug)
1251 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1252 pc, tcp->baddr);
1253 return 0;
1254 }
1255#endif /* ALPHA */
1256#endif /* !M68K */
1257#endif /* !POWERPC */
1258#endif /* !I386 */
1259#endif /* !SPARC */
1260#endif /* LINUX */
1261
1262#ifdef SUNOS4
1263#ifdef SPARC
1264
1265#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001266 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267#endif
1268
1269 if (!(tcp->flags & TCB_BPTSET)) {
1270 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1271 return -1;
1272 }
1273 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1274 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1275 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1276 return -1;
1277 }
1278 tcp->flags &= ~TCB_BPTSET;
1279
1280#if !LOOPA
1281 /*
1282 * Since we don't have a single instruction breakpoint, we may have
1283 * to adjust the program counter after removing the our `breakpoint'.
1284 */
1285 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1286 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1287 return -1;
1288 }
1289 if ((regs.r_pc < tcp->baddr) ||
1290 (regs.r_pc > tcp->baddr + 4)) {
1291 /* The breakpoint has not been reached yet */
1292 if (debug)
1293 fprintf(stderr,
1294 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1295 regs.r_pc, tcp->parent->baddr);
1296 return 0;
1297 }
1298 if (regs.r_pc != tcp->baddr)
1299 if (debug)
1300 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1301 regs.r_pc, tcp->baddr);
1302
1303 regs.r_pc = tcp->baddr;
1304 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1305 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1306 return -1;
1307 }
1308#endif /* LOOPA */
1309#endif /* SPARC */
1310#endif /* SUNOS4 */
1311
1312 return 0;
1313}
1314
1315#endif /* !SVR4 */
1316
1317#ifdef SUNOS4
1318
1319static int
1320getex(pid, hdr)
1321int pid;
1322struct exec *hdr;
1323{
1324 int n;
1325
1326 for (n = 0; n < sizeof *hdr; n += 4) {
1327 long res;
1328 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1329 return -1;
1330 memcpy(((char *) hdr) + n, &res, 4);
1331 }
1332 if (debug) {
1333 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1334 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1335 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1336 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1337 }
1338 return 0;
1339}
1340
1341int
1342fixvfork(tcp)
1343struct tcb *tcp;
1344{
1345 int pid = tcp->pid;
1346 /*
1347 * Change `vfork' in a freshly exec'ed dynamically linked
1348 * executable's (internal) symbol table to plain old `fork'
1349 */
1350
1351 struct exec hdr;
1352 struct link_dynamic dyn;
1353 struct link_dynamic_2 ld;
1354 char *strtab, *cp;
1355
1356 if (getex(pid, &hdr) < 0)
1357 return -1;
1358 if (!hdr.a_dynamic)
1359 return -1;
1360
1361 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1362 fprintf(stderr, "Cannot read DYNAMIC\n");
1363 return -1;
1364 }
1365 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1366 fprintf(stderr, "Cannot read link_dynamic_2\n");
1367 return -1;
1368 }
1369 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1370 fprintf(stderr, "fixvfork: out of memory\n");
1371 return -1;
1372 }
1373 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1374 (int)ld.ld_symb_size, strtab) < 0)
1375 goto err;
1376
1377#if 0
1378 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1379 fprintf(stderr, "[symbol: %s]\n", cp);
1380 cp += strlen(cp)+1;
1381 }
1382 return 0;
1383#endif
1384 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1385 if (strcmp(cp, "_vfork") == 0) {
1386 if (debug)
1387 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1388 strcpy(cp, "_fork");
1389 break;
1390 }
1391 cp += strlen(cp)+1;
1392 }
1393 if (cp < strtab + ld.ld_symb_size)
1394 /*
1395 * Write entire symbol table back to avoid
1396 * memory alignment bugs in ptrace
1397 */
1398 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1399 (int)ld.ld_symb_size, strtab) < 0)
1400 goto err;
1401
1402 free(strtab);
1403 return 0;
1404
1405err:
1406 free(strtab);
1407 return -1;
1408}
1409
1410#endif /* SUNOS4 */