]> granicus.if.org Git - strace/blob - util.c
revert debugging code
[strace] / util.c
1 /*
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>
5  * 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>
9  * 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 <signal.h>
39 #include <sys/syscall.h>
40 #include <sys/user.h>
41 #include <sys/param.h>
42 #include <fcntl.h>
43 #if HAVE_SYS_UIO_H
44 #include <sys/uio.h>
45 #endif
46 #ifdef SUNOS4
47 #include <machine/reg.h>
48 #include <a.out.h>
49 #include <link.h>
50 #endif /* SUNOS4 */
51
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
54 #endif
55
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
58 # include <asm/rse.h>
59 #endif
60
61 #ifdef HAVE_SYS_REG_H
62 #include <sys/reg.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
65 #undef PTRACE_SYSCALL
66 # 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
72 #include <linux/ptrace.h>
73 # undef ia64_fpreg
74 # undef pt_all_user_regs
75 #endif
76
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
81 #if defined(LINUXSPARC)
82
83 # 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
90
91 #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
99 #if !defined(__GLIBC__)
100
101 #include <linux/unistd.h>
102
103 #define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104           type5,arg5,syscall) \
105 type 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" \
115 #if defined (SPARC64)
116                   "t 0x6d\n\t" \
117 #else
118                   "t 0x10\n\t" \
119 #endif
120                   "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"); \
129 if (__res>=0) \
130         return (type) __res; \
131 errno = -__res; \
132 return -1; \
133 }
134
135 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137 #define _ptrace
138
139 #endif
140
141 #endif
142
143 /* 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
151 void
152 tv_tv(tv, a, b)
153 struct timeval *tv;
154 int a;
155 int b;
156 {
157         tv->tv_sec = a;
158         tv->tv_usec = b;
159 }
160
161 int
162 tv_nz(a)
163 struct timeval *a;
164 {
165         return a->tv_sec || a->tv_usec;
166 }
167
168 int
169 tv_cmp(a, b)
170 struct timeval *a, *b;
171 {
172         if (a->tv_sec < b->tv_sec
173             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174                 return -1;
175         if (a->tv_sec > b->tv_sec
176             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177                 return 1;
178         return 0;
179 }
180
181 double
182 tv_float(tv)
183 struct timeval *tv;
184 {
185         return tv->tv_sec + tv->tv_usec/1000000.0;
186 }
187
188 void
189 tv_add(tv, a, b)
190 struct timeval *tv, *a, *b;
191 {
192         tv->tv_sec = a->tv_sec + b->tv_sec;
193         tv->tv_usec = a->tv_usec + b->tv_usec;
194         if (tv->tv_usec > 1000000) {
195                 tv->tv_sec++;
196                 tv->tv_usec -= 1000000;
197         }
198 }
199
200 void
201 tv_sub(tv, a, b)
202 struct timeval *tv, *a, *b;
203 {
204         tv->tv_sec = a->tv_sec - b->tv_sec;
205         tv->tv_usec = a->tv_usec - b->tv_usec;
206         if (((long) tv->tv_usec) < 0) {
207                 tv->tv_sec--;
208                 tv->tv_usec += 1000000;
209         }
210 }
211
212 void
213 tv_div(tv, a, n)
214 struct timeval *tv, *a;
215 int n;
216 {
217         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219         tv->tv_usec %= 1000000;
220 }
221
222 void
223 tv_mul(tv, a, n)
224 struct timeval *tv, *a;
225 int n;
226 {
227         tv->tv_usec = a->tv_usec * n;
228         tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229         tv->tv_usec %= 1000000;
230 }
231
232 char *
233 xlookup(xlat, val)
234 const struct xlat *xlat;
235 int val;
236 {
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  */
246 void
247 printxval(xlat, val, dflt)
248 const struct xlat *xlat;
249 int val;
250 const char *dflt;
251 {
252         char *str = xlookup(xlat, val);
253
254         if (str)
255                 tprintf("%s", str);
256         else
257                 tprintf("%#x /* %s */", val, dflt);
258 }
259
260 /*
261  * Interpret `xlat' as an array of flags
262  * print the entries whose bits are on in `flags'
263  * return # of flags printed.
264  */
265 int
266 addflags(xlat, flags)
267 const struct xlat *xlat;
268 int flags;
269 {
270         int n;
271
272         for (n = 0; xlat->str; xlat++) {
273                 if (xlat->val && (flags & xlat->val) == xlat->val) {
274                         tprintf("|%s", xlat->str);
275                         flags &= ~xlat->val;
276                         n++;
277                 }
278         }
279         if (flags) {
280                 tprintf("|%#x", flags);
281                 n++;
282         }
283         return n;
284 }
285
286 int
287 printflags(xlat, flags, dflt)
288 const struct xlat *xlat;
289 int flags;
290 const char *dflt;
291 {
292         int n;
293         char *sep;
294
295         if (flags == 0 && xlat->val == 0) {
296                 tprintf("%s", xlat->str);
297                 return 1;
298         }
299
300         sep = "";
301         for (n = 0; xlat->str; xlat++) {
302                 if (xlat->val && (flags & xlat->val) == xlat->val) {
303                         tprintf("%s%s", sep, xlat->str);
304                         flags &= ~xlat->val;
305                         sep = "|";
306                         n++;
307                 }
308         }
309
310         if (n) {
311                 if (flags) {
312                         tprintf("%s%#x", sep, flags);
313                         n++;
314                 }
315         } else {
316                 if (flags) {
317                         tprintf("%#x", flags);
318                         if (dflt)
319                                 tprintf(" /* %s */", dflt);
320                 } else {
321                         if (dflt)
322                                 tprintf("0");
323                 }
324         }
325
326         return n;
327 }
328
329 void
330 printnum(tcp, addr, fmt)
331 struct tcb *tcp;
332 long addr;
333 char *fmt;
334 {
335         long num;
336
337         if (!addr) {
338                 tprintf("NULL");
339                 return;
340         }
341         if (umove(tcp, addr, &num) < 0) {
342                 tprintf("%#lx", addr);
343                 return;
344         }
345         tprintf("[");
346         tprintf(fmt, num);
347         tprintf("]");
348 }
349
350 void
351 printuid(text, uid)
352 const char *text;
353 unsigned long uid;
354 {
355         tprintf("%s", text);
356         tprintf((uid == -1) ? "%ld" : "%lu", uid);
357 }
358
359 static char path[MAXPATHLEN + 1];
360
361 void
362 string_quote(str)
363 char *str;
364 {
365         char buf[2 * MAXPATHLEN + 1];
366         char *s;
367
368         if (!strpbrk(str, "\"\'\\")) {
369                 tprintf("\"%s\"", str);
370                 return;
371         }
372         for (s = buf; *str; str++) {
373                 switch (*str) {
374                 case '\"': case '\'': case '\\':
375                         *s++ = '\\'; *s++ = *str; break;
376                 default:
377                         *s++ = *str; break;
378                 }
379         }
380         *s = '\0';
381         tprintf("\"%s\"", buf);
382 }
383
384 void
385 printpath(tcp, addr)
386 struct tcb *tcp;
387 long addr;
388 {
389         if (addr == 0)
390                 tprintf("NULL");
391         else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
392                 tprintf("%#lx", addr);
393         else
394                 string_quote(path);
395         return;
396 }
397
398 void
399 printpathn(tcp, addr, n)
400 struct tcb *tcp;
401 long addr;
402 int n;
403 {
404         if (addr == 0)
405                 tprintf("NULL");
406         else    if (umovestr(tcp, addr, n, path) < 0)
407                 tprintf("%#lx", addr);
408         else {
409                 path[n] = '\0';
410                 string_quote(path);
411         }
412 }
413
414 void
415 printstr(tcp, addr, len)
416 struct tcb *tcp;
417 long addr;
418 int len;
419 {
420         static unsigned char *str = NULL;
421         static char *outstr;
422         int i, n, c, usehex;
423         char *s, *outend;
424
425         if (!addr) {
426                 tprintf("NULL");
427                 return;
428         }
429         if (!str) {
430                 if ((str = malloc(max_strlen)) == NULL
431                     || (outstr = malloc(2*max_strlen)) == NULL) {
432                         fprintf(stderr, "out of memory\n");
433                         tprintf("%#lx", addr);
434                         return;
435                 }
436         }
437         outend = outstr + max_strlen * 2 - 10;
438         if (len < 0) {
439                 n = max_strlen;
440                 if (umovestr(tcp, addr, n, (char *) str) < 0) {
441                         tprintf("%#lx", addr);
442                         return;
443                 }
444         }
445         else {
446                 n = MIN(len, max_strlen);
447                 if (umoven(tcp, addr, n, (char *) str) < 0) {
448                         tprintf("%#lx", addr);
449                         return;
450                 }
451         }
452
453         usehex = 0;
454         if (xflag > 1)
455                 usehex = 1;
456         else if (xflag) {
457                 for (i = 0; i < n; i++) {
458                         c = str[i];
459                         if (len < 0 && c == '\0')
460                                 break;
461                         if (!isprint(c) && !isspace(c)) {
462                                 usehex = 1;
463                                 break;
464                         }
465                 }
466         }
467
468         s = outstr;
469         *s++ = '\"';
470
471         if (usehex) {
472                 for (i = 0; i < n; i++) {
473                         c = str[i];
474                         if (len < 0 && c == '\0')
475                                 break;
476                         sprintf(s, "\\x%02x", c);
477                         s += 4;
478                         if (s > outend)
479                                 break;
480                 }
481         }
482         else {
483                 for (i = 0; i < n; i++) {
484                         c = str[i];
485                         if (len < 0 && c == '\0')
486                                 break;
487                         switch (c) {
488                         case '\"': case '\'': case '\\':
489                                 *s++ = '\\'; *s++ = c; break;
490                         case '\f':
491                                 *s++ = '\\'; *s++ = 'f'; break;
492                         case '\n':
493                                 *s++ = '\\'; *s++ = 'n'; break;
494                         case '\r':
495                                 *s++ = '\\'; *s++ = 'r'; break;
496                         case '\t':
497                                 *s++ = '\\'; *s++ = 't'; break;
498                         case '\v':
499                                 *s++ = '\\'; *s++ = 'v'; break;
500                         default:
501                                 if (isprint(c))
502                                         *s++ = c;
503                                 else if (i < n - 1 && isdigit(str[i + 1])) {
504                                         sprintf(s, "\\%03o", c);
505                                         s += 4;
506                                 }
507                                 else {
508                                         sprintf(s, "\\%o", c);
509                                         s += strlen(s);
510                                 }
511                                 break;
512                         }
513                         if (s > outend)
514                                 break;
515                 }
516         }
517
518         *s++ = '\"';
519         if (i < len || (len < 0 && (i == n || s > outend))) {
520                 *s++ = '.'; *s++ = '.'; *s++ = '.';
521         }
522         *s = '\0';
523         tprintf("%s", outstr);
524 }
525
526 #if HAVE_SYS_UIO_H
527 void
528 dumpiov(tcp, len, addr)
529 struct tcb * tcp;
530 int len;
531 long addr;
532 {
533         struct iovec *iov;
534         int i;
535         unsigned long size;
536
537         size = sizeof(*iov) * (unsigned long) len;
538         if (size / sizeof(*iov) != len
539             || (iov = (struct iovec *) malloc(size)) == NULL) {
540                 fprintf(stderr, "out of memory\n");
541                 return;
542         }
543         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
544                 for (i = 0; i < len; i++) {
545                         /* include the buffer number to make it easy to
546                          * match up the trace with the source */
547                         tprintf(" * %lu bytes in buffer %d\n",
548                                 (unsigned long)iov[i].iov_len, i);
549                         dumpstr(tcp, (long) iov[i].iov_base,
550                                 iov[i].iov_len);
551                 }
552         }
553         free((char *) iov);
554
555 }
556 #endif
557
558 void
559 dumpstr(tcp, addr, len)
560 struct tcb *tcp;
561 long addr;
562 int len;
563 {
564         static int strsize = -1;
565         static unsigned char *str;
566         static char outstr[80];
567         char *s;
568         int i, j;
569
570         if (strsize < len) {
571                 if (str)
572                         free(str);
573                 if ((str = malloc(len)) == NULL) {
574                         fprintf(stderr, "out of memory\n");
575                         return;
576                 }
577                 strsize = len;
578         }
579
580         if (umoven(tcp, addr, len, (char *) str) < 0)
581                 return;
582
583         for (i = 0; i < len; i += 16) {
584                 s = outstr;
585                 sprintf(s, " | %05x ", i);
586                 s += 9;
587                 for (j = 0; j < 16; j++) {
588                         if (j == 8)
589                                 *s++ = ' ';
590                         if (i + j < len) {
591                                 sprintf(s, " %02x", str[i + j]);
592                                 s += 3;
593                         }
594                         else {
595                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
596                         }
597                 }
598                 *s++ = ' '; *s++ = ' ';
599                 for (j = 0; j < 16; j++) {
600                         if (j == 8)
601                                 *s++ = ' ';
602                         if (i + j < len) {
603                                 if (isprint(str[i + j]))
604                                         *s++ = str[i + j];
605                                 else
606                                         *s++ = '.';
607                         }
608                         else
609                                 *s++ = ' ';
610                 }
611                 tprintf("%s |\n", outstr);
612         }
613 }
614
615 #define PAGMASK (~(PAGSIZ - 1))
616 /*
617  * move `len' bytes of data from process `pid'
618  * at address `addr' to our space at `laddr'
619  */
620 int
621 umoven(tcp, addr, len, laddr)
622 struct tcb *tcp;
623 long addr;
624 int len;
625 char *laddr;
626 {
627
628 #ifdef LINUX
629         int pid = tcp->pid;
630         int n, m;
631         int started = 0;
632         union {
633                 long val;
634                 char x[sizeof(long)];
635         } u;
636
637         if (addr & (sizeof(long) - 1)) {
638                 /* addr not a multiple of sizeof(long) */
639                 n = addr - (addr & -sizeof(long)); /* residue */
640                 addr &= -sizeof(long); /* residue */
641                 errno = 0;
642                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
643                 if (errno) {
644                         if (started && (errno==EPERM || errno==EIO)) {
645                                 /* Ran into 'end of memory' - stupid "printpath" */
646                                 return 0;
647                         }
648                         /* But if not started, we had a bogus address. */
649                         perror("ptrace: umoven");
650                         return -1;
651                 }
652                 started = 1;
653                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
654                 addr += sizeof(long), laddr += m, len -= m;
655         }
656         while (len) {
657                 errno = 0;
658                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
659                 if (errno) {
660                         if (started && (errno==EPERM || errno==EIO)) {
661                                 /* Ran into 'end of memory' - stupid "printpath" */
662                                 return 0;
663                         }
664                         if (addr != 0)
665                                 perror("ptrace: umoven");
666                         return -1;
667                 }
668                 started = 1;
669                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
670                 addr += sizeof(long), laddr += m, len -= m;
671         }
672 #endif /* LINUX */
673
674 #ifdef SUNOS4
675         int pid = tcp->pid;
676 #if 0
677         int n, m;
678         union {
679                 long val;
680                 char x[sizeof(long)];
681         } u;
682
683         if (addr & (sizeof(long) - 1)) {
684                 /* addr not a multiple of sizeof(long) */
685                 n = addr - (addr & -sizeof(long)); /* residue */
686                 addr &= -sizeof(long); /* residue */
687                 errno = 0;
688                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
689                 if (errno) {
690                         perror("umoven");
691                         return -1;
692                 }
693                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
694                 addr += sizeof(long), laddr += m, len -= m;
695         }
696         while (len) {
697                 errno = 0;
698                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
699                 if (errno) {
700                         perror("umoven");
701                         return -1;
702                 }
703                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
704                 addr += sizeof(long), laddr += m, len -= m;
705         }
706 #else /* !oldway */
707         int n;
708
709         while (len) {
710                 n = MIN(len, PAGSIZ);
711                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
712                 if (ptrace(PTRACE_READDATA, pid,
713                            (char *) addr, len, laddr) < 0) {
714                         perror("umoven: ptrace(PTRACE_READDATA, ...)");
715                         abort();
716                         return -1;
717                 }
718                 len -= n;
719                 addr += n;
720                 laddr += n;
721         }
722 #endif /* !oldway */
723 #endif /* SUNOS4 */
724
725 #ifdef USE_PROCFS
726 #ifdef HAVE_MP_PROCFS
727         int fd = tcp->pfd_as;
728 #else
729         int fd = tcp->pfd;
730 #endif
731         lseek(fd, addr, SEEK_SET);
732         if (read(fd, laddr, len) == -1)
733                 return -1;
734 #endif /* USE_PROCFS */
735
736         return 0;
737 }
738
739 /*
740  * like `umove' but make the additional effort of looking
741  * for a terminating zero byte.
742  */
743 int
744 umovestr(tcp, addr, len, laddr)
745 struct tcb *tcp;
746 long addr;
747 int len;
748 char *laddr;
749 {
750 #ifdef USE_PROCFS
751 #ifdef HAVE_MP_PROCFS
752         int fd = tcp->pfd_as;
753 #else
754         int fd = tcp->pfd;
755 #endif
756         /* Some systems (e.g. FreeBSD) can be upset if we read off the
757            end of valid memory,  avoid this by trying to read up
758            to page boundaries.  But we don't know what a page is (and
759            getpagesize(2) (if it exists) doesn't necessarily return
760            hardware page size).  Assume all pages >= 1024 (a-historical
761            I know) */
762
763         int page = 1024;        /* How to find this? */
764         int move = page - (addr & (page - 1));
765         int left = len;
766
767         lseek(fd, addr, SEEK_SET);
768
769         while (left) {
770                 if (move > left) move = left;
771                 if ((move = read(fd, laddr, move)) <= 0)
772                         return left != len ? 0 : -1;
773                 if (memchr (laddr, 0, move)) break;
774                 left -= move;
775                 laddr += move;
776                 addr += move;
777                 move = page;
778         }
779 #else /* !USE_PROCFS */
780         int started = 0;
781         int pid = tcp->pid;
782         int i, n, m;
783         union {
784                 long val;
785                 char x[sizeof(long)];
786         } u;
787
788         if (addr & (sizeof(long) - 1)) {
789                 /* addr not a multiple of sizeof(long) */
790                 n = addr - (addr & -sizeof(long)); /* residue */
791                 addr &= -sizeof(long); /* residue */
792                 errno = 0;
793                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
794                 if (errno) {
795                         if (started && (errno==EPERM || errno==EIO)) {
796                                 /* Ran into 'end of memory' - stupid "printpath" */
797                                 return 0;
798                         }
799                         perror("umovestr");
800                         return -1;
801                 }
802                 started = 1;
803                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
804                 while (n & (sizeof(long) - 1))
805                         if (u.x[n++] == '\0')
806                                 return 0;
807                 addr += sizeof(long), laddr += m, len -= m;
808         }
809         while (len) {
810                 errno = 0;
811                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
812                 if (errno) {
813                         if (started && (errno==EPERM || errno==EIO)) {
814                                 /* Ran into 'end of memory' - stupid "printpath" */
815                                 return 0;
816                         }
817                         perror("umovestr");
818                         return -1;
819                 }
820                 started = 1;
821                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
822                 for (i = 0; i < sizeof(long); i++)
823                         if (u.x[i] == '\0')
824                                 return 0;
825
826                 addr += sizeof(long), laddr += m, len -= m;
827         }
828 #endif /* !USE_PROCFS */
829         return 0;
830 }
831
832 #ifdef LINUX
833 #if !defined (SPARC) && !defined(SPARC64)
834 #define PTRACE_WRITETEXT        101
835 #define PTRACE_WRITEDATA        102
836 #endif /* !SPARC && !SPARC64 */
837 #endif /* LINUX */
838
839 #ifdef SUNOS4
840
841 static int
842 uload(cmd, pid, addr, len, laddr)
843 int cmd;
844 int pid;
845 long addr;
846 int len;
847 char *laddr;
848 {
849 #if 0
850         int n;
851
852         while (len) {
853                 n = MIN(len, PAGSIZ);
854                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
855                 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
856                         perror("uload: ptrace(PTRACE_WRITE, ...)");
857                         return -1;
858                 }
859                 len -= n;
860                 addr += n;
861                 laddr += n;
862         }
863 #else
864         int peek, poke;
865         int n, m;
866         union {
867                 long val;
868                 char x[sizeof(long)];
869         } u;
870
871         if (cmd == PTRACE_WRITETEXT) {
872                 peek = PTRACE_PEEKTEXT;
873                 poke = PTRACE_POKETEXT;
874         }
875         else {
876                 peek = PTRACE_PEEKDATA;
877                 poke = PTRACE_POKEDATA;
878         }
879         if (addr & (sizeof(long) - 1)) {
880                 /* addr not a multiple of sizeof(long) */
881                 n = addr - (addr & -sizeof(long)); /* residue */
882                 addr &= -sizeof(long);
883                 errno = 0;
884                 u.val = ptrace(peek, pid, (char *) addr, 0);
885                 if (errno) {
886                         perror("uload: POKE");
887                         return -1;
888                 }
889                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
890                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
891                         perror("uload: POKE");
892                         return -1;
893                 }
894                 addr += sizeof(long), laddr += m, len -= m;
895         }
896         while (len) {
897                 if (len < sizeof(long))
898                         u.val = ptrace(peek, pid, (char *) addr, 0);
899                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
900                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
901                         perror("uload: POKE");
902                         return -1;
903                 }
904                 addr += sizeof(long), laddr += m, len -= m;
905         }
906 #endif
907         return 0;
908 }
909
910 int
911 tload(pid, addr, len, laddr)
912 int pid;
913 int addr, len;
914 char *laddr;
915 {
916         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
917 }
918
919 int
920 dload(pid, addr, len, laddr)
921 int pid;
922 int addr;
923 int len;
924 char *laddr;
925 {
926         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
927 }
928
929 #endif /* SUNOS4 */
930
931 #ifndef USE_PROCFS
932
933 int
934 upeek(pid, off, res)
935 int pid;
936 long off;
937 long *res;
938 {
939         long val;
940
941 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
942         {
943                 static int is_sun4m = -1;
944                 struct utsname name;
945
946                 /* Round up the usual suspects. */
947                 if (is_sun4m == -1) {
948                         if (uname(&name) < 0) {
949                                 perror("upeek: uname?");
950                                 exit(1);
951                         }
952                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
953                         if (is_sun4m) {
954                                 extern const struct xlat struct_user_offsets[];
955                                 const struct xlat *x;
956
957                                 for (x = struct_user_offsets; x->str; x++)
958                                         x->val += 1024;
959                         }
960                 }
961                 if (is_sun4m)
962                         off += 1024;
963         }
964 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
965         errno = 0;
966         val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
967         if (val == -1 && errno) {
968                 char buf[60];
969                 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
970                 perror(buf);
971                 return -1;
972         }
973         *res = val;
974         return 0;
975 }
976
977 #endif /* !USE_PROCFS */
978
979 long
980 getpc(tcp)
981 struct tcb *tcp;
982 {
983
984 #ifdef LINUX
985         long pc;
986 #if defined(I386)
987         if (upeek(tcp->pid, 4*EIP, &pc) < 0)
988                 return -1;
989 #elif defined(X86_64)
990         if (upeek(tcp->pid, 8*RIP, &pc) < 0)
991                 return -1;
992 #elif defined(IA64)
993         if (upeek(tcp->pid, PT_B0, &pc) < 0)
994                 return -1;
995 #elif defined(ARM)
996         if (upeek(tcp->pid, 4*15, &pc) < 0)
997                 return -1;
998 #elif defined(POWERPC)
999         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1000                 return -1;
1001 #elif defined(M68k)
1002         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1003                 return -1;
1004 #elif defined(ALPHA)
1005         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1006                 return -1;
1007 #elif defined(MIPS)
1008         if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1009                 return -1;
1010 #elif defined(SPARC) || defined(SPARC64)
1011         struct regs regs;
1012         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1013                 return -1;
1014         pc = regs.r_pc;
1015 #elif defined(S390) || defined(S390X)
1016         if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1017                 return -1;
1018 #elif defined(HPPA)
1019         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1020                 return -1;
1021 #elif defined(SH)
1022        if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1023                return -1;
1024 #elif defined(SH64)
1025        if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1026                return -1;
1027 #endif
1028         return pc;
1029 #endif /* LINUX */
1030
1031 #ifdef SUNOS4
1032         /*
1033          * Return current program counter for `pid'
1034          * Assumes PC is never 0xffffffff
1035          */
1036         struct regs regs;
1037
1038         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1039                 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1040                 return -1;
1041         }
1042         return regs.r_pc;
1043 #endif /* SUNOS4 */
1044
1045 #ifdef SVR4
1046         /* XXX */
1047         return 0;
1048 #endif /* SVR4 */
1049
1050 #ifdef FREEBSD
1051         struct reg regs;
1052         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1053         return regs.r_eip;
1054 #endif /* FREEBSD */
1055 }
1056
1057 void
1058 printcall(tcp)
1059 struct tcb *tcp;
1060 {
1061 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1062                            sizeof(long) == 8 ? "[????????????????] " : \
1063                            NULL /* crash */)
1064
1065 #ifdef LINUX
1066 #ifdef I386
1067         long eip;
1068
1069         if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1070                 PRINTBADPC;
1071                 return;
1072         }
1073         tprintf("[%08lx] ", eip);
1074
1075 #elif defined(S390) || defined(S390X)
1076          long psw;
1077          if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1078                  PRINTBADPC;
1079                  return;
1080          }
1081 #ifdef S390
1082          tprintf("[%08lx] ", psw);
1083 #elif S390X
1084        tprintf("[%16lx] ", psw);
1085 #endif
1086
1087 #elif defined(X86_64)
1088         long rip;
1089
1090         if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1091                 PRINTBADPC;
1092                 return;
1093         }
1094         tprintf("[%16lx] ", rip);
1095 #elif defined(IA64)
1096         long ip;
1097
1098         if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1099                 PRINTBADPC;
1100                 return;
1101         }
1102         tprintf("[%08lx] ", ip);
1103 #elif defined(POWERPC)
1104         long pc;
1105
1106         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1107                 tprintf ("[????????] ");
1108                 return;
1109         }
1110         tprintf("[%08lx] ", pc);
1111 #elif defined(M68k)
1112         long pc;
1113
1114         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1115                 tprintf ("[????????] ");
1116                 return;
1117         }
1118         tprintf("[%08lx] ", pc);
1119 #elif defined(ALPHA)
1120         long pc;
1121
1122         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1123                 tprintf ("[????????????????] ");
1124                 return;
1125         }
1126         tprintf("[%08lx] ", pc);
1127 #elif defined(SPARC) || defined(SPARC64)
1128         struct regs regs;
1129         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1130                 PRINTBADPC;
1131                 return;
1132         }
1133         tprintf("[%08lx] ", regs.r_pc);
1134 #elif defined(HPPA)
1135         long pc;
1136
1137         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1138                 tprintf ("[????????] ");
1139                 return;
1140         }
1141         tprintf("[%08lx] ", pc);
1142 #elif defined(MIPS)
1143         long pc;
1144
1145         if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1146                 tprintf ("[????????] ");
1147                 return;
1148         }
1149         tprintf("[%08lx] ", pc);
1150 #elif defined(SH)
1151        long pc;
1152
1153        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1154                tprintf ("[????????] ");
1155                return;
1156        }
1157        tprintf("[%08lx] ", pc);
1158 #elif defined(SH64)
1159         long pc;
1160
1161         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1162                 tprintf ("[????????????????] ");
1163                 return;
1164         }
1165         tprintf("[%08lx] ", pc);
1166 #elif defined(ARM)
1167         long pc;
1168
1169         if (upeek(tcp->pid, 4*15, &pc) < 0) {
1170                 PRINTBADPC;
1171                 return;
1172         }
1173         tprintf("[%08lx] ", pc);
1174 #endif /* !architecture */
1175 #endif /* LINUX */
1176
1177 #ifdef SUNOS4
1178         struct regs regs;
1179
1180         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1181                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1182                 PRINTBADPC;
1183                 return;
1184         }
1185         tprintf("[%08x] ", regs.r_o7);
1186 #endif /* SUNOS4 */
1187
1188 #ifdef SVR4
1189         /* XXX */
1190         PRINTBADPC;
1191 #endif
1192
1193 #ifdef FREEBSD
1194         struct reg regs;
1195         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1196         tprintf("[%08x] ", regs.r_eip);
1197 #endif /* FREEBSD */
1198 }
1199
1200 #ifndef USE_PROCFS
1201
1202 #if defined LINUX
1203
1204 #include <sys/syscall.h>
1205 #ifndef CLONE_PTRACE
1206 # define CLONE_PTRACE    0x00002000
1207 #endif
1208 #ifndef CLONE_STOPPED
1209 # define CLONE_STOPPED   0x02000000
1210 #endif
1211
1212 #ifdef IA64
1213
1214 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1215    subsystem has them for x86... */
1216 #define SYS_fork        2
1217 #define SYS_vfork       190
1218
1219 typedef unsigned long *arg_setup_state;
1220
1221 static int
1222 arg_setup(struct tcb *tcp, arg_setup_state *state)
1223 {
1224         unsigned long *bsp, cfm, sof, sol;
1225
1226         if (ia32)
1227                 return 0;
1228
1229         if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1230                 return -1;
1231         if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1232                 return -1;
1233
1234         sof = (cfm >> 0) & 0x7f;
1235         sol = (cfm >> 7) & 0x7f;
1236         bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1237
1238         *state = bsp;
1239         return 0;
1240 }
1241
1242 # define arg_finish_change(tcp, state)  0
1243
1244 #ifdef SYS_fork
1245 static int
1246 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1247 {
1248         int ret;
1249
1250         if (ia32)
1251                 ret = upeek (tcp->pid, PT_R11, valp);
1252         else
1253                 ret = umoven (tcp,
1254                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1255                               sizeof(long), (void *) valp);
1256         return ret;
1257 }
1258
1259 static int
1260 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1261 {
1262         int ret;
1263
1264         if (ia32)
1265                 ret = upeek (tcp->pid, PT_R9, valp);
1266         else
1267                 ret = umoven (tcp,
1268                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1269                               sizeof(long), (void *) valp);
1270         return ret;
1271 }
1272 #endif
1273
1274 static int
1275 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1276 {
1277         int req = PTRACE_POKEDATA;
1278         void *ap;
1279
1280         if (ia32) {
1281                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1282                 req = PTRACE_POKEUSER;
1283         } else
1284                 ap = ia64_rse_skip_regs(*state, 0);
1285         errno = 0;
1286         ptrace(req, tcp->pid, ap, val);
1287         return errno ? -1 : 0;
1288 }
1289
1290 static int
1291 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1292 {
1293         int req = PTRACE_POKEDATA;
1294         void *ap;
1295
1296         if (ia32) {
1297                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1298                 req = PTRACE_POKEUSER;
1299         } else
1300                 ap = ia64_rse_skip_regs(*state, 1);
1301         errno = 0;
1302         ptrace(req, tcp->pid, ap, val);
1303         return errno ? -1 : 0;
1304 }
1305
1306 #elif defined (SPARC) || defined (SPARC64)
1307
1308 typedef struct regs arg_setup_state;
1309
1310 # define arg_setup(tcp, state) \
1311   (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1312 # define arg_finish_change(tcp, state) \
1313   (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1314
1315 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1316 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1317 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1318 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1319 # define restore_arg0(tcp, state, val) 0
1320
1321 #else
1322
1323 # if defined S390 || defined S390X
1324 /* Note: this is only true for the `clone' system call, which handles
1325    arguments specially.  We could as well say that its first two arguments
1326    are swapped relative to other architectures, but that would just be
1327    another #ifdef in the calls.  */
1328 #  define arg0_offset   PT_GPR3
1329 #  define arg1_offset   PT_ORIGGPR2
1330 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1331 #  define restore_arg1(tcp, state, val) ((void) (state), 0)
1332 #  define arg0_index    1
1333 #  define arg1_index    0
1334 # elif defined (ALPHA) || defined (MIPS)
1335 #  define arg0_offset   REG_A0
1336 #  define arg1_offset   (REG_A0+1)
1337 # elif defined (POWERPC)
1338 #  define arg0_offset   (sizeof(unsigned long)*PT_R3)
1339 #  define arg1_offset   (sizeof(unsigned long)*PT_R4)
1340 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1341 # elif defined (HPPA)
1342 #  define arg0_offset    PT_GR26
1343 #  define arg1_offset    (PT_GR26-4)
1344 # elif defined (X86_64)
1345 #  define arg0_offset   ((long)(8*(current_personality ? RBX : RDI)))
1346 #  define arg1_offset   ((long)(8*(current_personality ? RCX : RSI)))
1347 # elif defined (SH)
1348 #  define arg0_offset   (4*(REG_REG0+4))
1349 #  define arg1_offset   (4*(REG_REG0+5))
1350 # elif defined (SH64)
1351    /* ABI defines arg0 & 1 in r2 & r3 */
1352 #  define arg0_offset   (REG_OFFSET+16)
1353 #  define arg1_offset   (REG_OFFSET+24)
1354 #  define restore_arg0(tcp, state, val) 0
1355 # else
1356 #  define arg0_offset   0
1357 #  define arg1_offset   4
1358 #  if defined ARM
1359 #   define restore_arg0(tcp, state, val) 0
1360 #  endif
1361 # endif
1362
1363 typedef int arg_setup_state;
1364
1365 # define arg_setup(tcp, state) (0)
1366 # define arg_finish_change(tcp, state)  0
1367 # define get_arg0(tcp, cookie, valp) \
1368   (upeek ((tcp)->pid, arg0_offset, (valp)))
1369 # define get_arg1(tcp, cookie, valp) \
1370   (upeek ((tcp)->pid, arg1_offset, (valp)))
1371
1372 static int
1373 set_arg0 (struct tcb *tcp, void *cookie, long val)
1374 {
1375         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1376 }
1377
1378 static int
1379 set_arg1 (struct tcb *tcp, void *cookie, long val)
1380 {
1381         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1382 }
1383
1384 #endif
1385
1386 #ifndef restore_arg0
1387 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1388 #endif
1389 #ifndef restore_arg1
1390 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1391 #endif
1392
1393 #ifndef arg0_index
1394 # define arg0_index 0
1395 # define arg1_index 1
1396 #endif
1397
1398 int
1399 setbpt(tcp)
1400 struct tcb *tcp;
1401 {
1402         extern int change_syscall(struct tcb *, int);
1403         arg_setup_state state;
1404
1405         if (tcp->flags & TCB_BPTSET) {
1406                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1407                 return -1;
1408         }
1409
1410         switch (known_scno(tcp)) {
1411 #ifdef SYS_vfork
1412         case SYS_vfork:
1413 #endif
1414 #ifdef SYS_fork
1415         case SYS_fork:
1416 #endif
1417 #if defined SYS_fork || defined SYS_vfork
1418                 if (arg_setup (tcp, &state) < 0
1419                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1420                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1421                     || change_syscall(tcp, SYS_clone) < 0
1422                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1423                     || set_arg1 (tcp, &state, 0) < 0
1424                     || arg_finish_change (tcp, &state) < 0)
1425                         return -1;
1426                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1427                 tcp->u_arg[arg1_index] = 0;
1428                 tcp->flags |= TCB_BPTSET;
1429                 return 0;
1430 #endif
1431
1432         case SYS_clone:
1433 #ifdef SYS_clone2
1434         case SYS_clone2:
1435 #endif
1436                 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1437                     && (arg_setup (tcp, &state) < 0
1438                         || set_arg0 (tcp, &state,
1439                                      tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1440                         || arg_finish_change (tcp, &state) < 0))
1441                         return -1;
1442                 tcp->flags |= TCB_BPTSET;
1443                 tcp->inst[0] = tcp->u_arg[arg0_index];
1444                 tcp->inst[1] = tcp->u_arg[arg1_index];
1445                 return 0;
1446
1447         default:
1448                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1449                         tcp->scno, tcp->pid);
1450                 break;
1451         }
1452
1453         return -1;
1454 }
1455
1456 int
1457 clearbpt(tcp)
1458 struct tcb *tcp;
1459 {
1460         arg_setup_state state;
1461         if (arg_setup (tcp, &state) < 0
1462             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1463             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1464             || arg_finish_change (tcp, &state))
1465                 return -1;
1466         tcp->flags &= ~TCB_BPTSET;
1467         return 0;
1468 }
1469
1470 #else
1471
1472 int
1473 setbpt(tcp)
1474 struct tcb *tcp;
1475 {
1476
1477 #ifdef LINUX
1478 #if defined (SPARC) || defined (SPARC64)
1479         /* We simply use the SunOS breakpoint code. */
1480
1481         struct regs regs;
1482         unsigned long inst;
1483 #define LOOPA   0x30800000      /* ba,a 0 */
1484
1485         if (tcp->flags & TCB_BPTSET) {
1486                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1487                 return -1;
1488         }
1489         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1490                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1491                 return -1;
1492         }
1493         tcp->baddr = regs.r_o7 + 8;
1494         errno = 0;
1495         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1496         if(errno) {
1497                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1498                 return -1;
1499         }
1500
1501         /*
1502          * XXX - BRUTAL MODE ON
1503          * We cannot set a real BPT in the child, since it will not be
1504          * traced at the moment it will reach the trap and would probably
1505          * die with a core dump.
1506          * Thus, we are force our way in by taking out two instructions
1507          * and insert an eternal loop instead, in expectance of the SIGSTOP
1508          * generated by out PTRACE_ATTACH.
1509          * Of cause, if we evaporate ourselves in the middle of all this...
1510          */
1511         errno = 0;
1512         inst = LOOPA;
1513 #if defined (SPARC64)
1514         inst <<= 32;
1515         inst |= (tcp->inst[0] & 0xffffffffUL);
1516 #endif
1517         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1518         if(errno) {
1519                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1520                 return -1;
1521         }
1522         tcp->flags |= TCB_BPTSET;
1523
1524 #else /* !SPARC && !SPARC64 */
1525 #ifdef IA64
1526         if (ia32) {
1527 #               define LOOP     0x0000feeb
1528                 if (tcp->flags & TCB_BPTSET) {
1529                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1530                                 tcp->pid);
1531                         return -1;
1532                 }
1533                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1534                         return -1;
1535                 if (debug)
1536                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1537                                 tcp->pid, tcp->baddr);
1538                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1539                                       (char *) tcp->baddr, 0);
1540                 if (errno) {
1541                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1542                         return -1;
1543                 }
1544                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1545                 if (errno) {
1546                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1547                         return -1;
1548                 }
1549                 tcp->flags |= TCB_BPTSET;
1550         } else {
1551                 /*
1552                  * Our strategy here is to replace the bundle that
1553                  * contained the clone() syscall with a bundle of the
1554                  * form:
1555                  *
1556                  *      { 1: br 1b; br 1b; br 1b }
1557                  *
1558                  * This ensures that the newly forked child will loop
1559                  * endlessly until we've got a chance to attach to it.
1560                  */
1561 #               define LOOP0    0x0000100000000017
1562 #               define LOOP1    0x4000000000200000
1563                 unsigned long addr, ipsr;
1564                 pid_t pid;
1565
1566                 pid = tcp->pid;
1567                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1568                         return -1;
1569                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1570                         return -1;
1571                 /* store "ri" in low two bits */
1572                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1573
1574                 errno = 0;
1575                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1576                                       0);
1577                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1578                                       0);
1579                 if (errno) {
1580                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1581                         return -1;
1582                 }
1583
1584                 errno = 0;
1585                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1586                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1587                 if (errno) {
1588                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1589                         return -1;
1590                 }
1591                 tcp->flags |= TCB_BPTSET;
1592         }
1593 #else /* !IA64 */
1594
1595 #if defined (I386) || defined(X86_64)
1596 #define LOOP    0x0000feeb
1597 #elif defined (M68K)
1598 #define LOOP    0x60fe0000
1599 #elif defined (ALPHA)
1600 #define LOOP    0xc3ffffff
1601 #elif defined (POWERPC)
1602 #define LOOP    0x48000000
1603 #elif defined(ARM)
1604 #define LOOP    0xEAFFFFFE
1605 #elif defined(MIPS)
1606 #define LOOP    0x1000ffff
1607 #elif defined(S390)
1608 #define LOOP    0xa7f40000      /* BRC 15,0 */
1609 #elif defined(S390X)
1610 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1611 #elif defined(HPPA)
1612 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1613 #elif defined(SH)
1614 #ifdef __LITTLE_ENDIAN__
1615 #define LOOP   0x0000affe
1616 #else
1617 #define LOOP   0xfeaf0000
1618 #endif
1619 #else
1620 #error unknown architecture
1621 #endif
1622
1623         if (tcp->flags & TCB_BPTSET) {
1624                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1625                 return -1;
1626         }
1627 #if defined (I386)
1628         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1629                 return -1;
1630 #elif defined (X86_64)
1631         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1632                 return -1;
1633 #elif defined (M68K)
1634         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1635           return -1;
1636 #elif defined (ALPHA)
1637         return -1;
1638 #elif defined (ARM)
1639         return -1;
1640 #elif defined (MIPS)
1641         return -1;              /* FIXME: I do not know what i do - Flo */
1642 #elif defined (POWERPC)
1643         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1644                 return -1;
1645 #elif defined(S390) || defined(S390X)
1646         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1647                 return -1;
1648 #elif defined(HPPA)
1649         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1650                 return -1;
1651         tcp->baddr &= ~0x03;
1652 #elif defined(SH)
1653        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1654                return -1;
1655 #else
1656 #error unknown architecture
1657 #endif
1658         if (debug)
1659                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1660         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1661         if (errno) {
1662                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1663                 return -1;
1664         }
1665         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1666         if (errno) {
1667                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1668                 return -1;
1669         }
1670         tcp->flags |= TCB_BPTSET;
1671
1672 #endif /* !IA64 */
1673 #endif /* SPARC || SPARC64 */
1674 #endif /* LINUX */
1675
1676 #ifdef SUNOS4
1677 #ifdef SPARC    /* This code is slightly sparc specific */
1678
1679         struct regs regs;
1680 #define BPT     0x91d02001      /* ta   1 */
1681 #define LOOP    0x10800000      /* ba   0 */
1682 #define LOOPA   0x30800000      /* ba,a 0 */
1683 #define NOP     0x01000000
1684 #if LOOPA
1685         static int loopdeloop[1] = {LOOPA};
1686 #else
1687         static int loopdeloop[2] = {LOOP, NOP};
1688 #endif
1689
1690         if (tcp->flags & TCB_BPTSET) {
1691                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1692                 return -1;
1693         }
1694         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1695                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1696                 return -1;
1697         }
1698         tcp->baddr = regs.r_o7 + 8;
1699         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1700                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1701                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1702                 return -1;
1703         }
1704
1705         /*
1706          * XXX - BRUTAL MODE ON
1707          * We cannot set a real BPT in the child, since it will not be
1708          * traced at the moment it will reach the trap and would probably
1709          * die with a core dump.
1710          * Thus, we are force our way in by taking out two instructions
1711          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1712          * generated by out PTRACE_ATTACH.
1713          * Of cause, if we evaporate ourselves in the middle of all this...
1714          */
1715         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1716                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1717                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1718                 return -1;
1719         }
1720         tcp->flags |= TCB_BPTSET;
1721
1722 #endif /* SPARC */
1723 #endif /* SUNOS4 */
1724
1725         return 0;
1726 }
1727
1728 int
1729 clearbpt(tcp)
1730 struct tcb *tcp;
1731 {
1732
1733 #ifdef LINUX
1734 #if defined(I386) || defined(X86_64)
1735         long eip;
1736 #elif defined(POWERPC)
1737         long pc;
1738 #elif defined(M68K)
1739         long pc;
1740 #elif defined(ALPHA)
1741         long pc;
1742 #elif defined(HPPA)
1743         long iaoq;
1744 #elif defined(SH)
1745        long pc;
1746 #endif /* architecture */
1747
1748 #if defined (SPARC) || defined (SPARC64)
1749         /* Again, we borrow the SunOS breakpoint code. */
1750         if (!(tcp->flags & TCB_BPTSET)) {
1751                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1752                 return -1;
1753         }
1754         errno = 0;
1755         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1756         if(errno) {
1757                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1758                 return -1;
1759         }
1760         tcp->flags &= ~TCB_BPTSET;
1761 #elif defined(IA64)
1762         if (ia32) {
1763                 unsigned long addr;
1764
1765                 if (debug)
1766                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1767                 if (!(tcp->flags & TCB_BPTSET)) {
1768                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1769                         return -1;
1770                 }
1771                 errno = 0;
1772                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1773                 if (errno) {
1774                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1775                         return -1;
1776                 }
1777                 tcp->flags &= ~TCB_BPTSET;
1778
1779                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1780                         return -1;
1781                 if (addr != tcp->baddr) {
1782                         /* The breakpoint has not been reached yet.  */
1783                         if (debug)
1784                                 fprintf(stderr,
1785                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1786                                                 addr, tcp->baddr);
1787                         return 0;
1788                 }
1789         } else {
1790                 unsigned long addr, ipsr;
1791                 pid_t pid;
1792
1793                 pid = tcp->pid;
1794
1795                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1796                         return -1;
1797                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1798                         return -1;
1799
1800                 /* restore original bundle: */
1801                 errno = 0;
1802                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1803                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1804                 if (errno) {
1805                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1806                         return -1;
1807                 }
1808
1809                 /* restore original "ri" in ipsr: */
1810                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1811                 errno = 0;
1812                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1813                 if (errno) {
1814                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1815                         return -1;
1816                 }
1817
1818                 tcp->flags &= ~TCB_BPTSET;
1819
1820                 if (addr != (tcp->baddr & ~0x3)) {
1821                         /* the breakpoint has not been reached yet.  */
1822                         if (debug)
1823                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1824                                         addr, tcp->baddr);
1825                         return 0;
1826                 }
1827         }
1828 #else /* !IA64  && !SPARC && !SPARC64 */
1829
1830         if (debug)
1831                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1832         if (!(tcp->flags & TCB_BPTSET)) {
1833                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1834                 return -1;
1835         }
1836         errno = 0;
1837         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1838         if (errno) {
1839                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1840                 return -1;
1841         }
1842         tcp->flags &= ~TCB_BPTSET;
1843
1844 #ifdef I386
1845         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1846                 return -1;
1847         if (eip != tcp->baddr) {
1848                 /* The breakpoint has not been reached yet.  */
1849                 if (debug)
1850                         fprintf(stderr,
1851                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1852                                         eip, tcp->baddr);
1853                 return 0;
1854         }
1855 #elif defined(X86_64)
1856         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1857                 return -1;
1858         if (eip != tcp->baddr) {
1859                 /* The breakpoint has not been reached yet.  */
1860                 if (debug)
1861                         fprintf(stderr,
1862                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1863                                         eip, tcp->baddr);
1864                 return 0;
1865         }
1866 #elif defined(POWERPC)
1867         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1868                 return -1;
1869         if (pc != tcp->baddr) {
1870                 /* The breakpoint has not been reached yet.  */
1871                 if (debug)
1872                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1873                                 pc, tcp->baddr);
1874                 return 0;
1875         }
1876 #elif defined(M68K)
1877         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1878                 return -1;
1879         if (pc != tcp->baddr) {
1880                 /* The breakpoint has not been reached yet.  */
1881                 if (debug)
1882                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1883                                 pc, tcp->baddr);
1884                 return 0;
1885         }
1886 #elif defined(ALPHA)
1887         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1888                 return -1;
1889         if (pc != tcp->baddr) {
1890                 /* The breakpoint has not been reached yet.  */
1891                 if (debug)
1892                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1893                                 pc, tcp->baddr);
1894                 return 0;
1895         }
1896 #elif defined(HPPA)
1897         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1898                 return -1;
1899         iaoq &= ~0x03;
1900         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1901                 /* The breakpoint has not been reached yet.  */
1902                 if (debug)
1903                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1904                                 iaoq, tcp->baddr);
1905                 return 0;
1906         }
1907         iaoq = tcp->baddr | 3;
1908         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1909          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1910          * has no significant effect.
1911          */
1912         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1913         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1914 #elif defined(SH)
1915        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1916                return -1;
1917         if (pc != tcp->baddr) {
1918                 /* The breakpoint has not been reached yet.  */
1919                 if (debug)
1920                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1921                                 pc, tcp->baddr);
1922                 return 0;
1923         }
1924
1925 #endif /* arch */
1926 #endif /* !SPARC && !SPARC64 && !IA64 */
1927 #endif /* LINUX */
1928
1929 #ifdef SUNOS4
1930 #ifdef SPARC
1931
1932 #if !LOOPA
1933         struct regs regs;
1934 #endif
1935
1936         if (!(tcp->flags & TCB_BPTSET)) {
1937                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1938                 return -1;
1939         }
1940         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1941                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1942                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1943                 return -1;
1944         }
1945         tcp->flags &= ~TCB_BPTSET;
1946
1947 #if !LOOPA
1948         /*
1949          * Since we don't have a single instruction breakpoint, we may have
1950          * to adjust the program counter after removing the our `breakpoint'.
1951          */
1952         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1953                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1954                 return -1;
1955         }
1956         if ((regs.r_pc < tcp->baddr) ||
1957                                 (regs.r_pc > tcp->baddr + 4)) {
1958                 /* The breakpoint has not been reached yet */
1959                 if (debug)
1960                         fprintf(stderr,
1961                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1962                                         regs.r_pc, tcp->parent->baddr);
1963                 return 0;
1964         }
1965         if (regs.r_pc != tcp->baddr)
1966                 if (debug)
1967                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1968                                 regs.r_pc, tcp->baddr);
1969
1970         regs.r_pc = tcp->baddr;
1971         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1972                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1973                 return -1;
1974         }
1975 #endif /* LOOPA */
1976 #endif /* SPARC */
1977 #endif /* SUNOS4 */
1978
1979         return 0;
1980 }
1981
1982 #endif
1983
1984 #endif /* !USE_PROCFS */
1985
1986 #ifdef SUNOS4
1987
1988 static int
1989 getex(pid, hdr)
1990 int pid;
1991 struct exec *hdr;
1992 {
1993         int n;
1994
1995         for (n = 0; n < sizeof *hdr; n += 4) {
1996                 long res;
1997                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1998                         return -1;
1999                 memcpy(((char *) hdr) + n, &res, 4);
2000         }
2001         if (debug) {
2002                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2003                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2004                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2005                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2006         }
2007         return 0;
2008 }
2009
2010 int
2011 fixvfork(tcp)
2012 struct tcb *tcp;
2013 {
2014         int pid = tcp->pid;
2015         /*
2016          * Change `vfork' in a freshly exec'ed dynamically linked
2017          * executable's (internal) symbol table to plain old `fork'
2018          */
2019
2020         struct exec hdr;
2021         struct link_dynamic dyn;
2022         struct link_dynamic_2 ld;
2023         char *strtab, *cp;
2024
2025         if (getex(pid, &hdr) < 0)
2026                 return -1;
2027         if (!hdr.a_dynamic)
2028                 return -1;
2029
2030         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2031                 fprintf(stderr, "Cannot read DYNAMIC\n");
2032                 return -1;
2033         }
2034         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2035                 fprintf(stderr, "Cannot read link_dynamic_2\n");
2036                 return -1;
2037         }
2038         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2039                 fprintf(stderr, "out of memory\n");
2040                 return -1;
2041         }
2042         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2043                                         (int)ld.ld_symb_size, strtab) < 0)
2044                 goto err;
2045
2046 #if 0
2047         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2048                 fprintf(stderr, "[symbol: %s]\n", cp);
2049                 cp += strlen(cp)+1;
2050         }
2051         return 0;
2052 #endif
2053         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2054                 if (strcmp(cp, "_vfork") == 0) {
2055                         if (debug)
2056                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2057                         strcpy(cp, "_fork");
2058                         break;
2059                 }
2060                 cp += strlen(cp)+1;
2061         }
2062         if (cp < strtab + ld.ld_symb_size)
2063                 /*
2064                  * Write entire symbol table back to avoid
2065                  * memory alignment bugs in ptrace
2066                  */
2067                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2068                                         (int)ld.ld_symb_size, strtab) < 0)
2069                         goto err;
2070
2071         free(strtab);
2072         return 0;
2073
2074 err:
2075         free(strtab);
2076         return -1;
2077 }
2078
2079 #endif /* SUNOS4 */