diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | bjm.c | 12 | ||||
-rwxr-xr-x | config.sub | 4 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | defs.h | 2 | ||||
-rw-r--r-- | desc.c | 2 | ||||
-rw-r--r-- | file.c | 28 | ||||
-rw-r--r-- | linux/dummy.h | 1 | ||||
-rw-r--r-- | linux/syscall.h | 18 | ||||
-rw-r--r-- | mem.c | 21 | ||||
-rw-r--r-- | process.c | 150 | ||||
-rw-r--r-- | signal.c | 29 | ||||
-rw-r--r-- | strace.c | 15 | ||||
-rw-r--r-- | syscall.c | 70 | ||||
-rw-r--r-- | system.c | 4 | ||||
-rw-r--r-- | util.c | 101 |
16 files changed, 398 insertions, 68 deletions
@@ -1,3 +1,7 @@ +2000-02-03 Wichert Akkerman <wakkerma@debian.org> + + * Merge Trillian (ia64) patches + 2000-01-02 Pavel Machek <pavel@ucw.cz> * probe if sys/poll.h exists in configure + minor cleanups @@ -80,7 +80,7 @@ struct tcb *tcp; } else if (tcp->u_rval!=0) { size_t ret; umove(tcp, tcp->u_arg[4], &ret); - tprintf("%#lx, %lu, %d", tcp->u_arg[2], tcp->u_arg[3], ret); + tprintf("%#lx, %lu, %Zu", tcp->u_arg[2], tcp->u_arg[3], ret); } else if (tcp->u_arg[1]==QM_INFO) { struct module_info mi; size_t ret; @@ -89,7 +89,7 @@ struct tcb *tcp; printflags(modflags, mi.flags); tprintf(", usecount=%lu}", mi.usecount); umove(tcp, tcp->u_arg[4], &ret); - tprintf(", %d", ret); + tprintf(", %Zu", ret); } else if ((tcp->u_arg[1]==QM_MODULES) || (tcp->u_arg[1]==QM_DEPS) || (tcp->u_arg[1]==QM_REFS)) { @@ -111,8 +111,8 @@ struct tcb *tcp; } free(data); } else - tprintf(" /* %d entries */ ", ret); - tprintf("}, %d", ret); + tprintf(" /* %Zu entries */ ", ret); + tprintf("}, %Zu", ret); } else if (tcp->u_arg[1]==QM_SYMBOLS) { size_t ret; umove(tcp, tcp->u_arg[4], &ret); @@ -129,8 +129,8 @@ struct tcb *tcp; } free(data); } else - tprintf(" /* %d entries */ ", ret); - tprintf("}, %d", ret); + tprintf(" /* %Zu entries */ ", ret); + tprintf("}, %Zd", ret); } else { printstr(tcp, tcp->u_arg[2], tcp->u_arg[3]); tprintf(", %#lx", tcp->u_arg[4]); @@ -149,7 +149,7 @@ esac case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. - tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \ | alpha | alphaev5 | alphaev56 | alphapca56 | we32k | ns16k | clipper \ @@ -171,7 +171,7 @@ case $basic_machine in exit 1 ;; # Recognize the basic CPU types with company name. - vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ diff --git a/configure.in b/configure.in index 41c0762..0bb6998 100644 --- a/configure.in +++ b/configure.in @@ -38,6 +38,9 @@ case "$host_cpu" in i[3456]86|pentium) arch=i386 ;; +ia64) + arch=ia64 + ;; m68k) arch=m68k ;; @@ -67,7 +70,7 @@ AC_MSG_RESULT($arch) # Autoheader trick. Heh, heh. arch_list=' -@@@syms="$syms I386 M68K SPARC MIPS ALPHA ARM POWERPC"@@@ +@@@syms="$syms I386 IA64 M68K SPARC MIPS ALPHA ARM POWERPC"@@@ ' osarch="$opsys" @@ -39,7 +39,7 @@ /* configuration section */ #ifndef MAX_QUALS -#define MAX_QUALS 1024 /* maximum number of syscalls, signals, etc. */ +#define MAX_QUALS 2048 /* maximum number of syscalls, signals, etc. */ #endif #ifndef MAX_PROCS #define MAX_PROCS 32 /* maximum number of processes tracable */ @@ -104,7 +104,7 @@ static struct xlat whence[] = { static void printflock(tcp, addr, getlk) struct tcb *tcp; -int addr; +long addr; int getlk; { struct flock fl; @@ -480,7 +480,7 @@ struct solstat { static void printstatsol(tcp, addr) struct tcb *tcp; -int addr; +long addr; { struct solstat statbuf; @@ -489,7 +489,7 @@ int addr; return; } if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#x", addr); + tprintf("%#lx", addr); return; } if (umove(tcp, addr, &statbuf) < 0) { @@ -584,7 +584,7 @@ struct stat *statbuf; static void printstat(tcp, addr) struct tcb *tcp; -int addr; +long addr; { struct stat statbuf; @@ -600,7 +600,7 @@ int addr; return; } if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#x", addr); + tprintf("%#lx", addr); return; } if (umove(tcp, addr, &statbuf) < 0) { @@ -615,7 +615,7 @@ int addr; static void printstat64(tcp, addr) struct tcb *tcp; -int addr; +long addr; { struct stat64 statbuf; @@ -631,7 +631,7 @@ int addr; return; } if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#x", addr); + tprintf("%#lx", addr); return; } if (umove(tcp, addr, &statbuf) < 0) { @@ -685,7 +685,7 @@ int addr; } #endif /* STAT64 */ -#ifdef linux +#if defined(linux) && !defined(IA64) static void convertoldstat(oldbuf, newbuf) const struct __old_kernel_stat *oldbuf; @@ -710,7 +710,7 @@ struct stat *newbuf; static void printoldstat(tcp, addr) struct tcb *tcp; -int addr; +long addr; { struct __old_kernel_stat statbuf; struct stat newstatbuf; @@ -727,7 +727,7 @@ int addr; return; } if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#x", addr); + tprintf("%#lx", addr); return; } if (umove(tcp, addr, &statbuf) < 0) { @@ -738,7 +738,7 @@ int addr; convertoldstat(&statbuf, &newstatbuf); realprintstat(tcp, &newstatbuf); } -#endif +#endif /* linux && !IA64 */ int @@ -772,6 +772,7 @@ struct tcb *tcp; #endif } +# if !defined(IA64) int sys_oldstat(tcp) struct tcb *tcp; @@ -784,7 +785,8 @@ struct tcb *tcp; } return 0; } -#endif +# endif /* !IA64 */ +#endif /* linux */ int sys_fstat(tcp) @@ -815,6 +817,7 @@ struct tcb *tcp; #endif } +# if !defined(IA64) int sys_oldfstat(tcp) struct tcb *tcp; @@ -826,6 +829,7 @@ struct tcb *tcp; } return 0; } +# endif /* !IA64 */ #endif int @@ -859,6 +863,7 @@ struct tcb *tcp; #endif } +# if !defined(IA64) int sys_oldlstat(tcp) struct tcb *tcp; @@ -871,6 +876,7 @@ struct tcb *tcp; } return 0; } +# endif /* !IA64 */ #endif diff --git a/linux/dummy.h b/linux/dummy.h index ba9c4b6..2d3a8a9 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -60,7 +60,6 @@ #define sys_umount sys_chdir #define sys_swapon sys_chdir #define sys_swapoff sys_chdir -#define sys_clone sys_fork #define sys_delete_module sys_chdir #define sys_fchdir sys_close #define sys_setfsuid sys_setuid diff --git a/linux/syscall.h b/linux/syscall.h index 2da0f86..956401c 100644 --- a/linux/syscall.h +++ b/linux/syscall.h @@ -109,7 +109,7 @@ int sys_osf_utimes(); #endif -#if !defined(ALPHA) && !defined(MIPS) +#if !defined(ALPHA) && !defined(IA64) && !defined(MIPS) #ifdef POWERPC # define SYS_socket_subcall 256 #else @@ -134,7 +134,7 @@ int sys_osf_utimes(); #define SYS_recvmsg (SYS_socket_subcall + 17) #define SYS_socket_nsubcalls 18 -#endif /* !ALPHA */ +#endif /* !(ALPHA || IA64 || MIPS) */ /* sys_ipc subcalls */ @@ -142,7 +142,7 @@ int sys_semget(), sys_semctl(), sys_semop(); int sys_msgsnd(), sys_msgrcv(), sys_msgget(), sys_msgctl(); int sys_shmat(), sys_shmdt(), sys_shmget(), sys_shmctl(); -#if !defined(ALPHA) && !defined(MIPS) +#if !defined(ALPHA) && !defined(IA64) && !defined(MIPS) #ifdef POWERPC # define SYS_ipc_subcall ((SYS_socket_subcall)+(SYS_socket_nsubcalls)) #else @@ -161,10 +161,18 @@ int sys_shmat(), sys_shmdt(), sys_shmget(), sys_shmctl(); #define SYS_shmctl (SYS_ipc_subcall + 24) #define SYS_ipc_nsubcalls 25 -#endif /* ALPHA */ +#endif /* !(ALPHA || IA64 || MIPS) */ + +#if defined(ALPHA) || defined(IA64) +int sys_getpagesize(); +#endif #ifdef ALPHA -int osf_statfs(), osf_fstatfs(), sys_getpagesize(), sys_madvise(); +int osf_statfs(), osf_fstatfs(), sys_madvise(); +#endif + +#ifdef IA64 +int sys_getpmsg(), sys_putpmsg(); /* STREAMS stuff */ #endif int sys_setpgrp(), sys_gethostname(), sys_getdtablesize(), sys_utimes(); @@ -170,9 +170,28 @@ int sys_old_mmap(tcp) struct tcb *tcp; { long u_arg[6]; - + int i, v; + +#if defined(IA64) + /* + * IA64 processes never call this routine, they only use the + * new `sys_mmap' interface. This code converts the integer + * arguments that the IA32 process pushed onto the stack into + * longs. + * + * Note that addresses with bit 31 set will be sign extended. + * Fortunately, those addresses are not currently being generated + * for IA32 processes so it's not a problem. + */ + for (i = 0; i < 6; i++) + if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1) + return 0; + else + u_arg[i] = v; +#else // defined(IA64) if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1) return 0; +#endif // defined(IA64) return print_mmap(tcp, u_arg); } @@ -70,6 +70,11 @@ #define GETGROUPS_T __kernel_gid_t #endif /* LINUX */ +#if defined(LINUX) && defined(IA64) +# include <asm/ptrace_offsets.h> +# include <asm/rse.h> +#endif + #ifdef HAVE_PRCTL #include <sys/prctl.h> #endif @@ -358,6 +363,18 @@ static struct xlat clone_flags[] = { { 0, NULL }, }; +int +sys_clone(tcp) +struct tcb *tcp; +{ + if (exiting(tcp)) { + tprintf("child_stack=%#lx, flags=", tcp->u_arg[1]); + if (printflags(clone_flags, tcp->u_arg[0]) == 0) + tprintf("0"); + } + return 0; +} + #endif int @@ -369,6 +386,31 @@ struct tcb *tcp; return 0; } +int +setarg(tcp, argnum) + struct tcb *tcp; + int argnum; +{ +#if defined (IA64) + { + unsigned long *bsp, *ap; + + if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) , 0) + return -1; + + ap = ia64_rse_skip_regs(bsp, argnum); + errno = 0; + ptrace(PTRACE_POKEDATA, tcp->pid, ap, tcp->u_arg[argnum]); + if (errno) + return -1; + + } +#else +# error Sorry, not done yet. +#endif + return 0; +} + #ifdef SYS_clone int internal_clone(tcp) @@ -376,18 +418,8 @@ struct tcb *tcp; { struct tcb *tcpchild; int pid; - int dont_follow = 0; if (entering(tcp)) { - tprintf("fn=%#lx, child_stack=%#lx, flags=", - tcp->u_arg[0], tcp->u_arg[1]); - if (printflags(clone_flags, tcp->u_arg[2]) == 0) - tprintf("0"); - tprintf(", args=%#lx", tcp->u_arg[3]); - - /* For now we don't follow clone yet.. we're just preparing the code */ - dont_follow = 1; - - if (!followfork || dont_follow) + if (!followfork) return 0; if (nprocs == MAX_PROCS) { tcp->flags &= ~TCB_FOLLOWFORK; @@ -396,15 +428,8 @@ struct tcb *tcp; } tcp->flags |= TCB_FOLLOWFORK; - /* XXX - * We will take the simple approach and add CLONE_PTRACE to the clone - * options. This only works on Linux 2.2.x and later. This means that - * we break all programs using clone on older kernels.. - * We should try to fallback to the bpt-trick if this fails, but right - * now we don't. - */ - - /* TODO: actually change the flags */ + tcp->u_arg[0] |= CLONE_PTRACE; + setarg(tcp, 0); } else { if (!(tcp->flags & TCB_FOLLOWFORK)) return 0; @@ -448,20 +473,6 @@ struct tcb *tcp; dont_follow = 1; } #endif -#ifdef SYS_clone - /* clone can do many things, not all of which we know how to handle. - Don't do much for now. */ - if (tcp->scno == SYS_clone) { - if (entering(tcp)) { - tprintf("fn=%#lx, child_stack=%#lx, flags=", - tcp->u_arg[0], tcp->u_arg[1]); - if (printflags(clone_flags, tcp->u_arg[2]) == 0) - tprintf("0"); - tprintf(", args=%#lx", tcp->u_arg[3]); - } - dont_follow = 1; - } -#endif if (entering(tcp)) { if (!followfork || dont_follow) return 0; @@ -1719,6 +1730,76 @@ struct xlat struct_user_offsets[] = { { 63, "fp31" }, { 64, "pc" }, #else /* !ALPHA */ +#ifdef IA64 + { PT_F32, "f32" }, { PT_F33, "f33" }, { PT_F34, "f34" }, + { PT_F35, "f35" }, { PT_F36, "f36" }, { PT_F37, "f37" }, + { PT_F38, "f38" }, { PT_F39, "f39" }, { PT_F40, "f40" }, + { PT_F41, "f41" }, { PT_F42, "f42" }, { PT_F43, "f43" }, + { PT_F44, "f44" }, { PT_F45, "f45" }, { PT_F46, "f46" }, + { PT_F47, "f47" }, { PT_F48, "f48" }, { PT_F49, "f49" }, + { PT_F50, "f50" }, { PT_F51, "f51" }, { PT_F52, "f52" }, + { PT_F53, "f53" }, { PT_F54, "f54" }, { PT_F55, "f55" }, + { PT_F56, "f56" }, { PT_F57, "f57" }, { PT_F58, "f58" }, + { PT_F59, "f59" }, { PT_F60, "f60" }, { PT_F61, "f61" }, + { PT_F62, "f62" }, { PT_F63, "f63" }, { PT_F64, "f64" }, + { PT_F65, "f65" }, { PT_F66, "f66" }, { PT_F67, "f67" }, + { PT_F68, "f68" }, { PT_F69, "f69" }, { PT_F70, "f70" }, + { PT_F71, "f71" }, { PT_F72, "f72" }, { PT_F73, "f73" }, + { PT_F74, "f74" }, { PT_F75, "f75" }, { PT_F76, "f76" }, + { PT_F77, "f77" }, { PT_F78, "f78" }, { PT_F79, "f79" }, + { PT_F80, "f80" }, { PT_F81, "f81" }, { PT_F82, "f82" }, + { PT_F83, "f83" }, { PT_F84, "f84" }, { PT_F85, "f85" }, + { PT_F86, "f86" }, { PT_F87, "f87" }, { PT_F88, "f88" }, + { PT_F89, "f89" }, { PT_F90, "f90" }, { PT_F91, "f91" }, + { PT_F92, "f92" }, { PT_F93, "f93" }, { PT_F94, "f94" }, + { PT_F95, "f95" }, { PT_F96, "f96" }, { PT_F97, "f97" }, + { PT_F98, "f98" }, { PT_F99, "f99" }, { PT_F100, "f100" }, + { PT_F101, "f101" }, { PT_F102, "f102" }, { PT_F103, "f103" }, + { PT_F104, "f104" }, { PT_F105, "f105" }, { PT_F106, "f106" }, + { PT_F107, "f107" }, { PT_F108, "f108" }, { PT_F109, "f109" }, + { PT_F110, "f110" }, { PT_F111, "f111" }, { PT_F112, "f112" }, + { PT_F113, "f113" }, { PT_F114, "f114" }, { PT_F115, "f115" }, + { PT_F116, "f116" }, { PT_F117, "f117" }, { PT_F118, "f118" }, + { PT_F119, "f119" }, { PT_F120, "f120" }, { PT_F121, "f121" }, + { PT_F122, "f122" }, { PT_F123, "f123" }, { PT_F124, "f124" }, + { PT_F125, "f125" }, { PT_F126, "f126" }, { PT_F127, "f127" }, + /* switch stack: */ + { PT_F2, "f2" }, { PT_F3, "f3" }, { PT_F4, "f4" }, + { PT_F5, "f5" }, { PT_F10, "f10" }, { PT_F11, "f11" }, + { PT_F12, "f12" }, { PT_F13, "f13" }, { PT_F14, "f14" }, + { PT_F15, "f15" }, { PT_F16, "f16" }, { PT_F17, "f17" }, + { PT_F18, "f18" }, { PT_F19, "f19" }, { PT_F20, "f20" }, + { PT_F21, "f21" }, { PT_F22, "f22" }, { PT_F23, "f23" }, + { PT_F24, "f24" }, { PT_F25, "f25" }, { PT_F26, "f26" }, + { PT_F27, "f27" }, { PT_F28, "f28" }, { PT_F29, "f29" }, + { PT_F30, "f30" }, { PT_F31, "f31" }, { PT_R4, "r4" }, + { PT_R5, "r5" }, { PT_R6, "r6" }, { PT_R7, "r7" }, + { PT_K_B0, "kb0" }, + { PT_B1, "b1" }, { PT_B2, "b2" }, { PT_B3, "b3" }, + { PT_B4, "b4" }, { PT_B5, "b5" }, + { PT_K_AR_PFS, "kar.pfs" }, + { PT_AR_LC, "ar.lc" }, { PT_K_AR_UNAT, "kar.unat" }, + { PT_K_AR_RNAT, "kar.rnat" }, { PT_K_AR_BSPSTORE, "kar.bspstore" }, + { PT_K_PR, "k.pr" }, + /* pt_regs */ + { PT_CR_IPSR, "cr.ipsr" }, { PT_CR_IIP, "cr.iip" }, + { PT_CR_IFS, "cr.ifs" }, { PT_AR_UNAT, "ar.unat" }, + { PT_AR_PFS, "ar.pfs" }, { PT_AR_RSC, "ar.rsc" }, + { PT_AR_RNAT, "ar.rnat" }, { PT_AR_BSPSTORE, "ar.bspstore" }, + { PT_PR, "pr" }, { PT_B6, "b6" }, { PT_AR_BSP, "ar.bsp" }, + { PT_R1, "r1" }, { PT_R2, "r2" }, { PT_R3, "r3" }, + { PT_R12, "r12" }, { PT_R13, "r13" }, { PT_R14, "r14" }, + { PT_R15, "r15" }, { PT_R8, "r8" }, { PT_R9, "r9" }, + { PT_R10, "r10" }, { PT_R11, "r11" }, { PT_R16, "r16" }, + { PT_R17, "r17" }, { PT_R18, "r18" }, { PT_R19, "r19" }, + { PT_R20, "r20" }, { PT_R21, "r21" }, { PT_R22, "r22" }, + { PT_R23, "r23" }, { PT_R24, "r24" }, { PT_R25, "r25" }, + { PT_R26, "r26" }, { PT_R27, "r27" }, { PT_R28, "r28" }, + { PT_R29, "r29" }, { PT_R30, "r30" }, { PT_R31, "r31" }, + { PT_AR_CCV, "ar.ccv" }, { PT_AR_FPSR, "ar.fpsr" }, + { PT_B0, "b0" }, { PT_B7, "b7" }, { PT_F6, "f6" }, + { PT_F7, "f7" }, { PT_F8, "f8" }, { PT_F9, "f9" }, +#else /* !IA64 */ #ifdef I386 { 4*EBX, "4*EBX" }, { 4*ECX, "4*ECX" }, @@ -1791,6 +1872,7 @@ struct xlat struct_user_offsets[] = { #ifdef I386 { uoff(u_debugreg), "offsetof(struct user, u_debugreg)" }, #endif /* I386 */ +#endif /* !IA64 */ #endif /* !ALPHA */ #endif /* !POWERPC/!SPARC */ #endif /* LINUX */ @@ -60,6 +60,10 @@ #ifdef LINUX +#ifdef IA64 +# include <asm/ptrace_offsets.h> +#endif /* !IA64 */ + #ifdef HAVE_ASM_SIGCONTEXT_H #include <asm/sigcontext.h> #ifdef SPARC @@ -251,7 +255,7 @@ sigset_t *s; static int copy_sigset_len(tcp, addr, s, len) struct tcb *tcp; -int addr; +long addr; sigset_t *s; int len; { @@ -741,6 +745,28 @@ struct tcb *tcp; } return 0; #else /* !I386 */ +#ifdef IA64 + struct sigcontext sc; + long sp; + + if (entering(tcp)) { + tcp->u_arg[0] = 0; + if (upeek(tcp->pid, PT_R12, &sp) < 0) + return 0; + if (umove(tcp, sp + 16, &sc) < 0) + return 0; + tcp->u_arg[0] = 1; + memcpy(tcp->u_arg + 1, &sc.sc_mask, sizeof(tcp->u_arg[1])); + } + else { + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + tcp->auxstr = sprintsigmask("mask now ", tcp->u_arg[1]); + return RVAL_NONE | RVAL_STR; + } + return 0; +#else /* !IA64 */ #ifdef POWERPC long esp; struct sigcontext_struct sc; @@ -867,6 +893,7 @@ struct tcb *tcp; #endif /* ALPHA */ #endif /* !M68K */ #endif /* !POWERPC */ +#endif /* !IA64 */ #endif /* !I386 */ #endif /* S390 */ } @@ -1481,10 +1481,25 @@ trace() /* Look up `pid' in our table. */ if ((tcp = pid2tcb(pid)) == NULL) { +#if 1 /* XXX davidm */ + struct tcb *tcpchild; + + if ((tcpchild = alloctcb(pid)) == NULL) { + fprintf(stderr, " [tcb table full]\n"); + kill(pid, SIGKILL); /* XXX */ + return 0; + } + tcpchild->flags |= TCB_ATTACHED; + newoutf(tcpchild); + tcp->nchildren++; + if (!qflag) + fprintf(stderr, "Process %d attached\n", pid); +#else fprintf(stderr, "unknown pid: %u\n", pid); if (WIFSTOPPED(status)) ptrace(PTRACE_CONT, pid, (char *) 1, 0); exit(1); +#endif } /* set current output file */ outf = tcp->outf; @@ -58,6 +58,11 @@ #endif #endif +#if defined(LINUX) && defined(IA64) +# include <asm/ptrace_offsets.h> +# include <asm/rse.h> +#endif + #ifndef SYS_ERRLIST_DECLARED extern int sys_nerr; extern char *sys_errlist[]; @@ -409,7 +414,7 @@ struct tcb *tcp; enum subcall_style { shift_style, deref_style, mask_style, door_style }; -#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) )) +#if !(defined(LINUX) && ( defined(ALPHA) || defined(IA64) || defined(MIPS) )) const int socket_map [] = { /* SYS_SOCKET */ 97, @@ -594,6 +599,25 @@ struct tcb *tcp; #elif defined (I386) if (upeek(pid, 4*ORIG_EAX, &scno) < 0) return -1; +#elif defined(IA64) +#define IA64_PSR_IS ((long)1 << 34) + if (upeek (pid, PT_CR_IPSR, &psr) >= 0) + ia32 = (psr & IA64_PSR_IS); + if (!(tcp->flags & TCB_INSYSCALL)) { + if (ia32) { + if (upeek(pid, PT_R8, &scno) < 0) + return -1; + } else { + if (upeek (pid, PT_R15, &scno) < 0) + return -1; + } + } else { + /* syscall in progress */ + if (upeek (pid, PT_R8, &r8) < 0) + return -1; + if (upeek (pid, PT_R10, &r10) < 0) + return -1; + } #elif defined (ARM) { long pc; @@ -732,6 +756,9 @@ struct tcb *tcp; #ifdef LINUX #if defined (I386) static long eax; +#elif defined (IA64) + long r8, r10, psr; + long ia32 = 0; #elif defined (POWERPC) static long result,flags; #elif defined (M68K) @@ -859,6 +886,29 @@ struct tcb *tcp; u_error = 0; } #else /* !I386 */ +#ifdef IA64 + if (ia32) { + int err; + + err = (int)r8; + if (err < 0 && -err < nerrnos) { + tcp->u_rval = -1; + u_error = -err; + } + else { + tcp->u_rval = err; + u_error = 0; + } + } else { + if (r10) { + tcp->u_rval = -1; + u_error = r8; + } else { + tcp->u_rval = r8; + u_error = 0; + } + } +#else /* !IA64 */ #ifdef MIPS if (a3) { tcp->u_rval = -1; @@ -923,6 +973,7 @@ struct tcb *tcp; #endif /* M68K */ #endif /* POWERPC */ #endif /* MIPS */ +#endif /* IA64 */ #endif /* I386 */ #endif /* LINUX */ #ifdef SUNOS4 @@ -999,6 +1050,21 @@ struct tcb *tcp; return -1; } } +#elif defined (IA64) + { + unsigned long *bsp, i; + + if (upeek(pid, PT_AR_BSP, (long *) &bsp) < 0) + return -1; + + tcp->u_nargs = sysent[tcp->scno].nargs; + for (i = 0; i < tcp->u_nargs; ++i) { + if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(bsp, i), sizeof(long), + (char *) &tcp->u_arg[i]) + < 0) + return -1; + } + } #elif defined (MIPS) { long sp; @@ -1274,7 +1340,7 @@ struct tcb *tcp; switch (tcp->scno + NR_SYSCALL_BASE) { #ifdef LINUX -#if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) +#if !defined (ALPHA) && !defined(IA64) && !defined(SPARC) && !defined(MIPS) case SYS_socketcall: decode_subcall(tcp, SYS_socket_subcall, SYS_socket_nsubcalls, deref_style); @@ -1734,7 +1734,7 @@ struct tcb *tcp; #endif )))) { printpath(tcp, (size_t)info.oldval); - tprintf(", %d, ", oldlen); + tprintf(", %Zu, ", oldlen); if (info.newval == 0) tprintf("NULL"); else if (syserror(tcp)) @@ -1743,7 +1743,7 @@ struct tcb *tcp; printpath(tcp, (size_t)info.newval); tprintf(", %Zd", info.newlen); } else { - tprintf("%p, %d, %p, %Zd", info.oldval, oldlen, + tprintf("%p, %Zd, %p, %Zd", info.oldval, oldlen, info.newval, info.newlen); } tprintf("}"); @@ -48,6 +48,10 @@ #include <linux/ptrace.h> #endif +#if defined(LINUX) && defined(IA64) +#include <asm/ptrace_offsets.h> +#endif + #ifdef HAVE_SYS_REG_H #include <sys/reg.h> # define PTRACE_PEEKUSR PTRACE_PEEKUSER @@ -874,6 +878,9 @@ struct tcb *tcp; #if defined(I386) if (upeek(tcp->pid, 4*EIP, &pc) < 0) return -1; +#elif defined(IA64) + if (upeek(tcp->pid, PT_B0, &pc) < 0) + return -1; #elif defined(ARM) if (upeek(tcp->pid, 4*15, &pc) < 0) return -1; @@ -936,6 +943,15 @@ struct tcb *tcp; } tprintf("[%08lx] ", eip); #else /* !I386K */ +#ifdef IA64 + long ip; + + if (upeek(tcp->pid, PT_B0, &ip) < 0) { + tprintf("[????????] "); + return; + } + tprintf("[%08lx] ", ip); +#else /* !IA64 */ #ifdef POWERPC long pc; @@ -974,6 +990,7 @@ struct tcb *tcp; #endif /* ALPHA */ #endif /* !M68K */ #endif /* !POWERPC */ +#endif /* !IA64 */ #endif /* !I386 */ #endif /* LINUX */ @@ -1044,6 +1061,47 @@ struct tcb *tcp; tcp->flags |= TCB_BPTSET; #else /* !SPARC */ +#ifdef IA64 + /* + * Our strategy here is to replace the bundle that contained + * the clone() syscall with a bundle of the form: + * + * { 1: br 1b; br 1b; br 1b } + * + * This ensures that the newly forked child will loop + * endlessly until we've got a chance to attach to it. + */ + { +# define LOOP0 0x0000100000000017 +# define LOOP1 0x4000000000200000 + unsigned long addr, ipsr; + pid_t pid; + + pid = tcp->pid; + if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) + return -1; + if (upeek(pid, PT_CR_IIP, &addr) < 0) + return -1; + tcp->baddr = addr | ((ipsr >> 41) & 0x3); /* store "ri" in low two bits */ + + errno = 0; + tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0); + tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0); + if (errno) { + perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); + return -1; + } + + errno = 0; + ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0); + ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1); + if (errno) { + perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); + return -1; + } + tcp->flags |= TCB_BPTSET; + } +#else /* !IA64 */ #if defined (I386) #define LOOP 0x0000feeb @@ -1102,6 +1160,7 @@ struct tcb *tcp; } tcp->flags |= TCB_BPTSET; +#endif /* !IA64 */ #endif /* SPARC */ #endif /* LINUX */ @@ -1193,6 +1252,47 @@ struct tcb *tcp; } tcp->flags &= ~TCB_BPTSET; #else /* !SPARC */ +#ifdef IA64 + { + unsigned long addr, ipsr; + pid_t pid; + + pid = tcp->pid; + + if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) + return -1; + if (upeek(pid, PT_CR_IIP, &addr) < 0) + return -1; + + /* restore original bundle: */ + errno = 0; + ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]); + ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]); + if (errno) { + perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)"); + return -1; + } + + /* restore original "ri" in ipsr: */ + ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41); + errno = 0; + ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr); + if (errno) { + perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)"); + return -1; + } + + tcp->flags &= ~TCB_BPTSET; + + if (addr != (tcp->baddr & ~0x3)) { + /* the breakpoint has not been reached yet. */ + if (debug) + fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", + addr, tcp->baddr); + return 0; + } + } +#else /* !IA64 */ if (debug) fprintf(stderr, "[%d] clearing bpt\n", tcp->pid); @@ -1256,6 +1356,7 @@ struct tcb *tcp; #endif /* !M68K */ #endif /* !POWERPC */ #endif /* !I386 */ +#endif /* !IA64 */ #endif /* !SPARC */ #endif /* LINUX */ |