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