~ubuntu-branches/debian/sid/cde/sid

« back to all changes in this revision

Viewing changes to strace-4.6/util.c

  • Committer: Package Import Robot
  • Author(s): Yaroslav Halchenko
  • Date: 2012-02-03 19:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20120203192705-ll6f1nr45ead65ed
Tags: upstream-0.1
ImportĀ upstreamĀ versionĀ 0.1

Show diffs side-by-side

added added

removed removed

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