trace.c revision 9a2ad351a1c3215dc596ff3e2e3fd4bc24445a6b
1#if HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <stdlib.h> 6#include <stddef.h> 7#include <sys/types.h> 8#include <sys/wait.h> 9#include <signal.h> 10#include <sys/ptrace.h> 11#include <string.h> 12#include <asm/ptrace_offsets.h> 13#include <asm/rse.h> 14 15#include "ltrace.h" 16 17/* What we think of as a bundle, ptrace thinks of it as two unsigned 18 * longs */ 19union bundle_t { 20 /* An IA64 instruction bundle has a 5 bit header describing the 21 * type of bundle, then 3 41 bit instructions 22 */ 23 struct { 24 struct { 25 unsigned long template : 5 ; 26 unsigned long slot0 : 41; 27 unsigned long bot_slot1 : 18; 28 } word0; 29 struct { 30 unsigned long top_slot1 : 23; 31 unsigned long slot2 : 41; 32 } word1; 33 } bitmap; 34 unsigned long code[2]; 35}; 36 37int 38syscall_p(struct process * proc, int status, int * sysnum) { 39 40 if (WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 41 unsigned long slot = (ptrace (PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) & 0x3; 42 unsigned long ip = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0); 43 44 /* r15 holds the system call number */ 45 unsigned long r15 = ptrace (PTRACE_PEEKUSER, proc->pid, PT_R15, 0); 46 unsigned long insn; 47 48 union bundle_t bundle; 49 50 /* On fault, the IP has moved forward to the next 51 * slot. If that is zero, then the actual place we 52 * broke was in the previous bundle, so wind back the 53 * IP. 54 */ 55 if (slot == 0) 56 ip = ip - 16; 57 bundle.code[0] = ptrace (PTRACE_PEEKTEXT, proc->pid, ip, 0); 58 bundle.code[1] = ptrace (PTRACE_PEEKTEXT, proc->pid, ip+8, 0); 59 60 unsigned long bot = 0UL | bundle.bitmap.word0.bot_slot1; 61 unsigned long top = 0UL | bundle.bitmap.word1.top_slot1; 62 63 /* handle the rollback, slot 0 is actually slot 2 of 64 * the previous instruction (see above) */ 65 switch (slot) { 66 case 0: 67 insn = bundle.bitmap.word1.slot2; 68 break; 69 case 1: 70 insn = bundle.bitmap.word0.slot0; 71 break; 72 case 2: 73 /* make sure we're shifting about longs */ 74 insn = 0UL | bot | (top << 18UL); 75 break; 76 default: 77 printf("Ummm, can't find instruction slot?\n"); 78 exit(1); 79 } 80 81 /* We need to support both the older break instruction 82 * type syscalls, and the new epc type ones. 83 * 84 * Bit 20 of the break constant is encoded in the "i" 85 * bit (bit 36) of the instruction, hence you should 86 * see 0x1000000000. 87 * 88 * An EPC call is just 0x1ffffffffff 89 */ 90 if (insn == 0x1000000000 || insn == 0x1ffffffffff) { 91 *sysnum = r15; 92 if (proc->callstack_depth > 0 && 93 proc->callstack[proc->callstack_depth-1].is_syscall) { 94 return 2; 95 } 96 return 1; 97 } 98 } 99 return 0; 100} 101 102long 103gimme_arg(enum tof type, struct process * proc, int arg_num) { 104 105 unsigned long bsp, cfm; 106 107 bsp = ptrace (PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0); 108 cfm = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0); 109 110 if (arg_num==-1) /* return value */ 111 return ptrace (PTRACE_PEEKUSER, proc->pid, PT_R8, 0); 112 113 /* First 8 arguments are passed in registers on the register 114 * stack, the following arguments are passed on the stack 115 * after a 16 byte scratch area 116 */ 117 if (type==LT_TOF_FUNCTION || LT_TOF_FUNCTIONR) { 118 if (arg_num < 8) 119 return ptrace (PTRACE_PEEKDATA, proc->pid, (long)ia64_rse_skip_regs((long*)bsp, -cfm+arg_num), 0); 120 else { 121 unsigned long sp = ptrace (PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16; 122 return ptrace (PTRACE_PEEKDATA, proc->pid, sp + (8*(arg_num - 8))); 123 } 124 } 125 126 if (type==LT_TOF_SYSCALL || LT_TOF_SYSCALLR ) 127 return ptrace (PTRACE_PEEKDATA, proc->pid, (long)ia64_rse_skip_regs((long *) bsp, arg_num), 0); 128 129 /* error if we get here */ 130 fprintf(stderr, "gimme_arg called with wrong arguments\n"); 131 exit(1); 132} 133 134void 135save_register_args(enum tof type, struct process * proc) { 136} 137 138void 139get_arch_dep(struct process * proc) { 140} 141