blob: c767065e0bf8986f59c89f9f28ed982640b7d4db [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
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000130 return (type) __res; \
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
Roland McGratha4d48532005-06-08 20:45:28 +0000151#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152void
153tv_tv(tv, a, b)
154struct timeval *tv;
155int a;
156int b;
157{
158 tv->tv_sec = a;
159 tv->tv_usec = b;
160}
Roland McGratha4d48532005-06-08 20:45:28 +0000161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163int
164tv_nz(a)
165struct timeval *a;
166{
167 return a->tv_sec || a->tv_usec;
168}
169
170int
171tv_cmp(a, b)
172struct timeval *a, *b;
173{
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
176 return -1;
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
179 return 1;
180 return 0;
181}
182
183double
184tv_float(tv)
185struct timeval *tv;
186{
187 return tv->tv_sec + tv->tv_usec/1000000.0;
188}
189
190void
191tv_add(tv, a, b)
192struct timeval *tv, *a, *b;
193{
194 tv->tv_sec = a->tv_sec + b->tv_sec;
195 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000196 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197 tv->tv_sec++;
198 tv->tv_usec -= 1000000;
199 }
200}
201
202void
203tv_sub(tv, a, b)
204struct timeval *tv, *a, *b;
205{
206 tv->tv_sec = a->tv_sec - b->tv_sec;
207 tv->tv_usec = a->tv_usec - b->tv_usec;
208 if (((long) tv->tv_usec) < 0) {
209 tv->tv_sec--;
210 tv->tv_usec += 1000000;
211 }
212}
213
214void
215tv_div(tv, a, n)
216struct timeval *tv, *a;
217int n;
218{
219 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
220 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
221 tv->tv_usec %= 1000000;
222}
223
224void
225tv_mul(tv, a, n)
226struct timeval *tv, *a;
227int n;
228{
229 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000230 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 tv->tv_usec %= 1000000;
232}
233
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000234const char *
235xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
Roland McGratheb9e2e82009-06-02 16:49:22 -0700244 * Generic ptrace wrapper which tracks ESRCH errors
245 * by setting tcp->ptrace_errno to ESRCH.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000246 *
247 * We assume that ESRCH indicates likely process death (SIGKILL?),
248 * modulo bugs where process somehow ended up not stopped.
249 * Unfortunately kernel uses ESRCH for that case too. Oh well.
Roland McGratheb9e2e82009-06-02 16:49:22 -0700250 *
251 * Currently used by upeek() only.
252 * TODO: use this in all other ptrace() calls while decoding.
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000253 */
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000254long
Roland McGratheb9e2e82009-06-02 16:49:22 -0700255do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
Denys Vlasenko4dedd562009-02-24 15:17:53 +0000256{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000257 long l;
258
259 errno = 0;
260 l = ptrace(request, tcp->pid, addr, data);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700261 /* Non-ESRCH errors might be our invalid reg/mem accesses,
262 * we do not record them. */
263 if (errno == ESRCH)
264 tcp->ptrace_errno = ESRCH;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000265 return l;
266}
267
268/*
269 * Used when we want to unblock stopped traced process.
270 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
271 * Returns 0 on success or if error was ESRCH
272 * (presumably process was killed while we talk to it).
273 * Otherwise prints error message and returns -1.
274 */
275int
Roland McGratheb9e2e82009-06-02 16:49:22 -0700276ptrace_restart(int op, struct tcb *tcp, int sig)
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000277{
278 int err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700279 const char *msg;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000280
281 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700282 ptrace(op, tcp->pid, (void *) 1, (void *) (long) sig);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000283 err = errno;
284 if (!err || err == ESRCH)
285 return 0;
286
287 tcp->ptrace_errno = err;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700288 msg = "SYSCALL";
289 if (op == PTRACE_CONT)
290 msg = "CONT";
291 if (op == PTRACE_DETACH)
292 msg = "DETACH";
293 fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
294 msg, sig, strerror(err));
Denys Vlasenko732d1bf2008-12-17 19:21:59 +0000295 return -1;
296}
297
298/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299 * Print entry in struct xlat table, if there.
300 */
301void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000302printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000303{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000304 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000305
306 if (str)
307 tprintf("%s", str);
308 else
309 tprintf("%#x /* %s */", val, dflt);
310}
311
312/*
313 * Interpret `xlat' as an array of flags
314 * print the entries whose bits are on in `flags'
315 * return # of flags printed.
316 */
317int
318addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000319const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000320int flags;
321{
322 int n;
323
324 for (n = 0; xlat->str; xlat++) {
325 if (xlat->val && (flags & xlat->val) == xlat->val) {
326 tprintf("|%s", xlat->str);
327 flags &= ~xlat->val;
328 n++;
329 }
330 }
331 if (flags) {
332 tprintf("|%#x", flags);
333 n++;
334 }
335 return n;
336}
337
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000338/*
339 * Interpret `xlat' as an array of flags/
340 * Print to static string the entries whose bits are on in `flags'
341 * Return static string.
342 */
343const char *
344sprintflags(const char *prefix, const struct xlat *xlat, int flags)
345{
346 static char outstr[1024];
347 int found = 0;
348
349 strcpy(outstr, prefix);
350
351 for (; xlat->str; xlat++) {
352 if ((flags & xlat->val) == xlat->val) {
353 if (found)
354 strcat(outstr, "|");
355 strcat(outstr, xlat->str);
356 flags &= ~xlat->val;
357 found = 1;
358 }
359 }
360 if (flags) {
361 if (found)
362 strcat(outstr, "|");
363 sprintf(outstr + strlen(outstr), "%#x", flags);
364 }
365
366 return outstr;
367}
368
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000369int
Roland McGrathb2dee132005-06-01 19:02:36 +0000370printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000371const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000373const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000374{
375 int n;
376 char *sep;
377
378 if (flags == 0 && xlat->val == 0) {
379 tprintf("%s", xlat->str);
380 return 1;
381 }
382
383 sep = "";
384 for (n = 0; xlat->str; xlat++) {
385 if (xlat->val && (flags & xlat->val) == xlat->val) {
386 tprintf("%s%s", sep, xlat->str);
387 flags &= ~xlat->val;
388 sep = "|";
389 n++;
390 }
391 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000392
393 if (n) {
394 if (flags) {
395 tprintf("%s%#x", sep, flags);
396 n++;
397 }
398 } else {
399 if (flags) {
400 tprintf("%#x", flags);
401 if (dflt)
402 tprintf(" /* %s */", dflt);
403 } else {
404 if (dflt)
405 tprintf("0");
406 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000408
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 return n;
410}
411
412void
413printnum(tcp, addr, fmt)
414struct tcb *tcp;
415long addr;
416char *fmt;
417{
Roland McGratheb285352003-01-14 09:59:00 +0000418 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000419
420 if (!addr) {
421 tprintf("NULL");
422 return;
423 }
424 if (umove(tcp, addr, &num) < 0) {
425 tprintf("%#lx", addr);
426 return;
427 }
428 tprintf("[");
429 tprintf(fmt, num);
430 tprintf("]");
431}
432
Roland McGrath6bc12202003-11-13 22:32:27 +0000433void
Roland McGrath9814a942005-07-04 23:28:10 +0000434printnum_int(tcp, addr, fmt)
435struct tcb *tcp;
436long addr;
437char *fmt;
438{
439 int num;
440
441 if (!addr) {
442 tprintf("NULL");
443 return;
444 }
445 if (umove(tcp, addr, &num) < 0) {
446 tprintf("%#lx", addr);
447 return;
448 }
449 tprintf("[");
450 tprintf(fmt, num);
451 tprintf("]");
452}
453
454void
Roland McGrath6bc12202003-11-13 22:32:27 +0000455printuid(text, uid)
456const char *text;
457unsigned long uid;
458{
459 tprintf("%s", text);
460 tprintf((uid == -1) ? "%ld" : "%lu", uid);
461}
462
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463static char path[MAXPATHLEN + 1];
464
Dmitry V. Levina501f142008-11-10 23:19:13 +0000465/*
466 * Quote string `instr' of length `size'
467 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
468 * If `len' < 0, treat `instr' as a NUL-terminated string
469 * and quote at most (`size' - 1) bytes.
470 */
Roland McGrath6d970322007-11-01 23:53:59 +0000471static int
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000472string_quote(const char *instr, char *outstr, int len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000474 const unsigned char *ustr = (const unsigned char *) instr;
475 char *s = outstr;
476 int usehex = 0, c, i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000478 if (xflag > 1)
479 usehex = 1;
480 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000481 /* Check for presence of symbol which require
482 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000483 for (i = 0; i < size; ++i) {
484 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000485 /* Check for NUL-terminated string. */
486 if (len < 0) {
487 if (c == '\0')
488 break;
489 /* Quote at most size - 1 bytes. */
490 if (i == size - 1)
491 continue;
492 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000493 if (!isprint(c) && !isspace(c)) {
494 usehex = 1;
495 break;
496 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 }
498 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000499
500 *s++ = '\"';
501
502 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000503 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000504 for (i = 0; i < size; ++i) {
505 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000506 /* Check for NUL-terminated string. */
507 if (len < 0) {
508 if (c == '\0')
509 break;
510 /* Quote at most size - 1 bytes. */
511 if (i == size - 1)
512 continue;
513 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000514 sprintf(s, "\\x%02x", c);
515 s += 4;
516 }
517 } else {
518 for (i = 0; i < size; ++i) {
519 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000520 /* Check for NUL-terminated string. */
521 if (len < 0) {
522 if (c == '\0')
523 break;
524 /* Quote at most size - 1 bytes. */
525 if (i == size - 1)
526 continue;
527 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000528 switch (c) {
529 case '\"': case '\\':
530 *s++ = '\\';
531 *s++ = c;
532 break;
533 case '\f':
534 *s++ = '\\';
535 *s++ = 'f';
536 break;
537 case '\n':
538 *s++ = '\\';
539 *s++ = 'n';
540 break;
541 case '\r':
542 *s++ = '\\';
543 *s++ = 'r';
544 break;
545 case '\t':
546 *s++ = '\\';
547 *s++ = 't';
548 break;
549 case '\v':
550 *s++ = '\\';
551 *s++ = 'v';
552 break;
553 default:
554 if (isprint(c))
555 *s++ = c;
556 else if (i + 1 < size
557 && isdigit(ustr[i + 1])) {
558 sprintf(s, "\\%03o", c);
559 s += 4;
560 } else {
561 sprintf(s, "\\%o", c);
562 s += strlen(s);
563 }
564 break;
565 }
566 }
567 }
568
569 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000571
572 /* Return nonzero if the string was unterminated. */
573 return i == size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574}
575
Dmitry V. Levina501f142008-11-10 23:19:13 +0000576/*
577 * Print path string specified by address `addr' and length `n'.
578 * If path length exceeds `n', append `...' to the output.
579 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000580void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000581printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000582{
Dmitry V. Levina501f142008-11-10 23:19:13 +0000583 if (!addr) {
Roland McGrath371ed8f2005-02-06 01:55:07 +0000584 tprintf("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000585 return;
586 }
587
Dmitry V. Levina501f142008-11-10 23:19:13 +0000588 /* Cap path length to the path buffer size,
589 and NUL-terminate the buffer. */
590 if (n > sizeof path - 1)
591 n = sizeof path - 1;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000592 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000593
594 /* Fetch one byte more to find out whether path length > n. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000595 if (umovestr(tcp, addr, n + 1, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 tprintf("%#lx", addr);
597 else {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000598 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
599 int trunc = (path[n] != '\0');
600
601 if (trunc)
602 path[n] = '\0';
Dmitry V. Levina501f142008-11-10 23:19:13 +0000603 (void) string_quote(path, outstr, -1, n + 1);
604 if (trunc)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000605 strcat(outstr, "...");
606 tprintf("%s", outstr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 }
608}
609
610void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000611printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000613 printpathn(tcp, addr, sizeof path - 1);
614}
615
Dmitry V. Levina501f142008-11-10 23:19:13 +0000616/*
617 * Print string specified by address `addr' and length `len'.
618 * If `len' < 0, treat the string as a NUL-terminated string.
619 * If string length exceeds `max_strlen', append `...' to the output.
620 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000621void
622printstr(struct tcb *tcp, long addr, int len)
623{
624 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000625 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000626 int size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627
628 if (!addr) {
629 tprintf("NULL");
630 return;
631 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000632 /* Allocate static buffers if they are not allocated yet. */
633 if (!str)
634 str = malloc(max_strlen + 1);
635 if (!outstr)
636 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
637 if (!str || !outstr) {
638 fprintf(stderr, "out of memory\n");
639 tprintf("%#lx", addr);
640 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000641 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000642
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000643 if (len < 0) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000644 /*
645 * Treat as a NUL-terminated string: fetch one byte more
646 * because string_quote() quotes one byte less.
647 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000648 size = max_strlen + 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000649 str[max_strlen] = '\0';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000650 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651 tprintf("%#lx", addr);
652 return;
653 }
654 }
655 else {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000656 size = MIN(len, max_strlen);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000657 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000658 tprintf("%#lx", addr);
659 return;
660 }
661 }
662
Dmitry V. Levina501f142008-11-10 23:19:13 +0000663 if (string_quote(str, outstr, len, size) &&
664 (len < 0 || len > max_strlen))
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000665 strcat(outstr, "...");
Roland McGratha503dcf2007-08-02 02:06:26 +0000666
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667 tprintf("%s", outstr);
668}
669
John Hughes1d08dcf2001-07-10 13:48:44 +0000670#if HAVE_SYS_UIO_H
671void
672dumpiov(tcp, len, addr)
673struct tcb * tcp;
674int len;
675long addr;
676{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000677#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
678 union {
679 struct { u_int32_t base; u_int32_t len; } *iov32;
680 struct { u_int64_t base; u_int64_t len; } *iov64;
681 } iovu;
682#define iov iovu.iov64
683#define sizeof_iov \
684 (personality_wordsize[current_personality] == 4 \
685 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
686#define iov_iov_base(i) \
687 (personality_wordsize[current_personality] == 4 \
688 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
689#define iov_iov_len(i) \
690 (personality_wordsize[current_personality] == 4 \
691 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
692#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000693 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000694#define sizeof_iov sizeof(*iov)
695#define iov_iov_base(i) iov[i].iov_base
696#define iov_iov_len(i) iov[i].iov_len
697#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000698 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000699 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000700
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000701 size = sizeof_iov * (unsigned long) len;
702 if (size / sizeof_iov != len
703 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000704 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000705 return;
706 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000707 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000708 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000709 /* include the buffer number to make it easy to
710 * match up the trace with the source */
711 tprintf(" * %lu bytes in buffer %d\n",
712 (unsigned long)iov_iov_len(i), i);
713 dumpstr(tcp, (long) iov_iov_base(i),
714 iov_iov_len(i));
715 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000716 }
717 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000718#undef sizeof_iov
719#undef iov_iov_base
720#undef iov_iov_len
721#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000722}
723#endif
724
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000725void
726dumpstr(tcp, addr, len)
727struct tcb *tcp;
728long addr;
729int len;
730{
731 static int strsize = -1;
732 static unsigned char *str;
733 static char outstr[80];
734 char *s;
735 int i, j;
736
737 if (strsize < len) {
738 if (str)
739 free(str);
740 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000741 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 return;
743 }
744 strsize = len;
745 }
746
747 if (umoven(tcp, addr, len, (char *) str) < 0)
748 return;
749
750 for (i = 0; i < len; i += 16) {
751 s = outstr;
752 sprintf(s, " | %05x ", i);
753 s += 9;
754 for (j = 0; j < 16; j++) {
755 if (j == 8)
756 *s++ = ' ';
757 if (i + j < len) {
758 sprintf(s, " %02x", str[i + j]);
759 s += 3;
760 }
761 else {
762 *s++ = ' '; *s++ = ' '; *s++ = ' ';
763 }
764 }
765 *s++ = ' '; *s++ = ' ';
766 for (j = 0; j < 16; j++) {
767 if (j == 8)
768 *s++ = ' ';
769 if (i + j < len) {
770 if (isprint(str[i + j]))
771 *s++ = str[i + j];
772 else
773 *s++ = '.';
774 }
775 else
776 *s++ = ' ';
777 }
778 tprintf("%s |\n", outstr);
779 }
780}
781
782#define PAGMASK (~(PAGSIZ - 1))
783/*
784 * move `len' bytes of data from process `pid'
785 * at address `addr' to our space at `laddr'
786 */
787int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000788umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000790#ifdef LINUX
Roland McGratheb9e2e82009-06-02 16:49:22 -0700791 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000793 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 union {
795 long val;
796 char x[sizeof(long)];
797 } u;
798
799 if (addr & (sizeof(long) - 1)) {
800 /* addr not a multiple of sizeof(long) */
801 n = addr - (addr & -sizeof(long)); /* residue */
802 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700803 errno = 0;
804 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
805 if (errno) {
806 if (started && (errno==EPERM || errno==EIO)) {
807 /* Ran into 'end of memory' - stupid "printpath" */
808 return 0;
809 }
810 /* But if not started, we had a bogus address. */
811 if (addr != 0 && errno != EIO && errno != ESRCH)
812 perror("ptrace: umoven");
813 return -1;
814 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000815 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
817 addr += sizeof(long), laddr += m, len -= m;
818 }
819 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700820 errno = 0;
821 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
822 if (errno) {
823 if (started && (errno==EPERM || errno==EIO)) {
824 /* Ran into 'end of memory' - stupid "printpath" */
825 return 0;
826 }
827 if (addr != 0 && errno != EIO && errno != ESRCH)
828 perror("ptrace: umoven");
829 return -1;
830 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000831 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
833 addr += sizeof(long), laddr += m, len -= m;
834 }
835#endif /* LINUX */
836
837#ifdef SUNOS4
838 int pid = tcp->pid;
839#if 0
840 int n, m;
841 union {
842 long val;
843 char x[sizeof(long)];
844 } u;
845
846 if (addr & (sizeof(long) - 1)) {
847 /* addr not a multiple of sizeof(long) */
848 n = addr - (addr & -sizeof(long)); /* residue */
849 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700850 errno = 0;
851 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
852 if (errno) {
853 if (errno != ESRCH)
854 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000855 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700856 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000857 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
858 addr += sizeof(long), laddr += m, len -= m;
859 }
860 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700861 errno = 0;
862 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
863 if (errno) {
864 if (errno != ESRCH)
865 perror("umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000866 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700867 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
869 addr += sizeof(long), laddr += m, len -= m;
870 }
871#else /* !oldway */
872 int n;
873
874 while (len) {
875 n = MIN(len, PAGSIZ);
876 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700877 if (ptrace(PTRACE_READDATA, pid,
878 (char *) addr, len, laddr) < 0) {
879 if (errno != ESRCH) {
880 perror("umoven: ptrace(PTRACE_READDATA, ...)");
881 abort();
882 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883 return -1;
884 }
885 len -= n;
886 addr += n;
887 laddr += n;
888 }
889#endif /* !oldway */
890#endif /* SUNOS4 */
891
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000892#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000893#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000894 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000895#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000896 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000898 lseek(fd, addr, SEEK_SET);
899 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000901#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902
903 return 0;
904}
905
906/*
907 * like `umove' but make the additional effort of looking
908 * for a terminating zero byte.
909 */
910int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000911umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000913#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000914#ifdef HAVE_MP_PROCFS
915 int fd = tcp->pfd_as;
916#else
917 int fd = tcp->pfd;
918#endif
919 /* Some systems (e.g. FreeBSD) can be upset if we read off the
920 end of valid memory, avoid this by trying to read up
921 to page boundaries. But we don't know what a page is (and
922 getpagesize(2) (if it exists) doesn't necessarily return
923 hardware page size). Assume all pages >= 1024 (a-historical
924 I know) */
925
926 int page = 1024; /* How to find this? */
927 int move = page - (addr & (page - 1));
928 int left = len;
929
930 lseek(fd, addr, SEEK_SET);
931
932 while (left) {
933 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000934 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000935 return left != len ? 0 : -1;
936 if (memchr (laddr, 0, move)) break;
937 left -= move;
938 laddr += move;
939 addr += move;
940 move = page;
941 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000942#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000943 int started = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700944 int pid = tcp->pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 int i, n, m;
946 union {
947 long val;
948 char x[sizeof(long)];
949 } u;
950
951 if (addr & (sizeof(long) - 1)) {
952 /* addr not a multiple of sizeof(long) */
953 n = addr - (addr & -sizeof(long)); /* residue */
954 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700955 errno = 0;
956 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
957 if (errno) {
958 if (started && (errno==EPERM || errno==EIO)) {
959 /* Ran into 'end of memory' - stupid "printpath" */
960 return 0;
961 }
962 if (addr != 0 && errno != EIO && errno != ESRCH)
963 perror("umovestr");
964 return -1;
965 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000966 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
968 while (n & (sizeof(long) - 1))
969 if (u.x[n++] == '\0')
970 return 0;
971 addr += sizeof(long), laddr += m, len -= m;
972 }
973 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700974 errno = 0;
975 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
976 if (errno) {
977 if (started && (errno==EPERM || errno==EIO)) {
978 /* Ran into 'end of memory' - stupid "printpath" */
979 return 0;
980 }
981 if (addr != 0 && errno != EIO && errno != ESRCH)
982 perror("umovestr");
983 return -1;
984 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000985 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
987 for (i = 0; i < sizeof(long); i++)
988 if (u.x[i] == '\0')
989 return 0;
990
991 addr += sizeof(long), laddr += m, len -= m;
992 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000993#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000994 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995}
996
997#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +0000998# if !defined (SPARC) && !defined(SPARC64)
999# define PTRACE_WRITETEXT 101
1000# define PTRACE_WRITEDATA 102
1001# endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002#endif /* LINUX */
1003
1004#ifdef SUNOS4
1005
1006static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001007uload(cmd, pid, addr, len, laddr)
1008int cmd;
1009int pid;
1010long addr;
1011int len;
1012char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001014# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 int n;
1016
1017 while (len) {
1018 n = MIN(len, PAGSIZ);
1019 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001020 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
1021 perror("uload: ptrace(PTRACE_WRITE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 return -1;
1023 }
1024 len -= n;
1025 addr += n;
1026 laddr += n;
1027 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001028# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 int peek, poke;
1030 int n, m;
1031 union {
1032 long val;
1033 char x[sizeof(long)];
1034 } u;
1035
1036 if (cmd == PTRACE_WRITETEXT) {
1037 peek = PTRACE_PEEKTEXT;
1038 poke = PTRACE_POKETEXT;
1039 }
1040 else {
1041 peek = PTRACE_PEEKDATA;
1042 poke = PTRACE_POKEDATA;
1043 }
1044 if (addr & (sizeof(long) - 1)) {
1045 /* addr not a multiple of sizeof(long) */
1046 n = addr - (addr & -sizeof(long)); /* residue */
1047 addr &= -sizeof(long);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001048 errno = 0;
1049 u.val = ptrace(peek, pid, (char *) addr, 0);
1050 if (errno) {
1051 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 return -1;
1053 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001054 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
1055 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
1056 perror("uload: POKE");
1057 return -1;
1058 }
1059 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 }
1061 while (len) {
1062 if (len < sizeof(long))
Roland McGratheb9e2e82009-06-02 16:49:22 -07001063 u.val = ptrace(peek, pid, (char *) addr, 0);
1064 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
1065 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
1066 perror("uload: POKE");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001067 return -1;
1068 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001069 addr += sizeof(long), laddr += m, len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001071# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001072 return 0;
1073}
1074
Roland McGratheb9e2e82009-06-02 16:49:22 -07001075int
1076tload(pid, addr, len, laddr)
1077int pid;
1078int addr, len;
1079char *laddr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001081 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1082}
1083
1084int
1085dload(pid, addr, len, laddr)
1086int pid;
1087int addr;
1088int len;
1089char *laddr;
1090{
1091 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092}
1093
1094#endif /* SUNOS4 */
1095
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001096#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097
1098int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001099upeek(tcp, off, res)
1100struct tcb *tcp;
1101long off;
1102long *res;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103{
1104 long val;
1105
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001106# ifdef SUNOS4_KERNEL_ARCH_KLUDGE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 {
1108 static int is_sun4m = -1;
1109 struct utsname name;
1110
1111 /* Round up the usual suspects. */
1112 if (is_sun4m == -1) {
1113 if (uname(&name) < 0) {
1114 perror("upeek: uname?");
1115 exit(1);
1116 }
1117 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1118 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001119 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120
1121 for (x = struct_user_offsets; x->str; x++)
1122 x->val += 1024;
1123 }
1124 }
1125 if (is_sun4m)
1126 off += 1024;
1127 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001128# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001129 errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001130 val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001131 if (val == -1 && errno) {
1132 if (errno != ESRCH) {
1133 char buf[60];
1134 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1135 perror(buf);
1136 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001138 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 *res = val;
1140 return 0;
1141}
1142
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001143#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144
Roland McGratha4d48532005-06-08 20:45:28 +00001145#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146long
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001147getpc(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148{
1149
1150#ifdef LINUX
1151 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001152# if defined(I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001153 if (upeek(tcp, 4*EIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001155# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001156 if (upeek(tcp, 8*RIP, &pc) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001157 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001158# elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001159 if (upeek(tcp, PT_B0, &pc) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001160 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001161# elif defined(ARM)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001162 if (upeek(tcp, 4*15, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001164# elif defined(AVR32)
1165 if (upeek(tcp, REG_PC, &pc) < 0)
1166 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001167# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001168 if (upeek(tcp, REG_PC, &pc) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001169 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001170# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001171 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001173# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001174 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001176# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001177 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001179# elif defined(MIPS)
1180 if (upeek(tcp, REG_EPC, &pc) < 0)
1181 return -1;
1182# elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001183 struct regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001184 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001186 pc = regs.r_pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001187# elif defined(S390) || defined(S390X)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001188 if(upeek(tcp,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001189 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001190# elif defined(HPPA)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001191 if(upeek(tcp,PT_IAOQ0,&pc) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001192 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001193# elif defined(SH)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001194 if (upeek(tcp, 4*REG_PC ,&pc) < 0)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001195 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001196# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001197 if (upeek(tcp, REG_PC ,&pc) < 0)
1198 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001199# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 return pc;
1201#endif /* LINUX */
1202
1203#ifdef SUNOS4
1204 /*
1205 * Return current program counter for `pid'
1206 * Assumes PC is never 0xffffffff
1207 */
1208 struct regs regs;
1209
Roland McGratheb9e2e82009-06-02 16:49:22 -07001210 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1211 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001213 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214 return regs.r_pc;
1215#endif /* SUNOS4 */
1216
1217#ifdef SVR4
1218 /* XXX */
1219 return 0;
1220#endif /* SVR4 */
1221
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001222#ifdef FREEBSD
1223 struct reg regs;
1224 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1225 return regs.r_eip;
1226#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001228#endif /* 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229
1230void
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001231printcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232{
Roland McGrath7a918832005-02-02 20:55:23 +00001233#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1234 sizeof(long) == 8 ? "[????????????????] " : \
1235 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236
1237#ifdef LINUX
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001238# ifdef I386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 long eip;
1240
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001241 if (upeek(tcp, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001242 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 return;
1244 }
1245 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001246
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001247# elif defined(S390) || defined(S390X)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001248 long psw;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001249 if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001250 PRINTBADPC;
1251 return;
1252 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001253# ifdef S390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001254 tprintf("[%08lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001255# elif S390X
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001256 tprintf("[%16lx] ", psw);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001257# endif
Roland McGratheac26fc2005-02-02 02:48:53 +00001258
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001259# elif defined(X86_64)
Michal Ludvig0e035502002-09-23 15:41:01 +00001260 long rip;
1261
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001262 if (upeek(tcp, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001263 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001264 return;
1265 }
1266 tprintf("[%16lx] ", rip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001267# elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001268 long ip;
1269
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001270 if (upeek(tcp, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001271 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001272 return;
1273 }
1274 tprintf("[%08lx] ", ip);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001275# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 long pc;
1277
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001278 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 tprintf ("[????????] ");
1280 return;
1281 }
1282 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001283# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 long pc;
1285
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001286 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 tprintf ("[????????] ");
1288 return;
1289 }
1290 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001291# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 long pc;
1293
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001294 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001295 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296 return;
1297 }
1298 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001299# elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001300 struct regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001301 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001302 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001303 return;
1304 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001305 tprintf("[%08lx] ", regs.r_pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001306# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001307 long pc;
1308
Roland McGratheb9e2e82009-06-02 16:49:22 -07001309 if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001310 tprintf ("[????????] ");
1311 return;
1312 }
1313 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001314# elif defined(MIPS)
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001315 long pc;
1316
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001317 if (upeek(tcp, REG_EPC, &pc) < 0) {
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001318 tprintf ("[????????] ");
1319 return;
1320 }
1321 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001322# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001323 long pc;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001324
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001325 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1326 tprintf ("[????????] ");
1327 return;
1328 }
1329 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001330# elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001331 long pc;
1332
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001333 if (upeek(tcp, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001334 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001335 return;
1336 }
1337 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001338# elif defined(ARM)
Roland McGrathef388682003-06-03 23:28:59 +00001339 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001340
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001341 if (upeek(tcp, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001342 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001343 return;
1344 }
1345 tprintf("[%08lx] ", pc);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001346# elif defined(AVR32)
1347 long pc;
1348
1349 if (upeek(tcp, REG_PC, &pc) < 0) {
1350 tprintf("[????????] ");
1351 return;
1352 }
1353 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001354# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001355 long pc;
1356
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001357 if (upeek(tcp, PT_PC, &pc) < 0) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001358 PRINTBADPC;
1359 return;
1360 }
1361 tprintf("[%08lx] ", pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001362#elif defined(CRISV10)
1363 long pc;
1364
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001365 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001366 PRINTBADPC;
1367 return;
1368 }
1369 tprintf("[%08lx] ", pc);
1370#elif defined(CRISV32)
1371 long pc;
1372
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001373 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001374 PRINTBADPC;
1375 return;
1376 }
1377 tprintf("[%08lx] ", pc);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001378# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379#endif /* LINUX */
1380
1381#ifdef SUNOS4
1382 struct regs regs;
1383
Roland McGratheb9e2e82009-06-02 16:49:22 -07001384 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1385 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001386 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001387 return;
1388 }
1389 tprintf("[%08x] ", regs.r_o7);
1390#endif /* SUNOS4 */
1391
1392#ifdef SVR4
1393 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001394 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395#endif
1396
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001397#ifdef FREEBSD
1398 struct reg regs;
1399 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1400 tprintf("[%08x] ", regs.r_eip);
1401#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402}
1403
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001404
1405/*
1406 * These #if's are huge, please indent them correctly.
1407 * It's easy to get confused otherwise.
1408 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001409#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001411# if defined LINUX
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001413# include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001414
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001415# include <sys/syscall.h>
1416# ifndef CLONE_PTRACE
1417# define CLONE_PTRACE 0x00002000
1418# endif
1419# ifndef CLONE_VFORK
1420# define CLONE_VFORK 0x00004000
1421# endif
1422# ifndef CLONE_VM
1423# define CLONE_VM 0x00000100
1424# endif
1425# ifndef CLONE_STOPPED
1426# define CLONE_STOPPED 0x02000000
1427# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001428
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001429# ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001430
Roland McGrath08267b82004-02-20 22:56:43 +00001431/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1432 subsystem has them for x86... */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001433# define SYS_fork 2
1434# define SYS_vfork 190
Roland McGrath08267b82004-02-20 22:56:43 +00001435
Roland McGrathd81f1d92003-01-09 06:53:34 +00001436typedef unsigned long *arg_setup_state;
1437
1438static int
1439arg_setup(struct tcb *tcp, arg_setup_state *state)
1440{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001441 unsigned long cfm, sof, sol;
1442 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001443
Jan Kratochvil1f942712008-08-06 21:38:52 +00001444 if (ia32) {
1445 /* Satisfy a false GCC warning. */
1446 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001447 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001448 }
Roland McGrath08267b82004-02-20 22:56:43 +00001449
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001450 if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001451 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001452 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453 return -1;
1454
1455 sof = (cfm >> 0) & 0x7f;
1456 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001457 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001458
Jan Kratochvil1f942712008-08-06 21:38:52 +00001459 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001460 return 0;
1461}
1462
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001463# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001464
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001465# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001466static int
1467get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1468{
Roland McGrath08267b82004-02-20 22:56:43 +00001469 int ret;
1470
1471 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001472 ret = upeek (tcp, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001473 else
1474 ret = umoven (tcp,
1475 (unsigned long) ia64_rse_skip_regs(*state, 0),
1476 sizeof(long), (void *) valp);
1477 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001478}
1479
1480static int
1481get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1482{
Roland McGrath08267b82004-02-20 22:56:43 +00001483 int ret;
1484
1485 if (ia32)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001486 ret = upeek (tcp, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001487 else
1488 ret = umoven (tcp,
1489 (unsigned long) ia64_rse_skip_regs(*state, 1),
1490 sizeof(long), (void *) valp);
1491 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001492}
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001493# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001494
1495static int
1496set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1497{
Roland McGrath08267b82004-02-20 22:56:43 +00001498 int req = PTRACE_POKEDATA;
1499 void *ap;
1500
1501 if (ia32) {
1502 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1503 req = PTRACE_POKEUSER;
1504 } else
1505 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001506 errno = 0;
1507 ptrace(req, tcp->pid, ap, val);
1508 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001509}
1510
1511static int
1512set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1513{
Roland McGrath08267b82004-02-20 22:56:43 +00001514 int req = PTRACE_POKEDATA;
1515 void *ap;
1516
1517 if (ia32) {
1518 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1519 req = PTRACE_POKEUSER;
1520 } else
1521 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001522 errno = 0;
1523 ptrace(req, tcp->pid, ap, val);
1524 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001525}
1526
Roland McGrathb659f872008-07-18 01:19:36 +00001527/* ia64 does not return the input arguments from functions (and syscalls)
1528 according to ia64 RSE (Register Stack Engine) behavior. */
1529
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001530# define restore_arg0(tcp, state, val) ((void) (state), 0)
1531# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001532
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001533# elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001534
1535typedef struct regs arg_setup_state;
1536
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001537# define arg_setup(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001538 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001539# define arg_finish_change(tcp, state) \
Roland McGratheb9e2e82009-06-02 16:49:22 -07001540 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001541
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001542# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1543# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1544# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1545# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1546# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001547
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001548# else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001549
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001550# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001551/* Note: this is only true for the `clone' system call, which handles
1552 arguments specially. We could as well say that its first two arguments
1553 are swapped relative to other architectures, but that would just be
1554 another #ifdef in the calls. */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001555# define arg0_offset PT_GPR3
1556# define arg1_offset PT_ORIGGPR2
1557# define restore_arg0(tcp, state, val) ((void) (state), 0)
1558# define restore_arg1(tcp, state, val) ((void) (state), 0)
1559# define arg0_index 1
1560# define arg1_index 0
1561# elif defined (ALPHA) || defined (MIPS)
1562# define arg0_offset REG_A0
1563# define arg1_offset (REG_A0+1)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001564# elif defined (AVR32)
1565# define arg0_offset (REG_R12)
1566# define arg1_offset (REG_R11)
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001567# elif defined (POWERPC)
1568# define arg0_offset (sizeof(unsigned long)*PT_R3)
1569# define arg1_offset (sizeof(unsigned long)*PT_R4)
1570# define restore_arg0(tcp, state, val) ((void) (state), 0)
1571# elif defined (HPPA)
1572# define arg0_offset PT_GR26
1573# define arg1_offset (PT_GR26-4)
1574# elif defined (X86_64)
1575# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1576# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1577# elif defined (SH)
1578# define arg0_offset (4*(REG_REG0+4))
1579# define arg1_offset (4*(REG_REG0+5))
1580# elif defined (SH64)
1581 /* ABI defines arg0 & 1 in r2 & r3 */
1582# define arg0_offset (REG_OFFSET+16)
1583# define arg1_offset (REG_OFFSET+24)
1584# define restore_arg0(tcp, state, val) 0
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001585# elif defined CRISV10 || defined CRISV32
1586# define arg0_offset (4*PT_R11)
1587# define arg1_offset (4*PT_ORIG_R10)
1588# define restore_arg0(tcp, state, val) 0
1589# define restore_arg1(tcp, state, val) 0
1590# define arg0_index 1
1591# define arg1_index 0
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001592# else
1593# define arg0_offset 0
1594# define arg1_offset 4
1595# if defined ARM
1596# define restore_arg0(tcp, state, val) 0
1597# endif
1598# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001599
1600typedef int arg_setup_state;
1601
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001602# define arg_setup(tcp, state) (0)
1603# define arg_finish_change(tcp, state) 0
1604# define get_arg0(tcp, cookie, valp) \
1605 (upeek ((tcp), arg0_offset, (valp)))
1606# define get_arg1(tcp, cookie, valp) \
1607 (upeek ((tcp), arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001608
1609static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001610set_arg0 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001611{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001612 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001613}
1614
1615static int
Roland McGratheb9e2e82009-06-02 16:49:22 -07001616set_arg1 (struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001617{
Roland McGratheb9e2e82009-06-02 16:49:22 -07001618 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001619}
1620
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001621# endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001622
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001623# ifndef restore_arg0
1624# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1625# endif
1626# ifndef restore_arg1
1627# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1628# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001629
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001630# ifndef arg0_index
1631# define arg0_index 0
1632# define arg1_index 1
1633# endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001634
Roland McGrathd81f1d92003-01-09 06:53:34 +00001635int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001636setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001637{
Roland McGrath3291ef22008-05-20 00:34:34 +00001638 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001639 arg_setup_state state;
1640
1641 if (tcp->flags & TCB_BPTSET) {
1642 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1643 return -1;
1644 }
1645
Roland McGrath3291ef22008-05-20 00:34:34 +00001646 /*
1647 * It's a silly kludge to initialize this with a search at runtime.
1648 * But it's better than maintaining another magic thing in the
1649 * godforsaken tables.
1650 */
1651 if (clone_scno[current_personality] == 0) {
1652 int i;
1653 for (i = 0; i < nsyscalls; ++i)
1654 if (sysent[i].sys_func == sys_clone) {
1655 clone_scno[current_personality] = i;
1656 break;
1657 }
1658 }
1659
Roland McGrath76989d72005-06-07 23:21:31 +00001660 switch (known_scno(tcp)) {
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001661# ifdef SYS_vfork
Roland McGrath9383c6c2003-01-18 00:19:31 +00001662 case SYS_vfork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001663# endif
1664# ifdef SYS_fork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001665 case SYS_fork:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001666# endif
1667# if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001668 if (arg_setup (tcp, &state) < 0
1669 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1670 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
Roland McGrath3291ef22008-05-20 00:34:34 +00001671 || change_syscall(tcp, clone_scno[current_personality]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001672 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1673 || set_arg1 (tcp, &state, 0) < 0
1674 || arg_finish_change (tcp, &state) < 0)
1675 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001676 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1677 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001678 tcp->flags |= TCB_BPTSET;
1679 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001680# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001681
1682 case SYS_clone:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001683# ifdef SYS_clone2
Roland McGrathd81f1d92003-01-09 06:53:34 +00001684 case SYS_clone2:
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001685# endif
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001686 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1687 contrary to x86 SYS_vfork above. Even on x86 we turn the
1688 vfork semantics into plain fork - each application must not
1689 depend on the vfork specifics according to POSIX. We would
1690 hang waiting for the parent resume otherwise. We need to
1691 clear also CLONE_VM but only in the CLONE_VFORK case as
1692 otherwise we would break pthread_create. */
1693
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001694 if ((arg_setup (tcp, &state) < 0
1695 || set_arg0 (tcp, &state,
1696 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001697 & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
1698 ? CLONE_VFORK | CLONE_VM : 0)) < 0
Roland McGrathd6ff0d52008-07-18 01:09:44 +00001699 || arg_finish_change (tcp, &state) < 0))
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001700 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001701 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001702 tcp->inst[0] = tcp->u_arg[arg0_index];
1703 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001704 return 0;
1705
1706 default:
1707 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1708 tcp->scno, tcp->pid);
1709 break;
1710 }
1711
1712 return -1;
1713}
1714
1715int
1716clearbpt(tcp)
1717struct tcb *tcp;
1718{
1719 arg_setup_state state;
1720 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001721 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1722 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001723 || arg_finish_change (tcp, &state))
1724 return -1;
1725 tcp->flags &= ~TCB_BPTSET;
1726 return 0;
1727}
1728
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001729# else /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001730
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731int
1732setbpt(tcp)
1733struct tcb *tcp;
1734{
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001735# ifdef LINUX
1736 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1737# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738 /* We simply use the SunOS breakpoint code. */
1739
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001740 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001741 unsigned long inst;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001742# define LOOPA 0x30800000 /* ba,a 0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743
1744 if (tcp->flags & TCB_BPTSET) {
1745 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1746 return -1;
1747 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001748 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1749 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750 return -1;
1751 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001752 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001753 errno = 0;
1754 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1755 if(errno) {
1756 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001758 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759
1760 /*
1761 * XXX - BRUTAL MODE ON
1762 * We cannot set a real BPT in the child, since it will not be
1763 * traced at the moment it will reach the trap and would probably
1764 * die with a core dump.
1765 * Thus, we are force our way in by taking out two instructions
1766 * and insert an eternal loop instead, in expectance of the SIGSTOP
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001767 * generated by our PTRACE_ATTACH.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768 * Of cause, if we evaporate ourselves in the middle of all this...
1769 */
1770 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001771 inst = LOOPA;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001772# if defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001773 inst <<= 32;
1774 inst |= (tcp->inst[0] & 0xffffffffUL);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001775# endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07001776 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1777 if(errno) {
1778 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001780 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 tcp->flags |= TCB_BPTSET;
1782
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001783# else /* !SPARC && !SPARC64 */
1784# ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001785 if (ia32) {
1786# define LOOP 0x0000feeb
1787 if (tcp->flags & TCB_BPTSET) {
1788 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1789 tcp->pid);
1790 return -1;
1791 }
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001792 if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001793 return -1;
1794 if (debug)
1795 fprintf(stderr, "[%d] setting bpt at %lx\n",
1796 tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001797 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1798 (char *) tcp->baddr, 0);
1799 if (errno) {
1800 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001801 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001802 }
1803 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1804 if (errno) {
1805 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001806 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001808 tcp->flags |= TCB_BPTSET;
1809 } else {
1810 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001811 * Our strategy here is to replace the bundle that
1812 * contained the clone() syscall with a bundle of the
1813 * form:
1814 *
1815 * { 1: br 1b; br 1b; br 1b }
1816 *
1817 * This ensures that the newly forked child will loop
1818 * endlessly until we've got a chance to attach to it.
1819 */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001820# define LOOP0 0x0000100000000017
1821# define LOOP1 0x4000000000200000
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001822 unsigned long addr, ipsr;
1823 pid_t pid;
1824
1825 pid = tcp->pid;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001826 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001827 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001828 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001829 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001830 /* store "ri" in low two bits */
1831 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001832
Roland McGratheb9e2e82009-06-02 16:49:22 -07001833 errno = 0;
1834 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1835 0);
1836 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1837 0);
1838 if (errno) {
1839 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001840 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001841 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001842
Roland McGratheb9e2e82009-06-02 16:49:22 -07001843 errno = 0;
1844 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1845 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1846 if (errno) {
1847 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001848 return -1;
1849 }
1850 tcp->flags |= TCB_BPTSET;
1851 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001852# else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001854# if defined (I386) || defined(X86_64)
1855# define LOOP 0x0000feeb
1856# elif defined (M68K)
1857# define LOOP 0x60fe0000
1858# elif defined (ALPHA)
1859# define LOOP 0xc3ffffff
1860# elif defined (POWERPC)
1861# define LOOP 0x48000000
1862# elif defined(ARM)
1863# define LOOP 0xEAFFFFFE
1864# elif defined(MIPS)
1865# define LOOP 0x1000ffff
1866# elif defined(S390)
1867# define LOOP 0xa7f40000 /* BRC 15,0 */
1868# elif defined(S390X)
1869# define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1870# elif defined(HPPA)
1871# define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1872# elif defined(SH)
1873# ifdef __LITTLE_ENDIAN__
1874# define LOOP 0x0000affe
1875# else
1876# define LOOP 0xfeaf0000
1877# endif
1878# else
1879# error unknown architecture
1880# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881
1882 if (tcp->flags & TCB_BPTSET) {
1883 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1884 return -1;
1885 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001886# if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001887 if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001888 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001889# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001890 if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001891 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001892# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001893 if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001894 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001895# elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001897# elif defined (ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001899# elif defined (MIPS)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001900 return -1; /* FIXME: I do not know what i do - Flo */
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001901# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001902 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001904# elif defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001905 if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001906 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001907# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001908 if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001909 return -1;
1910 tcp->baddr &= ~0x03;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001911# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001912 if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
1913 return -1;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001914# else
1915# error unknown architecture
1916# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917 if (debug)
1918 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001919 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1920 if (errno) {
1921 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001923 }
1924 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1925 if (errno) {
1926 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927 return -1;
1928 }
1929 tcp->flags |= TCB_BPTSET;
1930
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001931# endif /* !IA64 */
1932# endif /* !SPARC && !SPARC64 */
1933# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001935# ifdef SUNOS4
1936# ifdef SPARC /* This code is slightly sparc specific */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001938 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001939# define BPT 0x91d02001 /* ta 1 */
1940# define LOOP 0x10800000 /* ba 0 */
1941# define LOOPA 0x30800000 /* ba,a 0 */
1942# define NOP 0x01000000
1943# if LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944 static int loopdeloop[1] = {LOOPA};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001945# else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 static int loopdeloop[2] = {LOOP, NOP};
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001947# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948
1949 if (tcp->flags & TCB_BPTSET) {
1950 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1951 return -1;
1952 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001953 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1954 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 return -1;
1956 }
1957 tcp->baddr = regs.r_o7 + 8;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001958 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1959 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1960 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 return -1;
1962 }
1963
1964 /*
1965 * XXX - BRUTAL MODE ON
1966 * We cannot set a real BPT in the child, since it will not be
1967 * traced at the moment it will reach the trap and would probably
1968 * die with a core dump.
1969 * Thus, we are force our way in by taking out two instructions
1970 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1971 * generated by out PTRACE_ATTACH.
1972 * Of cause, if we evaporate ourselves in the middle of all this...
1973 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001974 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 sizeof loopdeloop, (char *) loopdeloop) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001976 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977 return -1;
1978 }
1979 tcp->flags |= TCB_BPTSET;
1980
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001981# endif /* SPARC */
1982# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983
1984 return 0;
1985}
1986
1987int
1988clearbpt(tcp)
1989struct tcb *tcp;
1990{
1991
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001992# ifdef LINUX
1993 DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1994# if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 long eip;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001996# elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001998# elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002000# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002002# elif defined(HPPA)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002003 long iaoq;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002004# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002005 long pc;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002006# endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002008# if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 /* Again, we borrow the SunOS breakpoint code. */
2010 if (!(tcp->flags & TCB_BPTSET)) {
2011 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2012 return -1;
2013 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002014 errno = 0;
2015 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2016 if(errno) {
2017 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018 return -1;
2019 }
2020 tcp->flags &= ~TCB_BPTSET;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002021# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002022 if (ia32) {
2023 unsigned long addr;
2024
2025 if (debug)
2026 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2027 if (!(tcp->flags & TCB_BPTSET)) {
2028 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2029 return -1;
2030 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002031 errno = 0;
2032 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2033 if (errno) {
2034 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002035 return -1;
2036 }
2037 tcp->flags &= ~TCB_BPTSET;
2038
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002039 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002040 return -1;
2041 if (addr != tcp->baddr) {
2042 /* The breakpoint has not been reached yet. */
2043 if (debug)
2044 fprintf(stderr,
2045 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2046 addr, tcp->baddr);
2047 return 0;
2048 }
2049 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002050 unsigned long addr, ipsr;
2051 pid_t pid;
2052
2053 pid = tcp->pid;
2054
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002055 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002056 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002057 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002058 return -1;
2059
2060 /* restore original bundle: */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002061 errno = 0;
2062 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
2063 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
2064 if (errno) {
2065 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002066 return -1;
2067 }
2068
2069 /* restore original "ri" in ipsr: */
2070 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002071 errno = 0;
2072 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
2073 if (errno) {
2074 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002075 return -1;
2076 }
2077
2078 tcp->flags &= ~TCB_BPTSET;
2079
2080 if (addr != (tcp->baddr & ~0x3)) {
2081 /* the breakpoint has not been reached yet. */
2082 if (debug)
2083 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2084 addr, tcp->baddr);
2085 return 0;
2086 }
2087 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002088# else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089
2090 if (debug)
2091 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2092 if (!(tcp->flags & TCB_BPTSET)) {
2093 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2094 return -1;
2095 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002096 errno = 0;
2097 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2098 if (errno) {
2099 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100 return -1;
2101 }
2102 tcp->flags &= ~TCB_BPTSET;
2103
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002104# ifdef I386
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002105 if (upeek(tcp, 4*EIP, &eip) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106 return -1;
2107 if (eip != tcp->baddr) {
2108 /* The breakpoint has not been reached yet. */
2109 if (debug)
2110 fprintf(stderr,
2111 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2112 eip, tcp->baddr);
2113 return 0;
2114 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002115# elif defined(X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002116 if (upeek(tcp, 8*RIP, &eip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002117 return -1;
2118 if (eip != tcp->baddr) {
2119 /* The breakpoint has not been reached yet. */
2120 if (debug)
2121 fprintf(stderr,
2122 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2123 eip, tcp->baddr);
2124 return 0;
2125 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002126# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002127 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 return -1;
2129 if (pc != tcp->baddr) {
2130 /* The breakpoint has not been reached yet. */
2131 if (debug)
2132 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2133 pc, tcp->baddr);
2134 return 0;
2135 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002136# elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002137 if (upeek(tcp, 4*PT_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 return -1;
2139 if (pc != tcp->baddr) {
2140 /* The breakpoint has not been reached yet. */
2141 if (debug)
2142 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2143 pc, tcp->baddr);
2144 return 0;
2145 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002146# elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002147 if (upeek(tcp, REG_PC, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 return -1;
2149 if (pc != tcp->baddr) {
2150 /* The breakpoint has not been reached yet. */
2151 if (debug)
2152 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2153 pc, tcp->baddr);
2154 return 0;
2155 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002156# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002157 if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002158 return -1;
2159 iaoq &= ~0x03;
2160 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2161 /* The breakpoint has not been reached yet. */
2162 if (debug)
2163 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2164 iaoq, tcp->baddr);
2165 return 0;
2166 }
2167 iaoq = tcp->baddr | 3;
2168 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2169 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2170 * has no significant effect.
2171 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002172 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2173 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002174# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002175 if (upeek(tcp, 4*REG_PC, &pc) < 0)
2176 return -1;
2177 if (pc != tcp->baddr) {
2178 /* The breakpoint has not been reached yet. */
2179 if (debug)
2180 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2181 pc, tcp->baddr);
2182 return 0;
2183 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002184
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002185# endif /* arch */
2186# endif /* !SPARC && !SPARC64 && !IA64 */
2187# endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002189# ifdef SUNOS4
2190# ifdef SPARC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002191
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002192# if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00002193 struct regs regs;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002194# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195
2196 if (!(tcp->flags & TCB_BPTSET)) {
2197 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2198 return -1;
2199 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002200 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 sizeof tcp->inst, (char *) tcp->inst) < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002202 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 return -1;
2204 }
2205 tcp->flags &= ~TCB_BPTSET;
2206
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002207# if !LOOPA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208 /*
2209 * Since we don't have a single instruction breakpoint, we may have
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002210 * to adjust the program counter after removing our `breakpoint'.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002212 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2213 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002214 return -1;
2215 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002216 if ((regs.r_pc < tcp->baddr) ||
2217 (regs.r_pc > tcp->baddr + 4)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 /* The breakpoint has not been reached yet */
2219 if (debug)
2220 fprintf(stderr,
2221 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002222 regs.r_pc, tcp->baddr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002223 return 0;
2224 }
2225 if (regs.r_pc != tcp->baddr)
2226 if (debug)
2227 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2228 regs.r_pc, tcp->baddr);
2229
2230 regs.r_pc = tcp->baddr;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002231 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2232 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 return -1;
2234 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002235# endif /* LOOPA */
2236# endif /* SPARC */
2237# endif /* SUNOS4 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002238
2239 return 0;
2240}
2241
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002242# endif /* !defined LINUX */
Roland McGrathd81f1d92003-01-09 06:53:34 +00002243
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002244#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002246
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002247#ifdef SUNOS4
2248
2249static int
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002250getex(tcp, hdr)
2251struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002252struct exec *hdr;
2253{
2254 int n;
2255
2256 for (n = 0; n < sizeof *hdr; n += 4) {
2257 long res;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002258 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 return -1;
2260 memcpy(((char *) hdr) + n, &res, 4);
2261 }
2262 if (debug) {
2263 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2264 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2265 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2266 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2267 }
2268 return 0;
2269}
2270
2271int
2272fixvfork(tcp)
2273struct tcb *tcp;
2274{
2275 int pid = tcp->pid;
2276 /*
2277 * Change `vfork' in a freshly exec'ed dynamically linked
2278 * executable's (internal) symbol table to plain old `fork'
2279 */
2280
2281 struct exec hdr;
2282 struct link_dynamic dyn;
2283 struct link_dynamic_2 ld;
2284 char *strtab, *cp;
2285
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002286 if (getex(tcp, &hdr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287 return -1;
2288 if (!hdr.a_dynamic)
2289 return -1;
2290
2291 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2292 fprintf(stderr, "Cannot read DYNAMIC\n");
2293 return -1;
2294 }
2295 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2296 fprintf(stderr, "Cannot read link_dynamic_2\n");
2297 return -1;
2298 }
2299 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002300 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301 return -1;
2302 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304 (int)ld.ld_symb_size, strtab) < 0)
2305 goto err;
2306
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002307# if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2309 fprintf(stderr, "[symbol: %s]\n", cp);
2310 cp += strlen(cp)+1;
2311 }
2312 return 0;
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00002313# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2315 if (strcmp(cp, "_vfork") == 0) {
2316 if (debug)
2317 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2318 strcpy(cp, "_fork");
2319 break;
2320 }
2321 cp += strlen(cp)+1;
2322 }
2323 if (cp < strtab + ld.ld_symb_size)
2324 /*
2325 * Write entire symbol table back to avoid
2326 * memory alignment bugs in ptrace
2327 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002328 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 (int)ld.ld_symb_size, strtab) < 0)
2330 goto err;
2331
2332 free(strtab);
2333 return 0;
2334
2335err:
2336 free(strtab);
2337 return -1;
2338}
2339
2340#endif /* SUNOS4 */