blob: 84baf7a194c13404cec7d6f2a5d665004625e193 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# 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
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Mike Frysinger8566c502009-10-12 11:05:14 -040081#if defined(LINUXSPARC) && defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000082# undef PTRACE_GETREGS
83# define PTRACE_GETREGS PTRACE_GETREGS64
84# undef PTRACE_SETREGS
85# define PTRACE_SETREGS PTRACE_SETREGS64
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000086#endif
87
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088/* 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
Roland McGratha4d48532005-06-08 20:45:28 +000096#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000097void
98tv_tv(tv, a, b)
99struct timeval *tv;
100int a;
101int b;
102{
103 tv->tv_sec = a;
104 tv->tv_usec = b;
105}
Roland McGratha4d48532005-06-08 20:45:28 +0000106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
108int
109tv_nz(a)
110struct timeval *a;
111{
112 return a->tv_sec || a->tv_usec;
113}
114
115int
116tv_cmp(a, b)
117struct timeval *a, *b;
118{
119 if (a->tv_sec < b->tv_sec
120 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
121 return -1;
122 if (a->tv_sec > b->tv_sec
123 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
124 return 1;
125 return 0;
126}
127
128double
129tv_float(tv)
130struct timeval *tv;
131{
132 return tv->tv_sec + tv->tv_usec/1000000.0;
133}
134
135void
136tv_add(tv, a, b)
137struct 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;
Roland McGrath58372f52007-07-24 01:38:22 +0000141 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142 tv->tv_sec++;
143 tv->tv_usec -= 1000000;
144 }
145}
146
147void
148tv_sub(tv, a, b)
149struct timeval *tv, *a, *b;
150{
151 tv->tv_sec = a->tv_sec - b->tv_sec;
152 tv->tv_usec = a->tv_usec - b->tv_usec;
153 if (((long) tv->tv_usec) < 0) {
154 tv->tv_sec--;
155 tv->tv_usec += 1000000;
156 }
157}
158
159void
160tv_div(tv, a, n)
161struct timeval *tv, *a;
162int n;
163{
164 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
165 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
166 tv->tv_usec %= 1000000;
167}
168
169void
170tv_mul(tv, a, n)
171struct timeval *tv, *a;
172int n;
173{
174 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000175 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176 tv->tv_usec %= 1000000;
177}
178
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000179const char *
180xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181{
182 for (; xlat->str != NULL; xlat++)
183 if (xlat->val == val)
184 return xlat->str;
185 return NULL;
186}
187
188/*
Roland McGratheb9e2e82009-06-02 16:49:22 -0700189 * Generic ptrace wrapper which tracks ESRCH errors
190 * by setting tcp->ptrace_errno to ESRCH.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000191 *
192 * We assume that ESRCH indicates likely process death (SIGKILL?),
193 * modulo bugs where process somehow ended up not stopped.
194 * Unfortunately kernel uses ESRCH for that case too. Oh well.
Roland McGratheb9e2e82009-06-02 16:49:22 -0700195 *
196 * Currently used by upeek() only.
197 * TODO: use this in all other ptrace() calls while decoding.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000198 */
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000199long
Roland McGratheb9e2e82009-06-02 16:49:22 -0700200do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000201{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000202 long l;
203
204 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400205 l = ptrace(request, tcp->pid, addr, (long) data);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700206 /* Non-ESRCH errors might be our invalid reg/mem accesses,
207 * we do not record them. */
208 if (errno == ESRCH)
209 tcp->ptrace_errno = ESRCH;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000210 return l;
211}
212
213/*
214 * Used when we want to unblock stopped traced process.
215 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
216 * Returns 0 on success or if error was ESRCH
217 * (presumably process was killed while we talk to it).
218 * Otherwise prints error message and returns -1.
219 */
220int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700221ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000222{
223 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700224 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000225
226 errno = 0;
Mike Frysinger09a13c22009-10-07 01:13:39 -0400227 ptrace(op, tcp->pid, (void *) 1, (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000228 err = errno;
229 if (!err || err == ESRCH)
230 return 0;
231
232 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700233 msg = "SYSCALL";
234 if (op == PTRACE_CONT)
235 msg = "CONT";
236 if (op == PTRACE_DETACH)
237 msg = "DETACH";
238 fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
239 msg, sig, strerror(err));
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000240 return -1;
241}
242
243/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 * Print entry in struct xlat table, if there.
245 */
246void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000247printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000249 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251 if (str)
252 tprintf("%s", str);
253 else
254 tprintf("%#x /* %s */", val, dflt);
255}
256
257/*
258 * Interpret `xlat' as an array of flags
259 * print the entries whose bits are on in `flags'
260 * return # of flags printed.
261 */
262int
263addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000264const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265int flags;
266{
267 int n;
268
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("|%s", xlat->str);
272 flags &= ~xlat->val;
273 n++;
274 }
275 }
276 if (flags) {
277 tprintf("|%#x", flags);
278 n++;
279 }
280 return n;
281}
282
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000283/*
284 * Interpret `xlat' as an array of flags/
285 * Print to static string the entries whose bits are on in `flags'
286 * Return static string.
287 */
288const char *
289sprintflags(const char *prefix, const struct xlat *xlat, int flags)
290{
291 static char outstr[1024];
292 int found = 0;
293
294 strcpy(outstr, prefix);
295
296 for (; xlat->str; xlat++) {
297 if ((flags & xlat->val) == xlat->val) {
298 if (found)
299 strcat(outstr, "|");
300 strcat(outstr, xlat->str);
301 flags &= ~xlat->val;
302 found = 1;
303 }
304 }
305 if (flags) {
306 if (found)
307 strcat(outstr, "|");
308 sprintf(outstr + strlen(outstr), "%#x", flags);
309 }
310
311 return outstr;
312}
313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314int
Roland McGrathb2dee132005-06-01 19:02:36 +0000315printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000316const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000318const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
320 int n;
321 char *sep;
322
323 if (flags == 0 && xlat->val == 0) {
324 tprintf("%s", xlat->str);
325 return 1;
326 }
327
328 sep = "";
329 for (n = 0; xlat->str; xlat++) {
330 if (xlat->val && (flags & xlat->val) == xlat->val) {
331 tprintf("%s%s", sep, xlat->str);
332 flags &= ~xlat->val;
333 sep = "|";
334 n++;
335 }
336 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000337
338 if (n) {
339 if (flags) {
340 tprintf("%s%#x", sep, flags);
341 n++;
342 }
343 } else {
344 if (flags) {
345 tprintf("%#x", flags);
346 if (dflt)
347 tprintf(" /* %s */", dflt);
348 } else {
349 if (dflt)
350 tprintf("0");
351 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000354 return n;
355}
356
357void
358printnum(tcp, addr, fmt)
359struct tcb *tcp;
360long addr;
361char *fmt;
362{
Roland McGratheb285352003-01-14 09:59:00 +0000363 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364
365 if (!addr) {
366 tprintf("NULL");
367 return;
368 }
369 if (umove(tcp, addr, &num) < 0) {
370 tprintf("%#lx", addr);
371 return;
372 }
373 tprintf("[");
374 tprintf(fmt, num);
375 tprintf("]");
376}
377
Roland McGrath6bc12202003-11-13 22:32:27 +0000378void
Roland McGrath9814a942005-07-04 23:28:10 +0000379printnum_int(tcp, addr, fmt)
380struct tcb *tcp;
381long addr;
382char *fmt;
383{
384 int num;
385
386 if (!addr) {
387 tprintf("NULL");
388 return;
389 }
390 if (umove(tcp, addr, &num) < 0) {
391 tprintf("%#lx", addr);
392 return;
393 }
394 tprintf("[");
395 tprintf(fmt, num);
396 tprintf("]");
397}
398
399void
Roland McGrath6bc12202003-11-13 22:32:27 +0000400printuid(text, uid)
401const char *text;
402unsigned long uid;
403{
404 tprintf("%s", text);
405 tprintf((uid == -1) ? "%ld" : "%lu", uid);
406}
407
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408static char path[MAXPATHLEN + 1];
409
Dmitry V. Levina501f142008-11-10 23:19:13 +0000410/*
411 * Quote string `instr' of length `size'
412 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
413 * If `len' < 0, treat `instr' as a NUL-terminated string
414 * and quote at most (`size' - 1) bytes.
415 */
Roland McGrath6d970322007-11-01 23:53:59 +0000416static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000417string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000418{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000419 const unsigned char *ustr = (const unsigned char *) instr;
420 char *s = outstr;
421 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000422
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000423 if (xflag > 1)
424 usehex = 1;
425 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000426 /* Check for presence of symbol which require
427 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000428 for (i = 0; i < size; ++i) {
429 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000430 /* Check for NUL-terminated string. */
431 if (len < 0) {
432 if (c == '\0')
433 break;
434 /* Quote at most size - 1 bytes. */
435 if (i == size - 1)
436 continue;
437 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000438 if (!isprint(c) && !isspace(c)) {
439 usehex = 1;
440 break;
441 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000442 }
443 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000444
445 *s++ = '\"';
446
447 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000448 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000449 for (i = 0; i < size; ++i) {
450 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000451 /* Check for NUL-terminated string. */
452 if (len < 0) {
453 if (c == '\0')
454 break;
455 /* Quote at most size - 1 bytes. */
456 if (i == size - 1)
457 continue;
458 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000459 sprintf(s, "\\x%02x", c);
460 s += 4;
461 }
462 } else {
463 for (i = 0; i < size; ++i) {
464 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000465 /* Check for NUL-terminated string. */
466 if (len < 0) {
467 if (c == '\0')
468 break;
469 /* Quote at most size - 1 bytes. */
470 if (i == size - 1)
471 continue;
472 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000473 switch (c) {
474 case '\"': case '\\':
475 *s++ = '\\';
476 *s++ = c;
477 break;
478 case '\f':
479 *s++ = '\\';
480 *s++ = 'f';
481 break;
482 case '\n':
483 *s++ = '\\';
484 *s++ = 'n';
485 break;
486 case '\r':
487 *s++ = '\\';
488 *s++ = 'r';
489 break;
490 case '\t':
491 *s++ = '\\';
492 *s++ = 't';
493 break;
494 case '\v':
495 *s++ = '\\';
496 *s++ = 'v';
497 break;
498 default:
499 if (isprint(c))
500 *s++ = c;
501 else if (i + 1 < size
502 && isdigit(ustr[i + 1])) {
503 sprintf(s, "\\%03o", c);
504 s += 4;
505 } else {
506 sprintf(s, "\\%o", c);
507 s += strlen(s);
508 }
509 break;
510 }
511 }
512 }
513
514 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000516
517 /* Return nonzero if the string was unterminated. */
518 return i == size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000519}
520
Dmitry V. Levina501f142008-11-10 23:19:13 +0000521/*
522 * Print path string specified by address `addr' and length `n'.
523 * If path length exceeds `n', append `...' to the output.
524 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000526printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527{
Dmitry V. Levina501f142008-11-10 23:19:13 +0000528 if (!addr) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000529 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000530 return;
531 }
532
Dmitry V. Levina501f142008-11-10 23:19:13 +0000533 /* Cap path length to the path buffer size,
534 and NUL-terminate the buffer. */
535 if (n > sizeof path - 1)
536 n = sizeof path - 1;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000537 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000538
539 /* Fetch one byte more to find out whether path length > n. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000540 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000541 tprintf("%#lx", addr);
542 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000543 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
544 int trunc = (path[n] != '\0');
545
546 if (trunc)
547 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000548 (void) string_quote(path, outstr, -1, n + 1);
549 if (trunc)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550 strcat(outstr, "...");
551 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552 }
553}
554
555void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000556printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000558 printpathn(tcp, addr, sizeof path - 1);
559}
560
Dmitry V. Levina501f142008-11-10 23:19:13 +0000561/*
562 * Print string specified by address `addr' and length `len'.
563 * If `len' < 0, treat the string as a NUL-terminated string.
564 * If string length exceeds `max_strlen', append `...' to the output.
565 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000566void
567printstr(struct tcb *tcp, long addr, int len)
568{
569 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000571 int size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572
573 if (!addr) {
574 tprintf("NULL");
575 return;
576 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000577 /* Allocate static buffers if they are not allocated yet. */
578 if (!str)
579 str = malloc(max_strlen + 1);
580 if (!outstr)
581 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
582 if (!str || !outstr) {
583 fprintf(stderr, "out of memory\n");
584 tprintf("%#lx", addr);
585 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000586 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000587
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000589 /*
590 * Treat as a NUL-terminated string: fetch one byte more
591 * because string_quote() quotes one byte less.
592 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000593 size = max_strlen + 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000594 str[max_strlen] = '\0';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000595 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 tprintf("%#lx", addr);
597 return;
598 }
599 }
600 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000601 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000602 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000603 tprintf("%#lx", addr);
604 return;
605 }
606 }
607
Dmitry V. Levina501f142008-11-10 23:19:13 +0000608 if (string_quote(str, outstr, len, size) &&
609 (len < 0 || len > max_strlen))
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000610 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000611
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612 tprintf("%s", outstr);
613}
614
John Hughes1d08dcf2001-07-10 13:48:44 +0000615#if HAVE_SYS_UIO_H
616void
617dumpiov(tcp, len, addr)
618struct tcb * tcp;
619int len;
620long addr;
621{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000622#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
623 union {
624 struct { u_int32_t base; u_int32_t len; } *iov32;
625 struct { u_int64_t base; u_int64_t len; } *iov64;
626 } iovu;
627#define iov iovu.iov64
628#define sizeof_iov \
629 (personality_wordsize[current_personality] == 4 \
630 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
631#define iov_iov_base(i) \
632 (personality_wordsize[current_personality] == 4 \
633 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
634#define iov_iov_len(i) \
635 (personality_wordsize[current_personality] == 4 \
636 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
637#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000638 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000639#define sizeof_iov sizeof(*iov)
640#define iov_iov_base(i) iov[i].iov_base
641#define iov_iov_len(i) iov[i].iov_len
642#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000643 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000644 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000645
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000646 size = sizeof_iov * (unsigned long) len;
647 if (size / sizeof_iov != len
648 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000649 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000650 return;
651 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000652 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000653 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000654 /* include the buffer number to make it easy to
655 * match up the trace with the source */
656 tprintf(" * %lu bytes in buffer %d\n",
657 (unsigned long)iov_iov_len(i), i);
658 dumpstr(tcp, (long) iov_iov_base(i),
659 iov_iov_len(i));
660 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000661 }
662 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000663#undef sizeof_iov
664#undef iov_iov_base
665#undef iov_iov_len
666#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000667}
668#endif
669
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670void
671dumpstr(tcp, addr, len)
672struct tcb *tcp;
673long addr;
674int len;
675{
676 static int strsize = -1;
677 static unsigned char *str;
678 static char outstr[80];
679 char *s;
680 int i, j;
681
682 if (strsize < len) {
683 if (str)
684 free(str);
685 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000686 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687 return;
688 }
689 strsize = len;
690 }
691
692 if (umoven(tcp, addr, len, (char *) str) < 0)
693 return;
694
695 for (i = 0; i < len; i += 16) {
696 s = outstr;
697 sprintf(s, " | %05x ", i);
698 s += 9;
699 for (j = 0; j < 16; j++) {
700 if (j == 8)
701 *s++ = ' ';
702 if (i + j < len) {
703 sprintf(s, " %02x", str[i + j]);
704 s += 3;
705 }
706 else {
707 *s++ = ' '; *s++ = ' '; *s++ = ' ';
708 }
709 }
710 *s++ = ' '; *s++ = ' ';
711 for (j = 0; j < 16; j++) {
712 if (j == 8)
713 *s++ = ' ';
714 if (i + j < len) {
715 if (isprint(str[i + j]))
716 *s++ = str[i + j];
717 else
718 *s++ = '.';
719 }
720 else
721 *s++ = ' ';
722 }
723 tprintf("%s |\n", outstr);
724 }
725}
726
727#define PAGMASK (~(PAGSIZ - 1))
728/*
729 * move `len' bytes of data from process `pid'
730 * at address `addr' to our space at `laddr'
731 */
732int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000733umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735#ifdef LINUX
Roland McGratheb9e2e82009-06-02 16:49:22 -0700736 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000738 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000739 union {
740 long val;
741 char x[sizeof(long)];
742 } u;
743
744 if (addr & (sizeof(long) - 1)) {
745 /* addr not a multiple of sizeof(long) */
746 n = addr - (addr & -sizeof(long)); /* residue */
747 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700748 errno = 0;
749 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
750 if (errno) {
751 if (started && (errno==EPERM || errno==EIO)) {
752 /* Ran into 'end of memory' - stupid "printpath" */
753 return 0;
754 }
755 /* But if not started, we had a bogus address. */
756 if (addr != 0 && errno != EIO && errno != ESRCH)
757 perror("ptrace: umoven");
758 return -1;
759 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000760 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
762 addr += sizeof(long), laddr += m, len -= m;
763 }
764 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700765 errno = 0;
766 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
767 if (errno) {
768 if (started && (errno==EPERM || errno==EIO)) {
769 /* Ran into 'end of memory' - stupid "printpath" */
770 return 0;
771 }
772 if (addr != 0 && errno != EIO && errno != ESRCH)
773 perror("ptrace: umoven");
774 return -1;
775 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000776 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
778 addr += sizeof(long), laddr += m, len -= m;
779 }
780#endif /* LINUX */
781
782#ifdef SUNOS4
783 int pid = tcp->pid;
784#if 0
785 int n, m;
786 union {
787 long val;
788 char x[sizeof(long)];
789 } u;
790
791 if (addr & (sizeof(long) - 1)) {
792 /* addr not a multiple of sizeof(long) */
793 n = addr - (addr & -sizeof(long)); /* residue */
794 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700795 errno = 0;
796 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
797 if (errno) {
798 if (errno != ESRCH)
799 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700801 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
803 addr += sizeof(long), laddr += m, len -= m;
804 }
805 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700806 errno = 0;
807 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
808 if (errno) {
809 if (errno != ESRCH)
810 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700812 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
814 addr += sizeof(long), laddr += m, len -= m;
815 }
816#else /* !oldway */
817 int n;
818
819 while (len) {
820 n = MIN(len, PAGSIZ);
821 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700822 if (ptrace(PTRACE_READDATA, pid,
823 (char *) addr, len, laddr) < 0) {
824 if (errno != ESRCH) {
825 perror("umoven: ptrace(PTRACE_READDATA, ...)");
826 abort();
827 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 return -1;
829 }
830 len -= n;
831 addr += n;
832 laddr += n;
833 }
834#endif /* !oldway */
835#endif /* SUNOS4 */
836
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000837#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000838#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000839 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000840#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000841 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000842#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000843 lseek(fd, addr, SEEK_SET);
844 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000846#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847
848 return 0;
849}
850
851/*
852 * like `umove' but make the additional effort of looking
853 * for a terminating zero byte.
854 */
855int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000856umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000857{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000858#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000859#ifdef HAVE_MP_PROCFS
860 int fd = tcp->pfd_as;
861#else
862 int fd = tcp->pfd;
863#endif
864 /* Some systems (e.g. FreeBSD) can be upset if we read off the
865 end of valid memory, avoid this by trying to read up
866 to page boundaries. But we don't know what a page is (and
867 getpagesize(2) (if it exists) doesn't necessarily return
868 hardware page size). Assume all pages >= 1024 (a-historical
869 I know) */
870
871 int page = 1024; /* How to find this? */
872 int move = page - (addr & (page - 1));
873 int left = len;
874
875 lseek(fd, addr, SEEK_SET);
876
877 while (left) {
878 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000879 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000880 return left != len ? 0 : -1;
881 if (memchr (laddr, 0, move)) break;
882 left -= move;
883 laddr += move;
884 addr += move;
885 move = page;
886 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000887#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000888 int started = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700889 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 int i, n, m;
891 union {
892 long val;
893 char x[sizeof(long)];
894 } u;
895
896 if (addr & (sizeof(long) - 1)) {
897 /* addr not a multiple of sizeof(long) */
898 n = addr - (addr & -sizeof(long)); /* residue */
899 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700900 errno = 0;
901 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
902 if (errno) {
903 if (started && (errno==EPERM || errno==EIO)) {
904 /* Ran into 'end of memory' - stupid "printpath" */
905 return 0;
906 }
907 if (addr != 0 && errno != EIO && errno != ESRCH)
908 perror("umovestr");
909 return -1;
910 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000911 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
913 while (n & (sizeof(long) - 1))
914 if (u.x[n++] == '\0')
915 return 0;
916 addr += sizeof(long), laddr += m, len -= m;
917 }
918 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700919 errno = 0;
920 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
921 if (errno) {
922 if (started && (errno==EPERM || errno==EIO)) {
923 /* Ran into 'end of memory' - stupid "printpath" */
924 return 0;
925 }
926 if (addr != 0 && errno != EIO && errno != ESRCH)
927 perror("umovestr");
928 return -1;
929 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000930 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
932 for (i = 0; i < sizeof(long); i++)
933 if (u.x[i] == '\0')
934 return 0;
935
936 addr += sizeof(long), laddr += m, len -= m;
937 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000938#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000939 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940}
941
942#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000943# if !defined (SPARC) && !defined(SPARC64)
944# define PTRACE_WRITETEXT 101
945# define PTRACE_WRITEDATA 102
946# endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947#endif /* LINUX */
948
949#ifdef SUNOS4
950
951static int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700952uload(cmd, pid, addr, len, laddr)
953int cmd;
954int pid;
955long addr;
956int len;
957char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000959# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960 int n;
961
962 while (len) {
963 n = MIN(len, PAGSIZ);
964 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700965 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
966 perror("uload: ptrace(PTRACE_WRITE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return -1;
968 }
969 len -= n;
970 addr += n;
971 laddr += n;
972 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000973# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 int peek, poke;
975 int n, m;
976 union {
977 long val;
978 char x[sizeof(long)];
979 } u;
980
981 if (cmd == PTRACE_WRITETEXT) {
982 peek = PTRACE_PEEKTEXT;
983 poke = PTRACE_POKETEXT;
984 }
985 else {
986 peek = PTRACE_PEEKDATA;
987 poke = PTRACE_POKEDATA;
988 }
989 if (addr & (sizeof(long) - 1)) {
990 /* addr not a multiple of sizeof(long) */
991 n = addr - (addr & -sizeof(long)); /* residue */
992 addr &= -sizeof(long);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700993 errno = 0;
994 u.val = ptrace(peek, pid, (char *) addr, 0);
995 if (errno) {
996 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 return -1;
998 }
Roland McGratheb9e2e82009-06-02 16:49:22 -0700999 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
1000 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
1001 perror("uload: POKE");
1002 return -1;
1003 }
1004 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 }
1006 while (len) {
1007 if (len < sizeof(long))
Roland McGratheb9e2e82009-06-02 16:49:22 -07001008 u.val = ptrace(peek, pid, (char *) addr, 0);
1009 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
1010 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
1011 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 return -1;
1013 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001014 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001016# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 return 0;
1018}
1019
Roland McGratheb9e2e82009-06-02 16:49:22 -07001020int
1021tload(pid, addr, len, laddr)
1022int pid;
1023int addr, len;
1024char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001026 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1027}
1028
1029int
1030dload(pid, addr, len, laddr)
1031int pid;
1032int addr;
1033int len;
1034char *laddr;
1035{
1036 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037}
1038
1039#endif /* SUNOS4 */
1040
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001041#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042
1043int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001044upeek(tcp, off, res)
1045struct tcb *tcp;
1046long off;
1047long *res;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048{
1049 long val;
1050
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001051# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 {
1053 static int is_sun4m = -1;
1054 struct utsname name;
1055
1056 /* Round up the usual suspects. */
1057 if (is_sun4m == -1) {
1058 if (uname(&name) < 0) {
1059 perror("upeek: uname?");
1060 exit(1);
1061 }
1062 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1063 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001064 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065
1066 for (x = struct_user_offsets; x->str; x++)
1067 x->val += 1024;
1068 }
1069 }
1070 if (is_sun4m)
1071 off += 1024;
1072 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001073# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001074 errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001075 val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001076 if (val == -1 && errno) {
1077 if (errno != ESRCH) {
1078 char buf[60];
1079 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1080 perror(buf);
1081 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001083 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 *res = val;
1085 return 0;
1086}
1087
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001088#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089
Roland McGratha4d48532005-06-08 20:45:28 +00001090#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091long
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001092getpc(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093{
1094
1095#ifdef LINUX
1096 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001097# if defined(I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001098 if (upeek(tcp, 4*EIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001100# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001101 if (upeek(tcp, 8*RIP, &pc) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001102 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001103# elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001104 if (upeek(tcp, PT_B0, &pc) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001105 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001106# elif defined(ARM)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001107 if (upeek(tcp, 4*15, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001109# elif defined(AVR32)
1110 if (upeek(tcp, REG_PC, &pc) < 0)
1111 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001112# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001113 if (upeek(tcp, REG_PC, &pc) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001114 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001115# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001116 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001118# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001119 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001121# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001122 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001124# elif defined(MIPS)
1125 if (upeek(tcp, REG_EPC, &pc) < 0)
1126 return -1;
1127# elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001128 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001129 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001131# if defined(SPARC64)
1132 pc = regs.tpc;
1133# else
1134 pc = regs.pc;
1135# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001136# elif defined(S390) || defined(S390X)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001137 if(upeek(tcp,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001138 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001139# elif defined(HPPA)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001140 if(upeek(tcp,PT_IAOQ0,&pc) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001141 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001142# elif defined(SH)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001143 if (upeek(tcp, 4*REG_PC ,&pc) < 0)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001144 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001145# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001146 if (upeek(tcp, REG_PC ,&pc) < 0)
1147 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001148# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 return pc;
1150#endif /* LINUX */
1151
1152#ifdef SUNOS4
1153 /*
1154 * Return current program counter for `pid'
1155 * Assumes PC is never 0xffffffff
1156 */
1157 struct regs regs;
1158
Roland McGratheb9e2e82009-06-02 16:49:22 -07001159 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1160 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001162 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 return regs.r_pc;
1164#endif /* SUNOS4 */
1165
1166#ifdef SVR4
1167 /* XXX */
1168 return 0;
1169#endif /* SVR4 */
1170
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001171#ifdef FREEBSD
1172 struct reg regs;
1173 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1174 return regs.r_eip;
1175#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001177#endif /* 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178
1179void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001180printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181{
Roland McGrath7a918832005-02-02 20:55:23 +00001182#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1183 sizeof(long) == 8 ? "[????????????????] " : \
1184 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185
1186#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001187# ifdef I386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 long eip;
1189
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001190 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001191 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192 return;
1193 }
1194 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001195
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001196# elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001197 long psw;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001198 if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001199 PRINTBADPC;
1200 return;
1201 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001202# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001203 tprintf("[%08lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001204# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001205 tprintf("[%16lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001206# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001207
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001208# elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001209 long rip;
1210
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001211 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001212 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001213 return;
1214 }
1215 tprintf("[%16lx] ", rip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001216# elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001217 long ip;
1218
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001219 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001220 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001221 return;
1222 }
1223 tprintf("[%08lx] ", ip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001224# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225 long pc;
1226
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001227 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 tprintf ("[????????] ");
1229 return;
1230 }
1231 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001232# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 long pc;
1234
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001235 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 tprintf ("[????????] ");
1237 return;
1238 }
1239 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001240# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 long pc;
1242
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001243 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001244 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 return;
1246 }
1247 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001248# elif defined(SPARC) || defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001249 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001250 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001251 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252 return;
1253 }
Mike Frysinger8566c502009-10-12 11:05:14 -04001254# if defined(SPARC64)
1255 tprintf("[%08lx] ", regs.tpc);
1256# else
1257 tprintf("[%08lx] ", regs.pc);
1258# endif
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001259# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001260 long pc;
1261
Roland McGratheb9e2e82009-06-02 16:49:22 -07001262 if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001263 tprintf ("[????????] ");
1264 return;
1265 }
1266 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001267# elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001268 long pc;
1269
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001270 if (upeek(tcp, REG_EPC, &pc) < 0) {
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001271 tprintf ("[????????] ");
1272 return;
1273 }
1274 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001275# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001276 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001277
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001278 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1279 tprintf ("[????????] ");
1280 return;
1281 }
1282 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001283# elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001284 long pc;
1285
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001286 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001287 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001288 return;
1289 }
1290 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001291# elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001292 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001293
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001294 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001295 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001296 return;
1297 }
1298 tprintf("[%08lx] ", pc);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001299# elif defined(AVR32)
1300 long pc;
1301
1302 if (upeek(tcp, REG_PC, &pc) < 0) {
1303 tprintf("[????????] ");
1304 return;
1305 }
1306 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001307# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001308 long pc;
1309
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001310 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001311 PRINTBADPC;
1312 return;
1313 }
1314 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001315#elif defined(CRISV10)
1316 long pc;
1317
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001318 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001319 PRINTBADPC;
1320 return;
1321 }
1322 tprintf("[%08lx] ", pc);
1323#elif defined(CRISV32)
1324 long pc;
1325
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001326 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001327 PRINTBADPC;
1328 return;
1329 }
1330 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001331# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332#endif /* LINUX */
1333
1334#ifdef SUNOS4
1335 struct regs regs;
1336
Roland McGratheb9e2e82009-06-02 16:49:22 -07001337 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1338 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001339 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340 return;
1341 }
1342 tprintf("[%08x] ", regs.r_o7);
1343#endif /* SUNOS4 */
1344
1345#ifdef SVR4
1346 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001347 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001348#endif
1349
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350#ifdef FREEBSD
1351 struct reg regs;
1352 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1353 tprintf("[%08x] ", regs.r_eip);
1354#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001355}
1356
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001357
1358/*
1359 * These #if's are huge, please indent them correctly.
1360 * It's easy to get confused otherwise.
1361 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001362#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001364# if defined LINUX
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001366# include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001367
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001368# include <sys/syscall.h>
1369# ifndef CLONE_PTRACE
1370# define CLONE_PTRACE 0x00002000
1371# endif
1372# ifndef CLONE_VFORK
1373# define CLONE_VFORK 0x00004000
1374# endif
1375# ifndef CLONE_VM
1376# define CLONE_VM 0x00000100
1377# endif
1378# ifndef CLONE_STOPPED
1379# define CLONE_STOPPED 0x02000000
1380# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001381
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001382# ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001383
Roland McGrath08267b82004-02-20 22:56:43 +00001384/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1385 subsystem has them for x86... */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001386# define SYS_fork 2
1387# define SYS_vfork 190
Roland McGrath08267b82004-02-20 22:56:43 +00001388
Roland McGrathd81f1d92003-01-09 06:53:34 +00001389typedef unsigned long *arg_setup_state;
1390
1391static int
1392arg_setup(struct tcb *tcp, arg_setup_state *state)
1393{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001394 unsigned long cfm, sof, sol;
1395 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001396
Jan Kratochvil1f942712008-08-06 21:38:52 +00001397 if (ia32) {
1398 /* Satisfy a false GCC warning. */
1399 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001400 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001401 }
Roland McGrath08267b82004-02-20 22:56:43 +00001402
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001403 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001404 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001405 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406 return -1;
1407
1408 sof = (cfm >> 0) & 0x7f;
1409 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001410 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411
Jan Kratochvil1f942712008-08-06 21:38:52 +00001412 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001413 return 0;
1414}
1415
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001416# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001418# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001419static int
1420get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1421{
Roland McGrath08267b82004-02-20 22:56:43 +00001422 int ret;
1423
1424 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001425 ret = upeek (tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001426 else
1427 ret = umoven (tcp,
1428 (unsigned long) ia64_rse_skip_regs(*state, 0),
1429 sizeof(long), (void *) valp);
1430 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001431}
1432
1433static int
1434get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1435{
Roland McGrath08267b82004-02-20 22:56:43 +00001436 int ret;
1437
1438 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001439 ret = upeek (tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001440 else
1441 ret = umoven (tcp,
1442 (unsigned long) ia64_rse_skip_regs(*state, 1),
1443 sizeof(long), (void *) valp);
1444 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001445}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001446# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001447
1448static int
1449set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1450{
Roland McGrath08267b82004-02-20 22:56:43 +00001451 int req = PTRACE_POKEDATA;
1452 void *ap;
1453
1454 if (ia32) {
1455 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1456 req = PTRACE_POKEUSER;
1457 } else
1458 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001459 errno = 0;
1460 ptrace(req, tcp->pid, ap, val);
1461 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462}
1463
1464static int
1465set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1466{
Roland McGrath08267b82004-02-20 22:56:43 +00001467 int req = PTRACE_POKEDATA;
1468 void *ap;
1469
1470 if (ia32) {
1471 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1472 req = PTRACE_POKEUSER;
1473 } else
1474 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001475 errno = 0;
1476 ptrace(req, tcp->pid, ap, val);
1477 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001478}
1479
Roland McGrathb659f872008-07-18 01:19:36 +00001480/* ia64 does not return the input arguments from functions (and syscalls)
1481 according to ia64 RSE (Register Stack Engine) behavior. */
1482
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001483# define restore_arg0(tcp, state, val) ((void) (state), 0)
1484# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001485
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001486# elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001487
Mike Frysinger8566c502009-10-12 11:05:14 -04001488typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001489
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001490# define arg_setup(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001491 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001492# define arg_finish_change(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001493 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001494
Mike Frysinger8566c502009-10-12 11:05:14 -04001495# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1496# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1497# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1498# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001499# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001500
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001501# else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001502
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001503# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001504/* Note: this is only true for the `clone' system call, which handles
1505 arguments specially. We could as well say that its first two arguments
1506 are swapped relative to other architectures, but that would just be
1507 another #ifdef in the calls. */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001508# define arg0_offset PT_GPR3
1509# define arg1_offset PT_ORIGGPR2
1510# define restore_arg0(tcp, state, val) ((void) (state), 0)
1511# define restore_arg1(tcp, state, val) ((void) (state), 0)
1512# define arg0_index 1
1513# define arg1_index 0
1514# elif defined (ALPHA) || defined (MIPS)
1515# define arg0_offset REG_A0
1516# define arg1_offset (REG_A0+1)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001517# elif defined (AVR32)
1518# define arg0_offset (REG_R12)
1519# define arg1_offset (REG_R11)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001520# elif defined (POWERPC)
1521# define arg0_offset (sizeof(unsigned long)*PT_R3)
1522# define arg1_offset (sizeof(unsigned long)*PT_R4)
1523# define restore_arg0(tcp, state, val) ((void) (state), 0)
1524# elif defined (HPPA)
1525# define arg0_offset PT_GR26
1526# define arg1_offset (PT_GR26-4)
1527# elif defined (X86_64)
1528# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1529# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1530# elif defined (SH)
1531# define arg0_offset (4*(REG_REG0+4))
1532# define arg1_offset (4*(REG_REG0+5))
1533# elif defined (SH64)
1534 /* ABI defines arg0 & 1 in r2 & r3 */
1535# define arg0_offset (REG_OFFSET+16)
1536# define arg1_offset (REG_OFFSET+24)
1537# define restore_arg0(tcp, state, val) 0
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001538# elif defined CRISV10 || defined CRISV32
1539# define arg0_offset (4*PT_R11)
1540# define arg1_offset (4*PT_ORIG_R10)
1541# define restore_arg0(tcp, state, val) 0
1542# define restore_arg1(tcp, state, val) 0
1543# define arg0_index 1
1544# define arg1_index 0
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001545# else
1546# define arg0_offset 0
1547# define arg1_offset 4
1548# if defined ARM
1549# define restore_arg0(tcp, state, val) 0
1550# endif
1551# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001552
1553typedef int arg_setup_state;
1554
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001555# define arg_setup(tcp, state) (0)
1556# define arg_finish_change(tcp, state) 0
1557# define get_arg0(tcp, cookie, valp) \
1558 (upeek ((tcp), arg0_offset, (valp)))
1559# define get_arg1(tcp, cookie, valp) \
1560 (upeek ((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001561
1562static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001563set_arg0 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001564{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001565 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001566}
1567
1568static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001569set_arg1 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001570{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001571 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001572}
1573
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001574# endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001575
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001576# ifndef restore_arg0
1577# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1578# endif
1579# ifndef restore_arg1
1580# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1581# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001582
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001583# ifndef arg0_index
1584# define arg0_index 0
1585# define arg1_index 1
1586# endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001587
Roland McGrathd81f1d92003-01-09 06:53:34 +00001588int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001589setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001590{
Roland McGrath3291ef22008-05-20 00:34:34 +00001591 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001592 arg_setup_state state;
1593
1594 if (tcp->flags & TCB_BPTSET) {
1595 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1596 return -1;
1597 }
1598
Roland McGrath3291ef22008-05-20 00:34:34 +00001599 /*
1600 * It's a silly kludge to initialize this with a search at runtime.
1601 * But it's better than maintaining another magic thing in the
1602 * godforsaken tables.
1603 */
1604 if (clone_scno[current_personality] == 0) {
1605 int i;
1606 for (i = 0; i < nsyscalls; ++i)
1607 if (sysent[i].sys_func == sys_clone) {
1608 clone_scno[current_personality] = i;
1609 break;
1610 }
1611 }
1612
Roland McGrath76989d72005-06-07 23:21:31 +00001613 switch (known_scno(tcp)) {
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001614# ifdef SYS_vfork
Roland McGrath9383c6c2003-01-18 00:19:31 +00001615 case SYS_vfork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001616# endif
1617# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001618 case SYS_fork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001619# endif
1620# if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001621 if (arg_setup (tcp, &state) < 0
1622 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1623 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001624 || change_syscall(tcp, clone_scno[current_personality]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001625 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1626 || set_arg1 (tcp, &state, 0) < 0
1627 || arg_finish_change (tcp, &state) < 0)
1628 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001629 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1630 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001631 tcp->flags |= TCB_BPTSET;
1632 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001633# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001634
1635 case SYS_clone:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001636# ifdef SYS_clone2
Roland McGrathd81f1d92003-01-09 06:53:34 +00001637 case SYS_clone2:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001638# endif
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001639 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1640 contrary to x86 SYS_vfork above. Even on x86 we turn the
1641 vfork semantics into plain fork - each application must not
1642 depend on the vfork specifics according to POSIX. We would
1643 hang waiting for the parent resume otherwise. We need to
1644 clear also CLONE_VM but only in the CLONE_VFORK case as
1645 otherwise we would break pthread_create. */
1646
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001647 if ((arg_setup (tcp, &state) < 0
1648 || set_arg0 (tcp, &state,
1649 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001650 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
1651 ? CLONE_VFORK | CLONE_VM : 0)) < 0
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001652 || arg_finish_change (tcp, &state) < 0))
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001653 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001654 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001655 tcp->inst[0] = tcp->u_arg[arg0_index];
1656 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001657 return 0;
1658
1659 default:
1660 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1661 tcp->scno, tcp->pid);
1662 break;
1663 }
1664
1665 return -1;
1666}
1667
1668int
1669clearbpt(tcp)
1670struct tcb *tcp;
1671{
1672 arg_setup_state state;
1673 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001674 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1675 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001676 || arg_finish_change (tcp, &state))
1677 return -1;
1678 tcp->flags &= ~TCB_BPTSET;
1679 return 0;
1680}
1681
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001682# else /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001683
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684int
1685setbpt(tcp)
1686struct tcb *tcp;
1687{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001688# ifdef LINUX
1689 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1690# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 /* We simply use the SunOS breakpoint code. */
1692
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001693 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001694 unsigned long inst;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001695# define LOOPA 0x30800000 /* ba,a 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
1697 if (tcp->flags & TCB_BPTSET) {
1698 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1699 return -1;
1700 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001701 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1702 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 return -1;
1704 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001705 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001706 errno = 0;
1707 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1708 if(errno) {
1709 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001711 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712
1713 /*
1714 * XXX - BRUTAL MODE ON
1715 * We cannot set a real BPT in the child, since it will not be
1716 * traced at the moment it will reach the trap and would probably
1717 * die with a core dump.
1718 * Thus, we are force our way in by taking out two instructions
1719 * and insert an eternal loop instead, in expectance of the SIGSTOP
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001720 * generated by our PTRACE_ATTACH.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721 * Of cause, if we evaporate ourselves in the middle of all this...
1722 */
1723 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001724 inst = LOOPA;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001725# if defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001726 inst <<= 32;
1727 inst |= (tcp->inst[0] & 0xffffffffUL);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001728# endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07001729 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1730 if(errno) {
1731 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001733 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 tcp->flags |= TCB_BPTSET;
1735
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001736# else /* !SPARC && !SPARC64 */
1737# ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001738 if (ia32) {
1739# define LOOP 0x0000feeb
1740 if (tcp->flags & TCB_BPTSET) {
1741 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1742 tcp->pid);
1743 return -1;
1744 }
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001745 if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001746 return -1;
1747 if (debug)
1748 fprintf(stderr, "[%d] setting bpt at %lx\n",
1749 tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001750 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1751 (char *) tcp->baddr, 0);
1752 if (errno) {
1753 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001754 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001755 }
1756 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1757 if (errno) {
1758 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001759 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001760 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001761 tcp->flags |= TCB_BPTSET;
1762 } else {
1763 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001764 * Our strategy here is to replace the bundle that
1765 * contained the clone() syscall with a bundle of the
1766 * form:
1767 *
1768 * { 1: br 1b; br 1b; br 1b }
1769 *
1770 * This ensures that the newly forked child will loop
1771 * endlessly until we've got a chance to attach to it.
1772 */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001773# define LOOP0 0x0000100000000017
1774# define LOOP1 0x4000000000200000
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001775 unsigned long addr, ipsr;
1776 pid_t pid;
1777
1778 pid = tcp->pid;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001779 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001780 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001781 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001782 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001783 /* store "ri" in low two bits */
1784 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001785
Roland McGratheb9e2e82009-06-02 16:49:22 -07001786 errno = 0;
1787 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1788 0);
1789 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1790 0);
1791 if (errno) {
1792 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001793 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001794 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001795
Roland McGratheb9e2e82009-06-02 16:49:22 -07001796 errno = 0;
1797 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1798 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1799 if (errno) {
1800 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001801 return -1;
1802 }
1803 tcp->flags |= TCB_BPTSET;
1804 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001805# else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001807# if defined (I386) || defined(X86_64)
1808# define LOOP 0x0000feeb
1809# elif defined (M68K)
1810# define LOOP 0x60fe0000
1811# elif defined (ALPHA)
1812# define LOOP 0xc3ffffff
1813# elif defined (POWERPC)
1814# define LOOP 0x48000000
1815# elif defined(ARM)
1816# define LOOP 0xEAFFFFFE
1817# elif defined(MIPS)
1818# define LOOP 0x1000ffff
1819# elif defined(S390)
1820# define LOOP 0xa7f40000 /* BRC 15,0 */
1821# elif defined(S390X)
1822# define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1823# elif defined(HPPA)
1824# define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1825# elif defined(SH)
1826# ifdef __LITTLE_ENDIAN__
1827# define LOOP 0x0000affe
1828# else
1829# define LOOP 0xfeaf0000
1830# endif
1831# else
1832# error unknown architecture
1833# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834
1835 if (tcp->flags & TCB_BPTSET) {
1836 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1837 return -1;
1838 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001839# if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001840 if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001842# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001843 if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001844 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001845# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001846 if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001847 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001848# elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001850# elif defined (ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001852# elif defined (MIPS)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001853 return -1; /* FIXME: I do not know what i do - Flo */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001854# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001855 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001857# elif defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001858 if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001859 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001860# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001861 if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001862 return -1;
1863 tcp->baddr &= ~0x03;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001864# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001865 if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
1866 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001867# else
1868# error unknown architecture
1869# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870 if (debug)
1871 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001872 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1873 if (errno) {
1874 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001876 }
1877 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1878 if (errno) {
1879 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 return -1;
1881 }
1882 tcp->flags |= TCB_BPTSET;
1883
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001884# endif /* !IA64 */
1885# endif /* !SPARC && !SPARC64 */
1886# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001888# ifdef SUNOS4
1889# ifdef SPARC /* This code is slightly sparc specific */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001891 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001892# define BPT 0x91d02001 /* ta 1 */
1893# define LOOP 0x10800000 /* ba 0 */
1894# define LOOPA 0x30800000 /* ba,a 0 */
1895# define NOP 0x01000000
1896# if LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897 static int loopdeloop[1] = {LOOPA};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001898# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 static int loopdeloop[2] = {LOOP, NOP};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001900# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901
1902 if (tcp->flags & TCB_BPTSET) {
1903 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1904 return -1;
1905 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001906 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1907 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908 return -1;
1909 }
1910 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001911 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1912 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1913 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 return -1;
1915 }
1916
1917 /*
1918 * XXX - BRUTAL MODE ON
1919 * We cannot set a real BPT in the child, since it will not be
1920 * traced at the moment it will reach the trap and would probably
1921 * die with a core dump.
1922 * Thus, we are force our way in by taking out two instructions
1923 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1924 * generated by out PTRACE_ATTACH.
1925 * Of cause, if we evaporate ourselves in the middle of all this...
1926 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001927 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001928 sizeof loopdeloop, (char *) loopdeloop) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001929 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930 return -1;
1931 }
1932 tcp->flags |= TCB_BPTSET;
1933
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001934# endif /* SPARC */
1935# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936
1937 return 0;
1938}
1939
1940int
1941clearbpt(tcp)
1942struct tcb *tcp;
1943{
1944
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001945# ifdef LINUX
1946 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1947# if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948 long eip;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001949# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001951# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001953# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001955# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001956 long iaoq;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001957# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001958 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001959# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001961# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 /* Again, we borrow the SunOS breakpoint code. */
1963 if (!(tcp->flags & TCB_BPTSET)) {
1964 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1965 return -1;
1966 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001967 errno = 0;
1968 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1969 if(errno) {
1970 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 return -1;
1972 }
1973 tcp->flags &= ~TCB_BPTSET;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001974# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001975 if (ia32) {
1976 unsigned long addr;
1977
1978 if (debug)
1979 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1980 if (!(tcp->flags & TCB_BPTSET)) {
1981 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1982 return -1;
1983 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001984 errno = 0;
1985 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1986 if (errno) {
1987 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001988 return -1;
1989 }
1990 tcp->flags &= ~TCB_BPTSET;
1991
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001992 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001993 return -1;
1994 if (addr != tcp->baddr) {
1995 /* The breakpoint has not been reached yet. */
1996 if (debug)
1997 fprintf(stderr,
1998 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1999 addr, tcp->baddr);
2000 return 0;
2001 }
2002 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002003 unsigned long addr, ipsr;
2004 pid_t pid;
2005
2006 pid = tcp->pid;
2007
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002008 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002009 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002010 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002011 return -1;
2012
2013 /* restore original bundle: */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002014 errno = 0;
2015 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
2016 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
2017 if (errno) {
2018 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002019 return -1;
2020 }
2021
2022 /* restore original "ri" in ipsr: */
2023 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002024 errno = 0;
2025 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
2026 if (errno) {
2027 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002028 return -1;
2029 }
2030
2031 tcp->flags &= ~TCB_BPTSET;
2032
2033 if (addr != (tcp->baddr & ~0x3)) {
2034 /* the breakpoint has not been reached yet. */
2035 if (debug)
2036 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2037 addr, tcp->baddr);
2038 return 0;
2039 }
2040 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002041# else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042
2043 if (debug)
2044 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2045 if (!(tcp->flags & TCB_BPTSET)) {
2046 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2047 return -1;
2048 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002049 errno = 0;
2050 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2051 if (errno) {
2052 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 return -1;
2054 }
2055 tcp->flags &= ~TCB_BPTSET;
2056
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002057# ifdef I386
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002058 if (upeek(tcp, 4*EIP, &eip) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 return -1;
2060 if (eip != tcp->baddr) {
2061 /* The breakpoint has not been reached yet. */
2062 if (debug)
2063 fprintf(stderr,
2064 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2065 eip, tcp->baddr);
2066 return 0;
2067 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002068# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002069 if (upeek(tcp, 8*RIP, &eip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002070 return -1;
2071 if (eip != tcp->baddr) {
2072 /* The breakpoint has not been reached yet. */
2073 if (debug)
2074 fprintf(stderr,
2075 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2076 eip, tcp->baddr);
2077 return 0;
2078 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002079# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002080 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 return -1;
2082 if (pc != tcp->baddr) {
2083 /* The breakpoint has not been reached yet. */
2084 if (debug)
2085 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2086 pc, tcp->baddr);
2087 return 0;
2088 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002089# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002090 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 return -1;
2092 if (pc != tcp->baddr) {
2093 /* The breakpoint has not been reached yet. */
2094 if (debug)
2095 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2096 pc, tcp->baddr);
2097 return 0;
2098 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002099# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002100 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 return -1;
2102 if (pc != tcp->baddr) {
2103 /* The breakpoint has not been reached yet. */
2104 if (debug)
2105 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2106 pc, tcp->baddr);
2107 return 0;
2108 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002109# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002110 if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002111 return -1;
2112 iaoq &= ~0x03;
2113 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2114 /* The breakpoint has not been reached yet. */
2115 if (debug)
2116 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2117 iaoq, tcp->baddr);
2118 return 0;
2119 }
2120 iaoq = tcp->baddr | 3;
2121 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2122 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2123 * has no significant effect.
2124 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002125 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2126 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002127# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002128 if (upeek(tcp, 4*REG_PC, &pc) < 0)
2129 return -1;
2130 if (pc != tcp->baddr) {
2131 /* The breakpoint has not been reached yet. */
2132 if (debug)
2133 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2134 pc, tcp->baddr);
2135 return 0;
2136 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002137
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002138# endif /* arch */
2139# endif /* !SPARC && !SPARC64 && !IA64 */
2140# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002142# ifdef SUNOS4
2143# ifdef SPARC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002144
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002145# if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00002146 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002147# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148
2149 if (!(tcp->flags & TCB_BPTSET)) {
2150 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2151 return -1;
2152 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002153 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 sizeof tcp->inst, (char *) tcp->inst) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002155 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002156 return -1;
2157 }
2158 tcp->flags &= ~TCB_BPTSET;
2159
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002160# if !LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002161 /*
2162 * Since we don't have a single instruction breakpoint, we may have
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002163 * to adjust the program counter after removing our `breakpoint'.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002164 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002165 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2166 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002167 return -1;
2168 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002169 if ((regs.r_pc < tcp->baddr) ||
2170 (regs.r_pc > tcp->baddr + 4)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 /* The breakpoint has not been reached yet */
2172 if (debug)
2173 fprintf(stderr,
2174 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002175 regs.r_pc, tcp->baddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 return 0;
2177 }
2178 if (regs.r_pc != tcp->baddr)
2179 if (debug)
2180 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2181 regs.r_pc, tcp->baddr);
2182
2183 regs.r_pc = tcp->baddr;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002184 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2185 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 return -1;
2187 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002188# endif /* LOOPA */
2189# endif /* SPARC */
2190# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002191
2192 return 0;
2193}
2194
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002195# endif /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00002196
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002197#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002199
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200#ifdef SUNOS4
2201
2202static int
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002203getex(tcp, hdr)
2204struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205struct exec *hdr;
2206{
2207 int n;
2208
2209 for (n = 0; n < sizeof *hdr; n += 4) {
2210 long res;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002211 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 return -1;
2213 memcpy(((char *) hdr) + n, &res, 4);
2214 }
2215 if (debug) {
2216 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2217 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2218 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2219 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2220 }
2221 return 0;
2222}
2223
2224int
2225fixvfork(tcp)
2226struct tcb *tcp;
2227{
2228 int pid = tcp->pid;
2229 /*
2230 * Change `vfork' in a freshly exec'ed dynamically linked
2231 * executable's (internal) symbol table to plain old `fork'
2232 */
2233
2234 struct exec hdr;
2235 struct link_dynamic dyn;
2236 struct link_dynamic_2 ld;
2237 char *strtab, *cp;
2238
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002239 if (getex(tcp, &hdr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 return -1;
2241 if (!hdr.a_dynamic)
2242 return -1;
2243
2244 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2245 fprintf(stderr, "Cannot read DYNAMIC\n");
2246 return -1;
2247 }
2248 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2249 fprintf(stderr, "Cannot read link_dynamic_2\n");
2250 return -1;
2251 }
2252 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002253 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254 return -1;
2255 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002256 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 (int)ld.ld_symb_size, strtab) < 0)
2258 goto err;
2259
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002260# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002261 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2262 fprintf(stderr, "[symbol: %s]\n", cp);
2263 cp += strlen(cp)+1;
2264 }
2265 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002266# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2268 if (strcmp(cp, "_vfork") == 0) {
2269 if (debug)
2270 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2271 strcpy(cp, "_fork");
2272 break;
2273 }
2274 cp += strlen(cp)+1;
2275 }
2276 if (cp < strtab + ld.ld_symb_size)
2277 /*
2278 * Write entire symbol table back to avoid
2279 * memory alignment bugs in ptrace
2280 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002281 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282 (int)ld.ld_symb_size, strtab) < 0)
2283 goto err;
2284
2285 free(strtab);
2286 return 0;
2287
2288err:
2289 free(strtab);
2290 return -1;
2291}
2292
2293#endif /* SUNOS4 */