]> granicus.if.org Git - strace/blob - util.c
Remove scno_good logic in syscall exit
[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) && defined (SPARC64)
82 # undef PTRACE_GETREGS
83 # define PTRACE_GETREGS PTRACE_GETREGS64
84 # undef PTRACE_SETREGS
85 # define PTRACE_SETREGS PTRACE_SETREGS64
86 #endif
87
88 /* macros */
89 #ifndef MAX
90 #define MAX(a,b)                (((a) > (b)) ? (a) : (b))
91 #endif
92 #ifndef MIN
93 #define MIN(a,b)                (((a) < (b)) ? (a) : (b))
94 #endif
95
96 int
97 tv_nz(struct timeval *a)
98 {
99         return a->tv_sec || a->tv_usec;
100 }
101
102 int
103 tv_cmp(struct timeval *a, struct timeval *b)
104 {
105         if (a->tv_sec < b->tv_sec
106             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
107                 return -1;
108         if (a->tv_sec > b->tv_sec
109             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
110                 return 1;
111         return 0;
112 }
113
114 double
115 tv_float(struct timeval *tv)
116 {
117         return tv->tv_sec + tv->tv_usec/1000000.0;
118 }
119
120 void
121 tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
122 {
123         tv->tv_sec = a->tv_sec + b->tv_sec;
124         tv->tv_usec = a->tv_usec + b->tv_usec;
125         if (tv->tv_usec >= 1000000) {
126                 tv->tv_sec++;
127                 tv->tv_usec -= 1000000;
128         }
129 }
130
131 void
132 tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
133 {
134         tv->tv_sec = a->tv_sec - b->tv_sec;
135         tv->tv_usec = a->tv_usec - b->tv_usec;
136         if (((long) tv->tv_usec) < 0) {
137                 tv->tv_sec--;
138                 tv->tv_usec += 1000000;
139         }
140 }
141
142 void
143 tv_div(struct timeval *tv, struct timeval *a, int n)
144 {
145         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
146         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
147         tv->tv_usec %= 1000000;
148 }
149
150 void
151 tv_mul(struct timeval *tv, struct timeval *a, int n)
152 {
153         tv->tv_usec = a->tv_usec * n;
154         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
155         tv->tv_usec %= 1000000;
156 }
157
158 const char *
159 xlookup(const struct xlat *xlat, int val)
160 {
161         for (; xlat->str != NULL; xlat++)
162                 if (xlat->val == val)
163                         return xlat->str;
164         return NULL;
165 }
166
167 /*
168  * Generic ptrace wrapper which tracks ESRCH errors
169  * by setting tcp->ptrace_errno to ESRCH.
170  *
171  * We assume that ESRCH indicates likely process death (SIGKILL?),
172  * modulo bugs where process somehow ended up not stopped.
173  * Unfortunately kernel uses ESRCH for that case too. Oh well.
174  *
175  * Currently used by upeek() only.
176  * TODO: use this in all other ptrace() calls while decoding.
177  */
178 long
179 do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
180 {
181         long l;
182
183         errno = 0;
184         l = ptrace(request, tcp->pid, addr, (long) data);
185         /* Non-ESRCH errors might be our invalid reg/mem accesses,
186          * we do not record them. */
187         if (errno == ESRCH)
188                 tcp->ptrace_errno = ESRCH;
189         return l;
190 }
191
192 /*
193  * Used when we want to unblock stopped traced process.
194  * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
195  * Returns 0 on success or if error was ESRCH
196  * (presumably process was killed while we talk to it).
197  * Otherwise prints error message and returns -1.
198  */
199 int
200 ptrace_restart(int op, struct tcb *tcp, int sig)
201 {
202         int err;
203         const char *msg;
204
205         errno = 0;
206         ptrace(op, tcp->pid, (void *) 1, (long) sig);
207         err = errno;
208         if (!err || err == ESRCH)
209                 return 0;
210
211         tcp->ptrace_errno = err;
212         msg = "SYSCALL";
213         if (op == PTRACE_CONT)
214                 msg = "CONT";
215         if (op == PTRACE_DETACH)
216                 msg = "DETACH";
217         fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
218                         msg, sig, strerror(err));
219         return -1;
220 }
221
222 /*
223  * Print entry in struct xlat table, if there.
224  */
225 void
226 printxval(const struct xlat *xlat, int val, const char *dflt)
227 {
228         const char *str = xlookup(xlat, val);
229
230         if (str)
231                 tprintf("%s", str);
232         else
233                 tprintf("%#x /* %s */", val, dflt);
234 }
235
236 #if HAVE_LONG_LONG
237 /*
238  * Print 64bit argument at position llarg and return the index of the next
239  * argument.
240  */
241 int
242 printllval(struct tcb *tcp, const char *format, int llarg)
243 {
244 # if defined(FREEBSD) \
245      || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
246      || defined(LINUX_MIPSO32) \
247      || defined(__ARM_EABI__)
248         /* Align 64bit argument to 64bit boundary.  */
249         llarg = (llarg + 1) & 0x1e;
250 # endif
251 # if defined LINUX && (defined X86_64 || defined POWERPC64)
252         if (current_personality == 0) {
253                 tprintf(format, tcp->u_arg[llarg]);
254                 llarg++;
255         } else {
256 #  ifdef POWERPC64
257                 /* Align 64bit argument to 64bit boundary.  */
258                 llarg = (llarg + 1) & 0x1e;
259 #  endif
260                 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
261                 llarg += 2;
262         }
263 # elif defined IA64 || defined ALPHA
264         tprintf(format, tcp->u_arg[llarg]);
265         llarg++;
266 # elif defined LINUX_MIPSN32
267         tprintf(format, tcp->ext_arg[llarg]);
268         llarg++;
269 # else
270         tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
271         llarg += 2;
272 # endif
273         return llarg;
274 }
275 #endif
276
277 /*
278  * Interpret `xlat' as an array of flags
279  * print the entries whose bits are on in `flags'
280  * return # of flags printed.
281  */
282 void
283 addflags(const struct xlat *xlat, int flags)
284 {
285         for (; xlat->str; xlat++) {
286                 if (xlat->val && (flags & xlat->val) == xlat->val) {
287                         tprintf("|%s", xlat->str);
288                         flags &= ~xlat->val;
289                 }
290         }
291         if (flags) {
292                 tprintf("|%#x", flags);
293         }
294 }
295
296 /*
297  * Interpret `xlat' as an array of flags.
298  * Print to static string the entries whose bits are on in `flags'
299  * Return static string.
300  */
301 const char *
302 sprintflags(const char *prefix, const struct xlat *xlat, int flags)
303 {
304         static char outstr[1024];
305         int found = 0;
306
307         strcpy(outstr, prefix);
308
309         for (; xlat->str; xlat++) {
310                 if ((flags & xlat->val) == xlat->val) {
311                         if (found)
312                                 strcat(outstr, "|");
313                         strcat(outstr, xlat->str);
314                         flags &= ~xlat->val;
315                         found = 1;
316                 }
317         }
318         if (flags) {
319                 if (found)
320                         strcat(outstr, "|");
321                 sprintf(outstr + strlen(outstr), "%#x", flags);
322         }
323
324         return outstr;
325 }
326
327 int
328 printflags(const struct xlat *xlat, int flags, const char *dflt)
329 {
330         int n;
331         const char *sep;
332
333         if (flags == 0 && xlat->val == 0) {
334                 tprintf("%s", xlat->str);
335                 return 1;
336         }
337
338         sep = "";
339         for (n = 0; xlat->str; xlat++) {
340                 if (xlat->val && (flags & xlat->val) == xlat->val) {
341                         tprintf("%s%s", sep, xlat->str);
342                         flags &= ~xlat->val;
343                         sep = "|";
344                         n++;
345                 }
346         }
347
348         if (n) {
349                 if (flags) {
350                         tprintf("%s%#x", sep, flags);
351                         n++;
352                 }
353         } else {
354                 if (flags) {
355                         tprintf("%#x", flags);
356                         if (dflt)
357                                 tprintf(" /* %s */", dflt);
358                 } else {
359                         if (dflt)
360                                 tprintf("0");
361                 }
362         }
363
364         return n;
365 }
366
367 void
368 printnum(struct tcb *tcp, long addr, const char *fmt)
369 {
370         long num;
371
372         if (!addr) {
373                 tprintf("NULL");
374                 return;
375         }
376         if (umove(tcp, addr, &num) < 0) {
377                 tprintf("%#lx", addr);
378                 return;
379         }
380         tprintf("[");
381         tprintf(fmt, num);
382         tprintf("]");
383 }
384
385 void
386 printnum_int(struct tcb *tcp, long addr, const char *fmt)
387 {
388         int num;
389
390         if (!addr) {
391                 tprintf("NULL");
392                 return;
393         }
394         if (umove(tcp, addr, &num) < 0) {
395                 tprintf("%#lx", addr);
396                 return;
397         }
398         tprintf("[");
399         tprintf(fmt, num);
400         tprintf("]");
401 }
402
403 void
404 printfd(struct tcb *tcp, int fd)
405 {
406         const char *p;
407
408         if (show_fd_path && (p = getfdpath(tcp, fd)))
409                 tprintf("%d<%s>", fd, p);
410         else
411                 tprintf("%d", fd);
412 }
413
414 void
415 printuid(const char *text, unsigned long uid)
416 {
417         tprintf("%s", text);
418         tprintf((uid == -1) ? "%ld" : "%lu", uid);
419 }
420
421 static char path[MAXPATHLEN + 1];
422
423 /*
424  * Quote string `instr' of length `size'
425  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
426  * If `len' < 0, treat `instr' as a NUL-terminated string
427  * and quote at most (`size' - 1) bytes.
428  */
429 static int
430 string_quote(const char *instr, char *outstr, int len, int size)
431 {
432         const unsigned char *ustr = (const unsigned char *) instr;
433         char *s = outstr;
434         int usehex = 0, c, i;
435
436         if (xflag > 1)
437                 usehex = 1;
438         else if (xflag) {
439                 /* Check for presence of symbol which require
440                    to hex-quote the whole string. */
441                 for (i = 0; i < size; ++i) {
442                         c = ustr[i];
443                         /* Check for NUL-terminated string. */
444                         if (len < 0) {
445                                 if (c == '\0')
446                                         break;
447                                 /* Quote at most size - 1 bytes. */
448                                 if (i == size - 1)
449                                         continue;
450                         }
451                         if (!isprint(c) && !isspace(c)) {
452                                 usehex = 1;
453                                 break;
454                         }
455                 }
456         }
457
458         *s++ = '\"';
459
460         if (usehex) {
461                 /* Hex-quote the whole string. */
462                 for (i = 0; i < size; ++i) {
463                         c = ustr[i];
464                         /* Check for NUL-terminated string. */
465                         if (len < 0) {
466                                 if (c == '\0')
467                                         break;
468                                 /* Quote at most size - 1 bytes. */
469                                 if (i == size - 1)
470                                         continue;
471                         }
472                         sprintf(s, "\\x%02x", c);
473                         s += 4;
474                 }
475         } else {
476                 for (i = 0; i < size; ++i) {
477                         c = ustr[i];
478                         /* Check for NUL-terminated string. */
479                         if (len < 0) {
480                                 if (c == '\0')
481                                         break;
482                                 /* Quote at most size - 1 bytes. */
483                                 if (i == size - 1)
484                                         continue;
485                         }
486                         switch (c) {
487                                 case '\"': case '\\':
488                                         *s++ = '\\';
489                                         *s++ = c;
490                                         break;
491                                 case '\f':
492                                         *s++ = '\\';
493                                         *s++ = 'f';
494                                         break;
495                                 case '\n':
496                                         *s++ = '\\';
497                                         *s++ = 'n';
498                                         break;
499                                 case '\r':
500                                         *s++ = '\\';
501                                         *s++ = 'r';
502                                         break;
503                                 case '\t':
504                                         *s++ = '\\';
505                                         *s++ = 't';
506                                         break;
507                                 case '\v':
508                                         *s++ = '\\';
509                                         *s++ = 'v';
510                                         break;
511                                 default:
512                                         if (isprint(c))
513                                                 *s++ = c;
514                                         else if (i + 1 < size
515                                                  && isdigit(ustr[i + 1])) {
516                                                 sprintf(s, "\\%03o", c);
517                                                 s += 4;
518                                         } else {
519                                                 sprintf(s, "\\%o", c);
520                                                 s += strlen(s);
521                                         }
522                                         break;
523                         }
524                 }
525         }
526
527         *s++ = '\"';
528         *s = '\0';
529
530         /* Return nonzero if the string was unterminated.  */
531         return i == size;
532 }
533
534 /*
535  * Print path string specified by address `addr' and length `n'.
536  * If path length exceeds `n', append `...' to the output.
537  */
538 void
539 printpathn(struct tcb *tcp, long addr, int n)
540 {
541         if (!addr) {
542                 tprintf("NULL");
543                 return;
544         }
545
546         /* Cap path length to the path buffer size,
547            and NUL-terminate the buffer. */
548         if (n > sizeof path - 1)
549                 n = sizeof path - 1;
550         path[n] = '\0';
551
552         /* Fetch one byte more to find out whether path length > n. */
553         if (umovestr(tcp, addr, n + 1, path) < 0)
554                 tprintf("%#lx", addr);
555         else {
556                 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
557                 int trunc = (path[n] != '\0');
558
559                 if (trunc)
560                         path[n] = '\0';
561                 (void) string_quote(path, outstr, -1, n + 1);
562                 if (trunc)
563                         strcat(outstr, "...");
564                 tprintf("%s", outstr);
565         }
566 }
567
568 void
569 printpath(struct tcb *tcp, long addr)
570 {
571         printpathn(tcp, addr, sizeof path - 1);
572 }
573
574 /*
575  * Print string specified by address `addr' and length `len'.
576  * If `len' < 0, treat the string as a NUL-terminated string.
577  * If string length exceeds `max_strlen', append `...' to the output.
578  */
579 void
580 printstr(struct tcb *tcp, long addr, int len)
581 {
582         static char *str = NULL;
583         static char *outstr;
584         int size;
585
586         if (!addr) {
587                 tprintf("NULL");
588                 return;
589         }
590         /* Allocate static buffers if they are not allocated yet. */
591         if (!str)
592                 str = malloc(max_strlen + 1);
593         if (!outstr)
594                 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
595         if (!str || !outstr) {
596                 fprintf(stderr, "out of memory\n");
597                 tprintf("%#lx", addr);
598                 return;
599         }
600
601         if (len < 0) {
602                 /*
603                  * Treat as a NUL-terminated string: fetch one byte more
604                  * because string_quote() quotes one byte less.
605                  */
606                 size = max_strlen + 1;
607                 str[max_strlen] = '\0';
608                 if (umovestr(tcp, addr, size, str) < 0) {
609                         tprintf("%#lx", addr);
610                         return;
611                 }
612         }
613         else {
614                 size = MIN(len, max_strlen);
615                 if (umoven(tcp, addr, size, str) < 0) {
616                         tprintf("%#lx", addr);
617                         return;
618                 }
619         }
620
621         if (string_quote(str, outstr, len, size) &&
622             (len < 0 || len > max_strlen))
623                 strcat(outstr, "...");
624
625         tprintf("%s", outstr);
626 }
627
628 #if HAVE_SYS_UIO_H
629 void
630 dumpiov(struct tcb *tcp, int len, long addr)
631 {
632 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
633         union {
634                 struct { u_int32_t base; u_int32_t len; } *iov32;
635                 struct { u_int64_t base; u_int64_t len; } *iov64;
636         } iovu;
637 #define iov iovu.iov64
638 #define sizeof_iov \
639   (personality_wordsize[current_personality] == 4 \
640    ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
641 #define iov_iov_base(i) \
642   (personality_wordsize[current_personality] == 4 \
643    ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
644 #define iov_iov_len(i) \
645   (personality_wordsize[current_personality] == 4 \
646    ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
647 #else
648         struct iovec *iov;
649 #define sizeof_iov sizeof(*iov)
650 #define iov_iov_base(i) iov[i].iov_base
651 #define iov_iov_len(i) iov[i].iov_len
652 #endif
653         int i;
654         unsigned long size;
655
656         size = sizeof_iov * (unsigned long) len;
657         if (size / sizeof_iov != len
658             || (iov = malloc(size)) == NULL) {
659                 fprintf(stderr, "out of memory\n");
660                 return;
661         }
662         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
663                 for (i = 0; i < len; i++) {
664                         /* include the buffer number to make it easy to
665                          * match up the trace with the source */
666                         tprintf(" * %lu bytes in buffer %d\n",
667                                 (unsigned long)iov_iov_len(i), i);
668                         dumpstr(tcp, (long) iov_iov_base(i),
669                                 iov_iov_len(i));
670                 }
671         }
672         free((char *) iov);
673 #undef sizeof_iov
674 #undef iov_iov_base
675 #undef iov_iov_len
676 #undef iov
677 }
678 #endif
679
680 void
681 dumpstr(struct tcb *tcp, long addr, int len)
682 {
683         static int strsize = -1;
684         static unsigned char *str;
685         static char outstr[80];
686         char *s;
687         int i, j;
688
689         if (strsize < len) {
690                 free(str);
691                 str = malloc(len);
692                 if (str == NULL) {
693                         fprintf(stderr, "out of memory\n");
694         /* BUG! On next call we may use NULL str! */
695                         return;
696                 }
697                 strsize = len;
698         }
699
700         if (umoven(tcp, addr, len, (char *) str) < 0)
701                 return;
702
703         for (i = 0; i < len; i += 16) {
704                 s = outstr;
705                 sprintf(s, " | %05x ", i);
706                 s += 9;
707                 for (j = 0; j < 16; j++) {
708                         if (j == 8)
709                                 *s++ = ' ';
710                         if (i + j < len) {
711                                 sprintf(s, " %02x", str[i + j]);
712                                 s += 3;
713                         }
714                         else {
715                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
716                         }
717                 }
718                 *s++ = ' '; *s++ = ' ';
719                 for (j = 0; j < 16; j++) {
720                         if (j == 8)
721                                 *s++ = ' ';
722                         if (i + j < len) {
723                                 if (isprint(str[i + j]))
724                                         *s++ = str[i + j];
725                                 else
726                                         *s++ = '.';
727                         }
728                         else
729                                 *s++ = ' ';
730                 }
731                 tprintf("%s |\n", outstr);
732         }
733 }
734
735 #define PAGMASK (~(PAGSIZ - 1))
736 /*
737  * move `len' bytes of data from process `pid'
738  * at address `addr' to our space at `laddr'
739  */
740 int
741 umoven(struct tcb *tcp, long addr, int len, char *laddr)
742 {
743 #ifdef LINUX
744         int pid = tcp->pid;
745         int n, m;
746         int started = 0;
747         union {
748                 long val;
749                 char x[sizeof(long)];
750         } u;
751
752         if (addr & (sizeof(long) - 1)) {
753                 /* addr not a multiple of sizeof(long) */
754                 n = addr - (addr & -sizeof(long)); /* residue */
755                 addr &= -sizeof(long); /* residue */
756                 errno = 0;
757                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
758                 if (errno) {
759                         if (started && (errno==EPERM || errno==EIO)) {
760                                 /* Ran into 'end of memory' - stupid "printpath" */
761                                 return 0;
762                         }
763                         /* But if not started, we had a bogus address. */
764                         if (addr != 0 && errno != EIO && errno != ESRCH)
765                                 perror("ptrace: umoven");
766                         return -1;
767                 }
768                 started = 1;
769                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
770                 addr += sizeof(long), laddr += m, len -= m;
771         }
772         while (len) {
773                 errno = 0;
774                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
775                 if (errno) {
776                         if (started && (errno==EPERM || errno==EIO)) {
777                                 /* Ran into 'end of memory' - stupid "printpath" */
778                                 return 0;
779                         }
780                         if (addr != 0 && errno != EIO && errno != ESRCH)
781                                 perror("ptrace: umoven");
782                         return -1;
783                 }
784                 started = 1;
785                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
786                 addr += sizeof(long), laddr += m, len -= m;
787         }
788 #endif /* LINUX */
789
790 #ifdef SUNOS4
791         int pid = tcp->pid;
792         int n;
793
794         while (len) {
795                 n = MIN(len, PAGSIZ);
796                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
797                 if (ptrace(PTRACE_READDATA, pid,
798                            (char *) addr, len, laddr) < 0) {
799                         if (errno != ESRCH) {
800                                 perror("umoven: ptrace(PTRACE_READDATA, ...)");
801                                 abort();
802                         }
803                         return -1;
804                 }
805                 len -= n;
806                 addr += n;
807                 laddr += n;
808         }
809 #endif /* SUNOS4 */
810
811 #ifdef USE_PROCFS
812 #ifdef HAVE_MP_PROCFS
813         int fd = tcp->pfd_as;
814 #else
815         int fd = tcp->pfd;
816 #endif
817         lseek(fd, addr, SEEK_SET);
818         if (read(fd, laddr, len) == -1)
819                 return -1;
820 #endif /* USE_PROCFS */
821
822         return 0;
823 }
824
825 /*
826  * like `umove' but make the additional effort of looking
827  * for a terminating zero byte.
828  */
829 int
830 umovestr(struct tcb *tcp, long addr, int len, char *laddr)
831 {
832 #ifdef USE_PROCFS
833 #ifdef HAVE_MP_PROCFS
834         int fd = tcp->pfd_as;
835 #else
836         int fd = tcp->pfd;
837 #endif
838         /* Some systems (e.g. FreeBSD) can be upset if we read off the
839            end of valid memory,  avoid this by trying to read up
840            to page boundaries.  But we don't know what a page is (and
841            getpagesize(2) (if it exists) doesn't necessarily return
842            hardware page size).  Assume all pages >= 1024 (a-historical
843            I know) */
844
845         int page = 1024;        /* How to find this? */
846         int move = page - (addr & (page - 1));
847         int left = len;
848
849         lseek(fd, addr, SEEK_SET);
850
851         while (left) {
852                 if (move > left)
853                         move = left;
854                 move = read(fd, laddr, move);
855                 if (move <= 0)
856                         return left != len ? 0 : -1;
857                 if (memchr(laddr, 0, move))
858                         break;
859                 left -= move;
860                 laddr += move;
861                 addr += move;
862                 move = page;
863         }
864 #else /* !USE_PROCFS */
865         int started = 0;
866         int pid = tcp->pid;
867         int i, n, m;
868         union {
869                 long val;
870                 char x[sizeof(long)];
871         } u;
872
873         if (addr & (sizeof(long) - 1)) {
874                 /* addr not a multiple of sizeof(long) */
875                 n = addr - (addr & -sizeof(long)); /* residue */
876                 addr &= -sizeof(long); /* residue */
877                 errno = 0;
878                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
879                 if (errno) {
880                         if (started && (errno==EPERM || errno==EIO)) {
881                                 /* Ran into 'end of memory' - stupid "printpath" */
882                                 return 0;
883                         }
884                         if (addr != 0 && errno != EIO && errno != ESRCH)
885                                 perror("umovestr");
886                         return -1;
887                 }
888                 started = 1;
889                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n, len));
890                 while (n & (sizeof(long) - 1))
891                         if (u.x[n++] == '\0')
892                                 return 0;
893                 addr += sizeof(long), laddr += m, len -= m;
894         }
895         while (len) {
896                 errno = 0;
897                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
898                 if (errno) {
899                         if (started && (errno==EPERM || errno==EIO)) {
900                                 /* Ran into 'end of memory' - stupid "printpath" */
901                                 return 0;
902                         }
903                         if (addr != 0 && errno != EIO && errno != ESRCH)
904                                 perror("umovestr");
905                         return -1;
906                 }
907                 started = 1;
908                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
909                 for (i = 0; i < sizeof(long); i++)
910                         if (u.x[i] == '\0')
911                                 return 0;
912
913                 addr += sizeof(long), laddr += m, len -= m;
914         }
915 #endif /* !USE_PROCFS */
916         return 0;
917 }
918
919 #ifdef LINUX
920 # if !defined (SPARC) && !defined(SPARC64)
921 #  define PTRACE_WRITETEXT      101
922 #  define PTRACE_WRITEDATA      102
923 # endif /* !SPARC && !SPARC64 */
924 #endif /* LINUX */
925
926 #ifdef SUNOS4
927
928 static int
929 uload(int cmd, int pid, long addr, int len, char *laddr)
930 {
931         int peek, poke;
932         int n, m;
933         union {
934                 long val;
935                 char x[sizeof(long)];
936         } u;
937
938         if (cmd == PTRACE_WRITETEXT) {
939                 peek = PTRACE_PEEKTEXT;
940                 poke = PTRACE_POKETEXT;
941         }
942         else {
943                 peek = PTRACE_PEEKDATA;
944                 poke = PTRACE_POKEDATA;
945         }
946         if (addr & (sizeof(long) - 1)) {
947                 /* addr not a multiple of sizeof(long) */
948                 n = addr - (addr & -sizeof(long)); /* residue */
949                 addr &= -sizeof(long);
950                 errno = 0;
951                 u.val = ptrace(peek, pid, (char *) addr, 0);
952                 if (errno) {
953                         perror("uload: POKE");
954                         return -1;
955                 }
956                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
957                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
958                         perror("uload: POKE");
959                         return -1;
960                 }
961                 addr += sizeof(long), laddr += m, len -= m;
962         }
963         while (len) {
964                 if (len < sizeof(long))
965                         u.val = ptrace(peek, pid, (char *) addr, 0);
966                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
967                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
968                         perror("uload: POKE");
969                         return -1;
970                 }
971                 addr += sizeof(long), laddr += m, len -= m;
972         }
973         return 0;
974 }
975
976 int
977 tload(int pid, int addr, int len, char *laddr)
978 {
979         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
980 }
981
982 int
983 dload(int pid, int addr, int len, char *laddr)
984 {
985         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
986 }
987
988 #endif /* SUNOS4 */
989
990 #ifndef USE_PROCFS
991
992 int
993 upeek(struct tcb *tcp, long off, long *res)
994 {
995         long val;
996
997 # ifdef SUNOS4_KERNEL_ARCH_KLUDGE
998         {
999                 static int is_sun4m = -1;
1000                 struct utsname name;
1001
1002                 /* Round up the usual suspects. */
1003                 if (is_sun4m == -1) {
1004                         if (uname(&name) < 0) {
1005                                 perror("upeek: uname?");
1006                                 exit(1);
1007                         }
1008                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
1009                         if (is_sun4m) {
1010                                 const struct xlat *x;
1011
1012                                 for (x = struct_user_offsets; x->str; x++)
1013                                         x->val += 1024;
1014                         }
1015                 }
1016                 if (is_sun4m)
1017                         off += 1024;
1018         }
1019 # endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1020         errno = 0;
1021         val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1022         if (val == -1 && errno) {
1023                 if (errno != ESRCH) {
1024                         char buf[60];
1025                         sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1026                         perror(buf);
1027                 }
1028                 return -1;
1029         }
1030         *res = val;
1031         return 0;
1032 }
1033
1034 #endif /* !USE_PROCFS */
1035
1036 void
1037 printcall(struct tcb *tcp)
1038 {
1039 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1040                            sizeof(long) == 8 ? "[????????????????] " : \
1041                            NULL /* crash */)
1042
1043 #ifdef LINUX
1044 # ifdef I386
1045         long eip;
1046
1047         if (upeek(tcp, 4*EIP, &eip) < 0) {
1048                 PRINTBADPC;
1049                 return;
1050         }
1051         tprintf("[%08lx] ", eip);
1052
1053 # elif defined(S390) || defined(S390X)
1054         long psw;
1055         if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
1056                 PRINTBADPC;
1057                 return;
1058         }
1059 #  ifdef S390
1060         tprintf("[%08lx] ", psw);
1061 #  elif S390X
1062         tprintf("[%16lx] ", psw);
1063 #  endif
1064
1065 # elif defined(X86_64)
1066         long rip;
1067
1068         if (upeek(tcp, 8*RIP, &rip) < 0) {
1069                 PRINTBADPC;
1070                 return;
1071         }
1072         tprintf("[%16lx] ", rip);
1073 # elif defined(IA64)
1074         long ip;
1075
1076         if (upeek(tcp, PT_B0, &ip) < 0) {
1077                 PRINTBADPC;
1078                 return;
1079         }
1080         tprintf("[%08lx] ", ip);
1081 # elif defined(POWERPC)
1082         long pc;
1083
1084         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1085                 PRINTBADPC;
1086                 return;
1087         }
1088 #  ifdef POWERPC64
1089         tprintf("[%016lx] ", pc);
1090 #  else
1091         tprintf("[%08lx] ", pc);
1092 #  endif
1093 # elif defined(M68K)
1094         long pc;
1095
1096         if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1097                 tprintf("[????????] ");
1098                 return;
1099         }
1100         tprintf("[%08lx] ", pc);
1101 # elif defined(ALPHA)
1102         long pc;
1103
1104         if (upeek(tcp, REG_PC, &pc) < 0) {
1105                 tprintf("[????????????????] ");
1106                 return;
1107         }
1108         tprintf("[%08lx] ", pc);
1109 # elif defined(SPARC) || defined(SPARC64)
1110         struct pt_regs regs;
1111         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1112                 PRINTBADPC;
1113                 return;
1114         }
1115 #  if defined(SPARC64)
1116         tprintf("[%08lx] ", regs.tpc);
1117 #  else
1118         tprintf("[%08lx] ", regs.pc);
1119 #  endif
1120 # elif defined(HPPA)
1121         long pc;
1122
1123         if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1124                 tprintf("[????????] ");
1125                 return;
1126         }
1127         tprintf("[%08lx] ", pc);
1128 # elif defined(MIPS)
1129         long pc;
1130
1131         if (upeek(tcp, REG_EPC, &pc) < 0) {
1132                 tprintf("[????????] ");
1133                 return;
1134         }
1135         tprintf("[%08lx] ", pc);
1136 # elif defined(SH)
1137         long pc;
1138
1139         if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1140                 tprintf("[????????] ");
1141                 return;
1142         }
1143         tprintf("[%08lx] ", pc);
1144 # elif defined(SH64)
1145         long pc;
1146
1147         if (upeek(tcp, REG_PC, &pc) < 0) {
1148                 tprintf("[????????????????] ");
1149                 return;
1150         }
1151         tprintf("[%08lx] ", pc);
1152 # elif defined(ARM)
1153         long pc;
1154
1155         if (upeek(tcp, 4*15, &pc) < 0) {
1156                 PRINTBADPC;
1157                 return;
1158         }
1159         tprintf("[%08lx] ", pc);
1160 # elif defined(AVR32)
1161         long pc;
1162
1163         if (upeek(tcp, REG_PC, &pc) < 0) {
1164                 tprintf("[????????] ");
1165                 return;
1166         }
1167         tprintf("[%08lx] ", pc);
1168 # elif defined(BFIN)
1169         long pc;
1170
1171         if (upeek(tcp, PT_PC, &pc) < 0) {
1172                 PRINTBADPC;
1173                 return;
1174         }
1175         tprintf("[%08lx] ", pc);
1176 #elif defined(CRISV10)
1177         long pc;
1178
1179         if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1180                 PRINTBADPC;
1181                 return;
1182         }
1183         tprintf("[%08lx] ", pc);
1184 #elif defined(CRISV32)
1185         long pc;
1186
1187         if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1188                 PRINTBADPC;
1189                 return;
1190         }
1191         tprintf("[%08lx] ", pc);
1192 # endif /* architecture */
1193 #endif /* LINUX */
1194
1195 #ifdef SUNOS4
1196         struct regs regs;
1197
1198         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1199                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1200                 PRINTBADPC;
1201                 return;
1202         }
1203         tprintf("[%08x] ", regs.r_o7);
1204 #endif /* SUNOS4 */
1205
1206 #ifdef SVR4
1207         /* XXX */
1208         PRINTBADPC;
1209 #endif
1210
1211 #ifdef FREEBSD
1212         struct reg regs;
1213         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1214         tprintf("[%08x] ", regs.r_eip);
1215 #endif /* FREEBSD */
1216 }
1217
1218
1219 /*
1220  * These #if's are huge, please indent them correctly.
1221  * It's easy to get confused otherwise.
1222  */
1223 #ifndef USE_PROCFS
1224
1225 # ifdef LINUX
1226
1227 #  include "syscall.h"
1228
1229 #  include <sys/syscall.h>
1230 #  ifndef CLONE_PTRACE
1231 #   define CLONE_PTRACE    0x00002000
1232 #  endif
1233 #  ifndef CLONE_VFORK
1234 #   define CLONE_VFORK     0x00004000
1235 #  endif
1236 #  ifndef CLONE_VM
1237 #   define CLONE_VM        0x00000100
1238 #  endif
1239 #  ifndef CLONE_STOPPED
1240 #   define CLONE_STOPPED   0x02000000
1241 #  endif
1242
1243 #  ifdef IA64
1244
1245 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1246    subsystem has them for x86... */
1247 #   define SYS_fork     2
1248 #   define SYS_vfork    190
1249
1250 typedef unsigned long *arg_setup_state;
1251
1252 static int
1253 arg_setup(struct tcb *tcp, arg_setup_state *state)
1254 {
1255         unsigned long cfm, sof, sol;
1256         long bsp;
1257
1258         if (ia32) {
1259                 /* Satisfy a false GCC warning.  */
1260                 *state = NULL;
1261                 return 0;
1262         }
1263
1264         if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1265                 return -1;
1266         if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1267                 return -1;
1268
1269         sof = (cfm >> 0) & 0x7f;
1270         sol = (cfm >> 7) & 0x7f;
1271         bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1272
1273         *state = (unsigned long *) bsp;
1274         return 0;
1275 }
1276
1277 #   define arg_finish_change(tcp, state)        0
1278
1279 #   ifdef SYS_fork
1280 static int
1281 get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1282 {
1283         int ret;
1284
1285         if (ia32)
1286                 ret = upeek(tcp, PT_R11, valp);
1287         else
1288                 ret = umoven(tcp,
1289                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1290                               sizeof(long), (void *) valp);
1291         return ret;
1292 }
1293
1294 static int
1295 get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1296 {
1297         int ret;
1298
1299         if (ia32)
1300                 ret = upeek(tcp, PT_R9, valp);
1301         else
1302                 ret = umoven(tcp,
1303                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1304                               sizeof(long), (void *) valp);
1305         return ret;
1306 }
1307 #   endif
1308
1309 static int
1310 set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1311 {
1312         int req = PTRACE_POKEDATA;
1313         void *ap;
1314
1315         if (ia32) {
1316                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1317                 req = PTRACE_POKEUSER;
1318         } else
1319                 ap = ia64_rse_skip_regs(*state, 0);
1320         errno = 0;
1321         ptrace(req, tcp->pid, ap, val);
1322         return errno ? -1 : 0;
1323 }
1324
1325 static int
1326 set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1327 {
1328         int req = PTRACE_POKEDATA;
1329         void *ap;
1330
1331         if (ia32) {
1332                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1333                 req = PTRACE_POKEUSER;
1334         } else
1335                 ap = ia64_rse_skip_regs(*state, 1);
1336         errno = 0;
1337         ptrace(req, tcp->pid, ap, val);
1338         return errno ? -1 : 0;
1339 }
1340
1341 /* ia64 does not return the input arguments from functions (and syscalls)
1342    according to ia64 RSE (Register Stack Engine) behavior.  */
1343
1344 #   define restore_arg0(tcp, state, val) ((void) (state), 0)
1345 #   define restore_arg1(tcp, state, val) ((void) (state), 0)
1346
1347 #  elif defined (SPARC) || defined (SPARC64)
1348
1349 typedef struct pt_regs arg_setup_state;
1350
1351 #   define arg_setup(tcp, state) \
1352     (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1353 #   define arg_finish_change(tcp, state) \
1354     (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1355
1356 #   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1357 #   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1358 #   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1359 #   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1360 #   define restore_arg0(tcp, state, val) 0
1361
1362 #  else /* other architectures */
1363
1364 #   if defined S390 || defined S390X
1365 /* Note: this is only true for the `clone' system call, which handles
1366    arguments specially.  We could as well say that its first two arguments
1367    are swapped relative to other architectures, but that would just be
1368    another #ifdef in the calls.  */
1369 #    define arg0_offset PT_GPR3
1370 #    define arg1_offset PT_ORIGGPR2
1371 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1372 #    define restore_arg1(tcp, state, val) ((void) (state), 0)
1373 #    define arg0_index  1
1374 #    define arg1_index  0
1375 #   elif defined (ALPHA) || defined (MIPS)
1376 #    define arg0_offset REG_A0
1377 #    define arg1_offset (REG_A0+1)
1378 #   elif defined (AVR32)
1379 #    define arg0_offset (REG_R12)
1380 #    define arg1_offset (REG_R11)
1381 #   elif defined (POWERPC)
1382 #    define arg0_offset (sizeof(unsigned long)*PT_R3)
1383 #    define arg1_offset (sizeof(unsigned long)*PT_R4)
1384 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1385 #   elif defined (HPPA)
1386 #    define arg0_offset  PT_GR26
1387 #    define arg1_offset  (PT_GR26-4)
1388 #   elif defined (X86_64)
1389 #    define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1390 #    define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1391 #   elif defined (SH)
1392 #    define arg0_offset (4*(REG_REG0+4))
1393 #    define arg1_offset (4*(REG_REG0+5))
1394 #   elif defined (SH64)
1395     /* ABI defines arg0 & 1 in r2 & r3 */
1396 #    define arg0_offset   (REG_OFFSET+16)
1397 #    define arg1_offset   (REG_OFFSET+24)
1398 #    define restore_arg0(tcp, state, val) 0
1399 #   elif defined CRISV10 || defined CRISV32
1400 #    define arg0_offset   (4*PT_R11)
1401 #    define arg1_offset   (4*PT_ORIG_R10)
1402 #    define restore_arg0(tcp, state, val) 0
1403 #    define restore_arg1(tcp, state, val) 0
1404 #    define arg0_index   1
1405 #    define arg1_index   0
1406 #   else
1407 #    define arg0_offset 0
1408 #    define arg1_offset 4
1409 #    if defined ARM
1410 #     define restore_arg0(tcp, state, val) 0
1411 #    endif
1412 #   endif
1413
1414 typedef int arg_setup_state;
1415
1416 #   define arg_setup(tcp, state) (0)
1417 #   define arg_finish_change(tcp, state)        0
1418 #   define get_arg0(tcp, cookie, valp) \
1419     (upeek((tcp), arg0_offset, (valp)))
1420 #   define get_arg1(tcp, cookie, valp) \
1421     (upeek((tcp), arg1_offset, (valp)))
1422
1423 static int
1424 set_arg0(struct tcb *tcp, void *cookie, long val)
1425 {
1426         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1427 }
1428
1429 static int
1430 set_arg1(struct tcb *tcp, void *cookie, long val)
1431 {
1432         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1433 }
1434
1435 #  endif /* architectures */
1436
1437 #  ifndef restore_arg0
1438 #   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1439 #  endif
1440 #  ifndef restore_arg1
1441 #   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1442 #  endif
1443
1444 #  ifndef arg0_index
1445 #   define arg0_index 0
1446 #   define arg1_index 1
1447 #  endif
1448
1449 int
1450 setbpt(struct tcb *tcp)
1451 {
1452         static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1453         arg_setup_state state;
1454
1455         if (tcp->flags & TCB_BPTSET) {
1456                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1457                 return -1;
1458         }
1459
1460         /*
1461          * It's a silly kludge to initialize this with a search at runtime.
1462          * But it's better than maintaining another magic thing in the
1463          * godforsaken tables.
1464          */
1465         if (clone_scno[current_personality] == 0) {
1466                 int i;
1467                 for (i = 0; i < nsyscalls; ++i)
1468                         if (sysent[i].sys_func == sys_clone) {
1469                                 clone_scno[current_personality] = i;
1470                                 break;
1471                         }
1472         }
1473
1474         switch (known_scno(tcp)) {
1475 #  ifdef SYS_vfork
1476         case SYS_vfork:
1477 #  endif
1478 #  ifdef SYS_fork
1479         case SYS_fork:
1480 #  endif
1481 #  if defined SYS_fork || defined SYS_vfork
1482                 if (arg_setup(tcp, &state) < 0
1483                     || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1484                     || get_arg1(tcp, &state, &tcp->inst[1]) < 0
1485                     || change_syscall(tcp, clone_scno[current_personality]) < 0
1486                     || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1487                     || set_arg1(tcp, &state, 0) < 0
1488                     || arg_finish_change(tcp, &state) < 0)
1489                         return -1;
1490                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1491                 tcp->u_arg[arg1_index] = 0;
1492                 tcp->flags |= TCB_BPTSET;
1493                 return 0;
1494 #  endif
1495
1496         case SYS_clone: ;
1497 #  ifdef SYS_clone2
1498         case SYS_clone2: ;
1499 #  endif
1500                 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1501                    contrary to x86 SYS_vfork above.  Even on x86 we turn the
1502                    vfork semantics into plain fork - each application must not
1503                    depend on the vfork specifics according to POSIX.  We would
1504                    hang waiting for the parent resume otherwise.  We need to
1505                    clear also CLONE_VM but only in the CLONE_VFORK case as
1506                    otherwise we would break pthread_create.  */
1507
1508                 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1509                 if (new_arg0 & CLONE_VFORK)
1510                         new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1511                 if (arg_setup(tcp, &state) < 0
1512                  || set_arg0(tcp, &state, new_arg0) < 0
1513                  || arg_finish_change(tcp, &state) < 0)
1514                         return -1;
1515                 tcp->flags |= TCB_BPTSET;
1516                 tcp->inst[0] = tcp->u_arg[arg0_index];
1517                 tcp->inst[1] = tcp->u_arg[arg1_index];
1518                 return 0;
1519
1520         default:
1521                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1522                         tcp->scno, tcp->pid);
1523                 break;
1524         }
1525
1526         return -1;
1527 }
1528
1529 int
1530 clearbpt(struct tcb *tcp)
1531 {
1532         arg_setup_state state;
1533         if (arg_setup(tcp, &state) < 0
1534             || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1535             || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1536             || arg_finish_change(tcp, &state))
1537                 if (errno != ESRCH)
1538                         return -1;
1539         tcp->flags &= ~TCB_BPTSET;
1540         return 0;
1541 }
1542
1543 # else /* !defined LINUX */
1544
1545 int
1546 setbpt(struct tcb *tcp)
1547 {
1548 #  ifdef SUNOS4
1549 #   ifdef SPARC /* This code is slightly sparc specific */
1550
1551         struct regs regs;
1552 #    define BPT 0x91d02001      /* ta   1 */
1553 #    define LOOP        0x10800000      /* ba   0 */
1554 #    define LOOPA       0x30800000      /* ba,a 0 */
1555 #    define NOP 0x01000000
1556 #    if LOOPA
1557         static int loopdeloop[1] = {LOOPA};
1558 #    else
1559         static int loopdeloop[2] = {LOOP, NOP};
1560 #    endif
1561
1562         if (tcp->flags & TCB_BPTSET) {
1563                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1564                 return -1;
1565         }
1566         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1567                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1568                 return -1;
1569         }
1570         tcp->baddr = regs.r_o7 + 8;
1571         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1572                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1573                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1574                 return -1;
1575         }
1576
1577         /*
1578          * XXX - BRUTAL MODE ON
1579          * We cannot set a real BPT in the child, since it will not be
1580          * traced at the moment it will reach the trap and would probably
1581          * die with a core dump.
1582          * Thus, we are force our way in by taking out two instructions
1583          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1584          * generated by out PTRACE_ATTACH.
1585          * Of cause, if we evaporate ourselves in the middle of all this...
1586          */
1587         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1588                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1589                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1590                 return -1;
1591         }
1592         tcp->flags |= TCB_BPTSET;
1593
1594 #   endif /* SPARC */
1595 #  endif /* SUNOS4 */
1596
1597         return 0;
1598 }
1599
1600 int
1601 clearbpt(struct tcb *tcp)
1602 {
1603 #  ifdef SUNOS4
1604 #   ifdef SPARC
1605
1606 #    if !LOOPA
1607         struct regs regs;
1608 #    endif
1609
1610         if (!(tcp->flags & TCB_BPTSET)) {
1611                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1612                 return -1;
1613         }
1614         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1615                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1616                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1617                 return -1;
1618         }
1619         tcp->flags &= ~TCB_BPTSET;
1620
1621 #    if !LOOPA
1622         /*
1623          * Since we don't have a single instruction breakpoint, we may have
1624          * to adjust the program counter after removing our `breakpoint'.
1625          */
1626         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1627                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1628                 return -1;
1629         }
1630         if ((regs.r_pc < tcp->baddr) ||
1631                                 (regs.r_pc > tcp->baddr + 4)) {
1632                 /* The breakpoint has not been reached yet */
1633                 if (debug)
1634                         fprintf(stderr,
1635                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1636                                         regs.r_pc, tcp->baddr);
1637                 return 0;
1638         }
1639         if (regs.r_pc != tcp->baddr)
1640                 if (debug)
1641                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1642                                 regs.r_pc, tcp->baddr);
1643
1644         regs.r_pc = tcp->baddr;
1645         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1646                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1647                 return -1;
1648         }
1649 #    endif /* LOOPA */
1650 #   endif /* SPARC */
1651 #  endif /* SUNOS4 */
1652
1653         return 0;
1654 }
1655
1656 # endif /* !defined LINUX */
1657
1658 #endif /* !USE_PROCFS */
1659
1660
1661 #ifdef SUNOS4
1662
1663 static int
1664 getex(struct tcb *tcp, struct exec *hdr)
1665 {
1666         int n;
1667
1668         for (n = 0; n < sizeof *hdr; n += 4) {
1669                 long res;
1670                 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
1671                         return -1;
1672                 memcpy(((char *) hdr) + n, &res, 4);
1673         }
1674         if (debug) {
1675                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1676                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1677                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1678                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1679         }
1680         return 0;
1681 }
1682
1683 int
1684 fixvfork(struct tcb *tcp)
1685 {
1686         int pid = tcp->pid;
1687         /*
1688          * Change `vfork' in a freshly exec'ed dynamically linked
1689          * executable's (internal) symbol table to plain old `fork'
1690          */
1691
1692         struct exec hdr;
1693         struct link_dynamic dyn;
1694         struct link_dynamic_2 ld;
1695         char *strtab, *cp;
1696
1697         if (getex(tcp, &hdr) < 0)
1698                 return -1;
1699         if (!hdr.a_dynamic)
1700                 return -1;
1701
1702         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1703                 fprintf(stderr, "Cannot read DYNAMIC\n");
1704                 return -1;
1705         }
1706         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1707                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1708                 return -1;
1709         }
1710         strtab = malloc((unsigned)ld.ld_symb_size);
1711         if (strtab == NULL) {
1712                 fprintf(stderr, "out of memory\n");
1713                 return -1;
1714         }
1715         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1716                                         (int)ld.ld_symb_size, strtab) < 0)
1717                 goto err;
1718
1719         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1720                 if (strcmp(cp, "_vfork") == 0) {
1721                         if (debug)
1722                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1723                         strcpy(cp, "_fork");
1724                         break;
1725                 }
1726                 cp += strlen(cp)+1;
1727         }
1728         if (cp < strtab + ld.ld_symb_size)
1729                 /*
1730                  * Write entire symbol table back to avoid
1731                  * memory alignment bugs in ptrace
1732                  */
1733                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1734                                         (int)ld.ld_symb_size, strtab) < 0)
1735                         goto err;
1736
1737         free(strtab);
1738         return 0;
1739
1740 err:
1741         free(strtab);
1742         return -1;
1743 }
1744
1745 #endif /* SUNOS4 */