2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
39 #include <sys/syscall.h>
41 #include <sys/param.h>
47 #include <machine/reg.h>
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 # define ia64_fpreg XXX_ia64_fpreg
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 # define pt_all_user_regs XXX_pt_all_user_regs
72 #include <linux/ptrace.h>
74 # undef pt_all_user_regs
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
81 #if defined(LINUXSPARC)
83 # define fpq kernel_fpq
85 # define fpu kernel_fpu
93 # undef PTRACE_GETREGS
94 # define PTRACE_GETREGS PTRACE_GETREGS64
95 # undef PTRACE_SETREGS
96 # define PTRACE_SETREGS PTRACE_SETREGS64
99 #if !defined(__GLIBC__)
101 #include <linux/unistd.h>
103 #define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
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" \
115 #if defined (SPARC64)
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
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"); \
130 return (type) __res; \
135 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
145 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
148 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
165 return a->tv_sec || a->tv_usec;
170 struct timeval *a, *b;
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
185 return tv->tv_sec + tv->tv_usec/1000000.0;
190 struct timeval *tv, *a, *b;
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
196 tv->tv_usec -= 1000000;
202 struct timeval *tv, *a, *b;
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
208 tv->tv_usec += 1000000;
214 struct timeval *tv, *a;
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
224 struct timeval *tv, *a;
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
234 const struct xlat *xlat;
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
244 * Print entry in struct xlat table, if there.
247 printxval(xlat, val, dflt)
248 const struct xlat *xlat;
252 char *str = xlookup(xlat, val);
257 tprintf("%#x /* %s */", val, dflt);
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
266 addflags(xlat, flags)
267 const struct xlat *xlat;
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
280 tprintf("|%#x", flags);
287 printflags(xlat, flags)
288 const struct xlat *xlat;
294 if (flags == 0 && xlat->val == 0) {
295 tprintf("%s", xlat->str);
300 for (n = 0; xlat->str; xlat++) {
301 if (xlat->val && (flags & xlat->val) == xlat->val) {
302 tprintf("%s%s", sep, xlat->str);
309 tprintf("%s%#x", sep, flags);
316 printnum(tcp, addr, fmt)
327 if (umove(tcp, addr, &num) < 0) {
328 tprintf("%#lx", addr);
342 tprintf((uid == -1) ? "%ld" : "%lu", uid);
345 static char path[MAXPATHLEN + 1];
351 char buf[2 * MAXPATHLEN + 1];
354 if (!strpbrk(str, "\"\'\\")) {
355 tprintf("\"%s\"", str);
358 for (s = buf; *str; str++) {
360 case '\"': case '\'': case '\\':
361 *s++ = '\\'; *s++ = *str; break;
367 tprintf("\"%s\"", buf);
375 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
376 tprintf("%#lx", addr);
383 printpathn(tcp, addr, n)
388 if (umovestr(tcp, addr, n, path) < 0)
389 tprintf("%#lx", addr);
397 printstr(tcp, addr, len)
402 static unsigned char *str = NULL;
412 if ((str = malloc(max_strlen)) == NULL
413 || (outstr = malloc(2*max_strlen)) == NULL) {
414 fprintf(stderr, "printstr: no memory\n");
415 tprintf("%#lx", addr);
419 outend = outstr + max_strlen * 2 - 10;
422 if (umovestr(tcp, addr, n, (char *) str) < 0) {
423 tprintf("%#lx", addr);
428 n = MIN(len, max_strlen);
429 if (umoven(tcp, addr, n, (char *) str) < 0) {
430 tprintf("%#lx", addr);
439 for (i = 0; i < n; i++) {
441 if (len < 0 && c == '\0')
443 if (!isprint(c) && !isspace(c)) {
454 for (i = 0; i < n; i++) {
456 if (len < 0 && c == '\0')
458 sprintf(s, "\\x%02x", c);
465 for (i = 0; i < n; i++) {
467 if (len < 0 && c == '\0')
470 case '\"': case '\'': case '\\':
471 *s++ = '\\'; *s++ = c; break;
473 *s++ = '\\'; *s++ = 'f'; break;
475 *s++ = '\\'; *s++ = 'n'; break;
477 *s++ = '\\'; *s++ = 'r'; break;
479 *s++ = '\\'; *s++ = 't'; break;
481 *s++ = '\\'; *s++ = 'v'; break;
485 else if (i < n - 1 && isdigit(str[i + 1])) {
486 sprintf(s, "\\%03o", c);
490 sprintf(s, "\\%o", c);
501 if (i < len || (len < 0 && (i == n || s > outend))) {
502 *s++ = '.'; *s++ = '.'; *s++ = '.';
505 tprintf("%s", outstr);
510 dumpiov(tcp, len, addr)
519 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
520 fprintf(stderr, "dump: No memory");
523 if (umoven(tcp, addr,
524 len * sizeof *iov, (char *) iov) >= 0) {
526 for (i = 0; i < len; i++) {
527 /* include the buffer number to make it easy to
528 * match up the trace with the source */
529 tprintf(" * %lu bytes in buffer %d\n",
530 (unsigned long)iov[i].iov_len, i);
531 dumpstr(tcp, (long) iov[i].iov_base,
541 dumpstr(tcp, addr, len)
546 static int strsize = -1;
547 static unsigned char *str;
548 static char outstr[80];
555 if ((str = malloc(len)) == NULL) {
556 fprintf(stderr, "dump: no memory\n");
562 if (umoven(tcp, addr, len, (char *) str) < 0)
565 for (i = 0; i < len; i += 16) {
567 sprintf(s, " | %05x ", i);
569 for (j = 0; j < 16; j++) {
573 sprintf(s, " %02x", str[i + j]);
577 *s++ = ' '; *s++ = ' '; *s++ = ' ';
580 *s++ = ' '; *s++ = ' ';
581 for (j = 0; j < 16; j++) {
585 if (isprint(str[i + j]))
593 tprintf("%s |\n", outstr);
597 #define PAGMASK (~(PAGSIZ - 1))
599 * move `len' bytes of data from process `pid'
600 * at address `addr' to our space at `laddr'
603 umoven(tcp, addr, len, laddr)
616 char x[sizeof(long)];
619 if (addr & (sizeof(long) - 1)) {
620 /* addr not a multiple of sizeof(long) */
621 n = addr - (addr & -sizeof(long)); /* residue */
622 addr &= -sizeof(long); /* residue */
624 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
626 if (started && (errno==EPERM || errno==EIO)) {
627 /* Ran into 'end of memory' - stupid "printpath" */
630 /* But if not started, we had a bogus address. */
631 perror("ptrace: umoven");
635 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
636 addr += sizeof(long), laddr += m, len -= m;
640 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
642 if (started && (errno==EPERM || errno==EIO)) {
643 /* Ran into 'end of memory' - stupid "printpath" */
647 perror("ptrace: umoven");
651 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
652 addr += sizeof(long), laddr += m, len -= m;
662 char x[sizeof(long)];
665 if (addr & (sizeof(long) - 1)) {
666 /* addr not a multiple of sizeof(long) */
667 n = addr - (addr & -sizeof(long)); /* residue */
668 addr &= -sizeof(long); /* residue */
670 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
675 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
676 addr += sizeof(long), laddr += m, len -= m;
680 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
685 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
686 addr += sizeof(long), laddr += m, len -= m;
692 n = MIN(len, PAGSIZ);
693 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
694 if (ptrace(PTRACE_READDATA, pid,
695 (char *) addr, len, laddr) < 0) {
696 perror("umoven: ptrace(PTRACE_READDATA, ...)");
708 #ifdef HAVE_MP_PROCFS
709 int fd = tcp->pfd_as;
713 lseek(fd, addr, SEEK_SET);
714 if (read(fd, laddr, len) == -1)
716 #endif /* USE_PROCFS */
722 * like `umove' but make the additional effort of looking
723 * for a terminating zero byte.
726 umovestr(tcp, addr, len, laddr)
733 #ifdef HAVE_MP_PROCFS
734 int fd = tcp->pfd_as;
738 /* Some systems (e.g. FreeBSD) can be upset if we read off the
739 end of valid memory, avoid this by trying to read up
740 to page boundaries. But we don't know what a page is (and
741 getpagesize(2) (if it exists) doesn't necessarily return
742 hardware page size). Assume all pages >= 1024 (a-historical
745 int page = 1024; /* How to find this? */
746 int move = page - (addr & (page - 1));
749 lseek(fd, addr, SEEK_SET);
752 if (move > left) move = left;
753 if ((move = read(fd, laddr, move)) <= 0)
754 return left != len ? 0 : -1;
755 if (memchr (laddr, 0, move)) break;
761 #else /* !USE_PROCFS */
767 char x[sizeof(long)];
770 if (addr & (sizeof(long) - 1)) {
771 /* addr not a multiple of sizeof(long) */
772 n = addr - (addr & -sizeof(long)); /* residue */
773 addr &= -sizeof(long); /* residue */
775 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
777 if (started && (errno==EPERM || errno==EIO)) {
778 /* Ran into 'end of memory' - stupid "printpath" */
785 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
786 while (n & (sizeof(long) - 1))
787 if (u.x[n++] == '\0')
789 addr += sizeof(long), laddr += m, len -= m;
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
795 if (started && (errno==EPERM || errno==EIO)) {
796 /* Ran into 'end of memory' - stupid "printpath" */
803 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
804 for (i = 0; i < sizeof(long); i++)
808 addr += sizeof(long), laddr += m, len -= m;
810 #endif /* !USE_PROCFS */
815 #if !defined (SPARC) && !defined(SPARC64)
816 #define PTRACE_WRITETEXT 101
817 #define PTRACE_WRITEDATA 102
818 #endif /* !SPARC && !SPARC64 */
824 uload(cmd, pid, addr, len, laddr)
835 n = MIN(len, PAGSIZ);
836 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
837 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
838 perror("uload: ptrace(PTRACE_WRITE, ...)");
850 char x[sizeof(long)];
853 if (cmd == PTRACE_WRITETEXT) {
854 peek = PTRACE_PEEKTEXT;
855 poke = PTRACE_POKETEXT;
858 peek = PTRACE_PEEKDATA;
859 poke = PTRACE_POKEDATA;
861 if (addr & (sizeof(long) - 1)) {
862 /* addr not a multiple of sizeof(long) */
863 n = addr - (addr & -sizeof(long)); /* residue */
864 addr &= -sizeof(long);
866 u.val = ptrace(peek, pid, (char *) addr, 0);
868 perror("uload: POKE");
871 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
872 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
873 perror("uload: POKE");
876 addr += sizeof(long), laddr += m, len -= m;
879 if (len < sizeof(long))
880 u.val = ptrace(peek, pid, (char *) addr, 0);
881 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
882 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
883 perror("uload: POKE");
886 addr += sizeof(long), laddr += m, len -= m;
893 tload(pid, addr, len, laddr)
898 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
902 dload(pid, addr, len, laddr)
908 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
923 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
925 static int is_sun4m = -1;
928 /* Round up the usual suspects. */
929 if (is_sun4m == -1) {
930 if (uname(&name) < 0) {
931 perror("upeek: uname?");
934 is_sun4m = strcmp(name.machine, "sun4m") == 0;
936 extern const struct xlat struct_user_offsets[];
937 const struct xlat *x;
939 for (x = struct_user_offsets; x->str; x++)
946 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
948 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
949 if (val == -1 && errno) {
951 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
959 #endif /* !USE_PROCFS */
969 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
971 #elif defined(X86_64)
972 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
975 if (upeek(tcp->pid, PT_B0, &pc) < 0)
978 if (upeek(tcp->pid, 4*15, &pc) < 0)
980 #elif defined(POWERPC)
981 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
984 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
987 if (upeek(tcp->pid, REG_PC, &pc) < 0)
990 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
992 #elif defined(SPARC) || defined(SPARC64)
994 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
997 #elif defined(S390) || defined(S390X)
998 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1001 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1004 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1007 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1015 * Return current program counter for `pid'
1016 * Assumes PC is never 0xffffffff
1020 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1021 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1034 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1036 #endif /* FREEBSD */
1048 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1049 tprintf("[????????] ");
1052 tprintf("[%08lx] ", eip);
1053 #elif defined(X86_64)
1056 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1057 tprintf("[????????] ");
1060 tprintf("[%16lx] ", rip);
1064 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1065 tprintf("[????????] ");
1068 tprintf("[%08lx] ", ip);
1069 #elif defined(POWERPC)
1072 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1073 tprintf ("[????????] ");
1076 tprintf("[%08lx] ", pc);
1080 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1081 tprintf ("[????????] ");
1084 tprintf("[%08lx] ", pc);
1085 #elif defined(ALPHA)
1088 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1089 tprintf ("[????????] ");
1092 tprintf("[%08lx] ", pc);
1093 #elif defined(SPARC) || defined(SPARC64)
1095 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1096 tprintf("[????????] ");
1099 tprintf("[%08lx] ", regs.r_pc);
1103 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1104 tprintf ("[????????] ");
1107 tprintf("[%08lx] ", pc);
1111 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1112 tprintf ("[????????] ");
1115 tprintf("[%08lx] ", pc);
1119 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1120 tprintf ("[????????] ");
1123 tprintf("[%08lx] ", pc);
1127 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1128 tprintf ("[????????] ");
1131 tprintf("[%08lx] ", pc);
1135 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1136 tprintf("[????????] ");
1139 tprintf("[%08lx] ", pc);
1140 #endif /* !architecture */
1146 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1147 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1148 tprintf("[????????] ");
1151 tprintf("[%08x] ", regs.r_o7);
1156 tprintf("[????????] ");
1161 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1162 tprintf("[%08x] ", regs.r_eip);
1163 #endif /* FREEBSD */
1170 #include <sys/syscall.h>
1171 #ifndef CLONE_PTRACE
1172 # define CLONE_PTRACE 0x00002000
1177 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1178 subsystem has them for x86... */
1180 #define SYS_vfork 190
1182 typedef unsigned long *arg_setup_state;
1185 arg_setup(struct tcb *tcp, arg_setup_state *state)
1187 unsigned long *bsp, cfm, sof, sol;
1192 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1194 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1197 sof = (cfm >> 0) & 0x7f;
1198 sol = (cfm >> 7) & 0x7f;
1199 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1205 # define arg_finish_change(tcp, state) 0
1209 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1214 ret = upeek (tcp->pid, PT_R11, valp);
1217 (unsigned long) ia64_rse_skip_regs(*state, 0),
1218 sizeof(long), (void *) valp);
1223 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1228 ret = upeek (tcp->pid, PT_R9, valp);
1231 (unsigned long) ia64_rse_skip_regs(*state, 1),
1232 sizeof(long), (void *) valp);
1238 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1240 int req = PTRACE_POKEDATA;
1244 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1245 req = PTRACE_POKEUSER;
1247 ap = ia64_rse_skip_regs(*state, 0);
1249 ptrace(req, tcp->pid, ap, val);
1250 return errno ? -1 : 0;
1254 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1256 int req = PTRACE_POKEDATA;
1260 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1261 req = PTRACE_POKEUSER;
1263 ap = ia64_rse_skip_regs(*state, 1);
1265 ptrace(req, tcp->pid, ap, val);
1266 return errno ? -1 : 0;
1269 #elif defined (SPARC) || defined (SPARC64)
1271 typedef struct regs arg_setup_state;
1273 # define arg_setup(tcp, state) \
1274 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1275 # define arg_finish_change(tcp, state) \
1276 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1278 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1279 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1280 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1281 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1282 # define restore_arg0(tcp, state, val) 0
1286 # if defined S390 || defined S390X
1287 /* Note: this is only true for the `clone' system call, which handles
1288 arguments specially. We could as well say that its first two arguments
1289 are swapped relative to other architectures, but that would just be
1290 another #ifdef in the calls. */
1291 # define arg0_offset PT_GPR3
1292 # define arg1_offset PT_ORIGGPR2
1293 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1294 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1295 # define arg0_index 1
1296 # define arg1_index 0
1297 # elif defined (ALPHA) || defined (MIPS)
1298 # define arg0_offset REG_A0
1299 # define arg1_offset (REG_A0+1)
1300 # elif defined (POWERPC)
1301 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1302 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1303 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1304 # elif defined (HPPA)
1305 # define arg0_offset PT_GR26
1306 # define arg1_offset (PT_GR26-4)
1307 # elif defined (X86_64)
1308 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1309 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1311 # define arg0_offset (4*(REG_REG0+4))
1312 # define arg1_offset (4*(REG_REG0+5))
1313 # elif defined (SH64)
1314 /* ABI defines arg0 & 1 in r2 & r3 */
1315 # define arg0_offset (REG_OFFSET+16)
1316 # define arg1_offset (REG_OFFSET+24)
1317 # define restore_arg0(tcp, state, val) 0
1319 # define arg0_offset 0
1320 # define arg1_offset 4
1322 # define restore_arg0(tcp, state, val) 0
1326 typedef int arg_setup_state;
1328 # define arg_setup(tcp, state) (0)
1329 # define arg_finish_change(tcp, state) 0
1330 # define get_arg0(tcp, cookie, valp) \
1331 (upeek ((tcp)->pid, arg0_offset, (valp)))
1332 # define get_arg1(tcp, cookie, valp) \
1333 (upeek ((tcp)->pid, arg1_offset, (valp)))
1336 set_arg0 (struct tcb *tcp, void *cookie, long val)
1338 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1342 set_arg1 (struct tcb *tcp, void *cookie, long val)
1344 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1349 #ifndef restore_arg0
1350 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1352 #ifndef restore_arg1
1353 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1357 # define arg0_index 0
1358 # define arg1_index 1
1365 extern int change_syscall(struct tcb *, int);
1366 arg_setup_state state;
1368 if (tcp->flags & TCB_BPTSET) {
1369 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1373 switch (tcp->scno) {
1380 #if defined SYS_fork || defined SYS_vfork
1381 if (arg_setup (tcp, &state) < 0
1382 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1383 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1384 || change_syscall(tcp, SYS_clone) < 0
1385 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1386 || set_arg1 (tcp, &state, 0) < 0
1387 || arg_finish_change (tcp, &state) < 0)
1389 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1390 tcp->u_arg[arg1_index] = 0;
1391 tcp->flags |= TCB_BPTSET;
1399 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1400 && (arg_setup (tcp, &state) < 0
1401 || set_arg0 (tcp, &state,
1402 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1403 || arg_finish_change (tcp, &state) < 0))
1405 tcp->flags |= TCB_BPTSET;
1406 tcp->inst[0] = tcp->u_arg[arg0_index];
1407 tcp->inst[1] = tcp->u_arg[arg1_index];
1411 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1412 tcp->scno, tcp->pid);
1423 arg_setup_state state;
1424 if (arg_setup (tcp, &state) < 0
1425 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1426 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1427 || arg_finish_change (tcp, &state))
1429 tcp->flags &= ~TCB_BPTSET;
1441 #if defined (SPARC) || defined (SPARC64)
1442 /* We simply use the SunOS breakpoint code. */
1446 #define LOOPA 0x30800000 /* ba,a 0 */
1448 if (tcp->flags & TCB_BPTSET) {
1449 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1452 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1453 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1456 tcp->baddr = regs.r_o7 + 8;
1458 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1460 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1465 * XXX - BRUTAL MODE ON
1466 * We cannot set a real BPT in the child, since it will not be
1467 * traced at the moment it will reach the trap and would probably
1468 * die with a core dump.
1469 * Thus, we are force our way in by taking out two instructions
1470 * and insert an eternal loop instead, in expectance of the SIGSTOP
1471 * generated by out PTRACE_ATTACH.
1472 * Of cause, if we evaporate ourselves in the middle of all this...
1476 #if defined (SPARC64)
1478 inst |= (tcp->inst[0] & 0xffffffffUL);
1480 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1482 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1485 tcp->flags |= TCB_BPTSET;
1487 #else /* !SPARC && !SPARC64 */
1490 # define LOOP 0x0000feeb
1491 if (tcp->flags & TCB_BPTSET) {
1492 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1496 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1499 fprintf(stderr, "[%d] setting bpt at %lx\n",
1500 tcp->pid, tcp->baddr);
1501 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1502 (char *) tcp->baddr, 0);
1504 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1507 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1509 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1512 tcp->flags |= TCB_BPTSET;
1515 * Our strategy here is to replace the bundle that
1516 * contained the clone() syscall with a bundle of the
1519 * { 1: br 1b; br 1b; br 1b }
1521 * This ensures that the newly forked child will loop
1522 * endlessly until we've got a chance to attach to it.
1524 # define LOOP0 0x0000100000000017
1525 # define LOOP1 0x4000000000200000
1526 unsigned long addr, ipsr;
1530 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1532 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1534 /* store "ri" in low two bits */
1535 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1538 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1540 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1543 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1548 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1549 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1551 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1554 tcp->flags |= TCB_BPTSET;
1558 #if defined (I386) || defined(X86_64)
1559 #define LOOP 0x0000feeb
1560 #elif defined (M68K)
1561 #define LOOP 0x60fe0000
1562 #elif defined (ALPHA)
1563 #define LOOP 0xc3ffffff
1564 #elif defined (POWERPC)
1565 #define LOOP 0x48000000
1567 #define LOOP 0xEAFFFFFE
1569 #define LOOP 0x1000ffff
1571 #define LOOP 0xa7f40000 /* BRC 15,0 */
1572 #elif defined(S390X)
1573 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1575 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1577 #ifdef __LITTLE_ENDIAN__
1578 #define LOOP 0x0000affe
1580 #define LOOP 0xfeaf0000
1583 #error unknown architecture
1586 if (tcp->flags & TCB_BPTSET) {
1587 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1591 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1593 #elif defined (X86_64)
1594 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1596 #elif defined (M68K)
1597 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1599 #elif defined (ALPHA)
1603 #elif defined (MIPS)
1604 return -1; /* FIXME: I do not know what i do - Flo */
1605 #elif defined (POWERPC)
1606 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1608 #elif defined(S390) || defined(S390X)
1609 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1612 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1614 tcp->baddr &= ~0x03;
1616 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1619 #error unknown architecture
1622 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1623 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1625 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1628 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1630 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1633 tcp->flags |= TCB_BPTSET;
1636 #endif /* SPARC || SPARC64 */
1640 #ifdef SPARC /* This code is slightly sparc specific */
1643 #define BPT 0x91d02001 /* ta 1 */
1644 #define LOOP 0x10800000 /* ba 0 */
1645 #define LOOPA 0x30800000 /* ba,a 0 */
1646 #define NOP 0x01000000
1648 static int loopdeloop[1] = {LOOPA};
1650 static int loopdeloop[2] = {LOOP, NOP};
1653 if (tcp->flags & TCB_BPTSET) {
1654 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1657 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1658 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1661 tcp->baddr = regs.r_o7 + 8;
1662 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1663 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1664 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1669 * XXX - BRUTAL MODE ON
1670 * We cannot set a real BPT in the child, since it will not be
1671 * traced at the moment it will reach the trap and would probably
1672 * die with a core dump.
1673 * Thus, we are force our way in by taking out two instructions
1674 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1675 * generated by out PTRACE_ATTACH.
1676 * Of cause, if we evaporate ourselves in the middle of all this...
1678 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1679 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1680 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1683 tcp->flags |= TCB_BPTSET;
1697 #if defined(I386) || defined(X86_64)
1699 #elif defined(POWERPC)
1703 #elif defined(ALPHA)
1709 #endif /* architecture */
1711 #if defined (SPARC) || defined (SPARC64)
1712 /* Again, we borrow the SunOS breakpoint code. */
1713 if (!(tcp->flags & TCB_BPTSET)) {
1714 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1718 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1720 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1723 tcp->flags &= ~TCB_BPTSET;
1729 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1730 if (!(tcp->flags & TCB_BPTSET)) {
1731 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1735 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1737 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1740 tcp->flags &= ~TCB_BPTSET;
1742 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1744 if (addr != tcp->baddr) {
1745 /* The breakpoint has not been reached yet. */
1748 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1753 unsigned long addr, ipsr;
1758 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1760 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1763 /* restore original bundle: */
1765 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1766 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1768 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1772 /* restore original "ri" in ipsr: */
1773 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1775 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1777 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1781 tcp->flags &= ~TCB_BPTSET;
1783 if (addr != (tcp->baddr & ~0x3)) {
1784 /* the breakpoint has not been reached yet. */
1786 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1791 #else /* !IA64 && !SPARC && !SPARC64 */
1794 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1795 if (!(tcp->flags & TCB_BPTSET)) {
1796 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1800 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1802 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1805 tcp->flags &= ~TCB_BPTSET;
1808 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1810 if (eip != tcp->baddr) {
1811 /* The breakpoint has not been reached yet. */
1814 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1818 #elif defined(X86_64)
1819 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1821 if (eip != tcp->baddr) {
1822 /* The breakpoint has not been reached yet. */
1825 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1829 #elif defined(POWERPC)
1830 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1832 if (pc != tcp->baddr) {
1833 /* The breakpoint has not been reached yet. */
1835 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1840 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1842 if (pc != tcp->baddr) {
1843 /* The breakpoint has not been reached yet. */
1845 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1849 #elif defined(ALPHA)
1850 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1852 if (pc != tcp->baddr) {
1853 /* The breakpoint has not been reached yet. */
1855 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1860 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1863 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1864 /* The breakpoint has not been reached yet. */
1866 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1870 iaoq = tcp->baddr | 3;
1871 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1872 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1873 * has no significant effect.
1875 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1876 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1878 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1880 if (pc != tcp->baddr) {
1881 /* The breakpoint has not been reached yet. */
1883 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1889 #endif /* !SPARC && !SPARC64 && !IA64 */
1899 if (!(tcp->flags & TCB_BPTSET)) {
1900 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1903 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1904 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1905 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1908 tcp->flags &= ~TCB_BPTSET;
1912 * Since we don't have a single instruction breakpoint, we may have
1913 * to adjust the program counter after removing the our `breakpoint'.
1915 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1916 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1919 if ((regs.r_pc < tcp->baddr) ||
1920 (regs.r_pc > tcp->baddr + 4)) {
1921 /* The breakpoint has not been reached yet */
1924 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1925 regs.r_pc, tcp->parent->baddr);
1928 if (regs.r_pc != tcp->baddr)
1930 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1931 regs.r_pc, tcp->baddr);
1933 regs.r_pc = tcp->baddr;
1934 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1935 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1947 #endif /* !USE_PROCFS */
1958 for (n = 0; n < sizeof *hdr; n += 4) {
1960 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1962 memcpy(((char *) hdr) + n, &res, 4);
1965 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1966 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1967 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1968 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1979 * Change `vfork' in a freshly exec'ed dynamically linked
1980 * executable's (internal) symbol table to plain old `fork'
1984 struct link_dynamic dyn;
1985 struct link_dynamic_2 ld;
1988 if (getex(pid, &hdr) < 0)
1993 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1994 fprintf(stderr, "Cannot read DYNAMIC\n");
1997 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1998 fprintf(stderr, "Cannot read link_dynamic_2\n");
2001 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2002 fprintf(stderr, "fixvfork: out of memory\n");
2005 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2006 (int)ld.ld_symb_size, strtab) < 0)
2010 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2011 fprintf(stderr, "[symbol: %s]\n", cp);
2016 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2017 if (strcmp(cp, "_vfork") == 0) {
2019 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2020 strcpy(cp, "_fork");
2025 if (cp < strtab + ld.ld_symb_size)
2027 * Write entire symbol table back to avoid
2028 * memory alignment bugs in ptrace
2030 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2031 (int)ld.ld_symb_size, strtab) < 0)