trace.c revision f728123bd75a65a6a1536e198c3c30719e494e71
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 "common.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 37union cfm_t { 38 struct { 39 unsigned long sof:7; 40 unsigned long sol:7; 41 unsigned long sor:4; 42 unsigned long rrb_gr:7; 43 unsigned long rrb_fr:7; 44 unsigned long rrb_pr:6; 45 } cfm; 46 unsigned long value; 47}; 48 49int 50syscall_p(Process *proc, int status, int *sysnum) { 51 if (WIFSTOPPED(status) 52 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 53 unsigned long slot = 54 (ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) & 55 0x3; 56 unsigned long ip = 57 ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0); 58 59 /* r15 holds the system call number */ 60 unsigned long r15 = 61 ptrace(PTRACE_PEEKUSER, proc->pid, PT_R15, 0); 62 unsigned long insn; 63 64 union bundle_t bundle; 65 66 /* On fault, the IP has moved forward to the next 67 * slot. If that is zero, then the actual place we 68 * broke was in the previous bundle, so wind back the 69 * IP. 70 */ 71 if (slot == 0) 72 ip = ip - 16; 73 bundle.code[0] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); 74 bundle.code[1] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip + 8, 0); 75 76 unsigned long bot = 0UL | bundle.bitmap.word0.bot_slot1; 77 unsigned long top = 0UL | bundle.bitmap.word1.top_slot1; 78 79 /* handle the rollback, slot 0 is actually slot 2 of 80 * the previous instruction (see above) */ 81 switch (slot) { 82 case 0: 83 insn = bundle.bitmap.word1.slot2; 84 break; 85 case 1: 86 insn = bundle.bitmap.word0.slot0; 87 break; 88 case 2: 89 /* make sure we're shifting about longs */ 90 insn = 0UL | bot | (top << 18UL); 91 break; 92 default: 93 printf("Ummm, can't find instruction slot?\n"); 94 exit(1); 95 } 96 97 /* We need to support both the older break instruction 98 * type syscalls, and the new epc type ones. 99 * 100 * Bit 20 of the break constant is encoded in the "i" 101 * bit (bit 36) of the instruction, hence you should 102 * see 0x1000000000. 103 * 104 * An EPC call is just 0x1ffffffffff 105 */ 106 if (insn == 0x1000000000 || insn == 0x1ffffffffff) { 107 *sysnum = r15; 108 if (proc->callstack_depth > 0 && 109 proc->callstack[proc->callstack_depth - 1].is_syscall && 110 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 111 return 2; 112 } 113 return 1; 114 } 115 } 116 return 0; 117} 118 119/* Stolen from David Mosberger's utrace tool, which he released under 120 the GPL 121 (http://www.gelato.unsw.edu.au/archives/linux-ia64/0104/1405.html) */ 122static inline double 123fpreg_to_double (struct ia64_fpreg *fp) { 124 double result; 125 126 asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp)); 127 return result; 128} 129 130static long 131gimme_long_arg(enum tof type, Process *proc, int arg_num) { 132 union cfm_t cfm; 133 unsigned long bsp; 134 135 bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0); 136 cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0); 137 138 if (arg_num == -1) /* return value */ 139 return ptrace(PTRACE_PEEKUSER, proc->pid, PT_R8, 0); 140 141 /* First 8 arguments are passed in registers on the register 142 * stack, the following arguments are passed on the stack 143 * after a 16 byte scratch area 144 * 145 * If the function has returned, the ia64 register window has 146 * been reverted to the caller's configuration. So although in 147 * the callee, the first parameter is in R32, in the caller 148 * the first parameter comes in the registers after the local 149 * registers (really, input parameters plus locals, but the 150 * hardware doesn't track the distinction.) So we have to add 151 * in the size of the local area (sol) to find the first 152 * parameter passed to the callee. */ 153 if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { 154 if (arg_num < 8) { 155 if (type == LT_TOF_FUNCTIONR) 156 arg_num += cfm.cfm.sol; 157 158 return ptrace(PTRACE_PEEKDATA, proc->pid, 159 (long)ia64_rse_skip_regs((unsigned long *)bsp, 160 -cfm.cfm.sof + arg_num), 161 0); 162 } else { 163 unsigned long sp = 164 ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16; 165 return ptrace(PTRACE_PEEKDATA, proc->pid, 166 sp + (8 * (arg_num - 8))); 167 } 168 } 169 170 if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR) 171 return ptrace(PTRACE_PEEKDATA, proc->pid, 172 (long)ia64_rse_skip_regs((unsigned long *)bsp, arg_num), 173 0); 174 175 /* error if we get here */ 176 fprintf(stderr, "gimme_arg called with wrong arguments\n"); 177 exit(1); 178} 179 180static long float_regs[8] = { PT_F8, PT_F9, PT_F10, PT_F11, 181 PT_F12, PT_F13, PT_F14, PT_F15 }; 182static double 183gimme_float_arg(enum tof type, Process *proc, int arg_num) { 184 union cfm_t cfm; 185 unsigned long bsp; 186 struct ia64_fpreg reg; 187 188 if (arg_num == -1) { /* return value */ 189 reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid, 190 PT_F8, 0); 191 reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid, 192 PT_F8 + 0x8, 0); 193 return fpreg_to_double(®); 194 } 195 196 bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0); 197 cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0); 198 199 /* The first 8 arguments are passed in regular registers 200 * (counting from R32), unless they are floating point values 201 * (the case in question here). In that case, up to the first 202 * 8 regular registers are still "allocated" for each of the 203 * first 8 parameters, but if a parameter is floating point, 204 * then the register is left unset and the parameter is passed 205 * in the first available floating-point register, counting 206 * from F8. 207 * 208 * Take func(int a, float f, int b, double d), for example. 209 * a - passed in R32 210 * f - R33 left unset, value passed in F8 211 * b - passed in R34 212 * d - R35 left unset, value passed in F9 213 * 214 * ltrace handles this by counting floating point arguments 215 * while parsing declarations. The "arg_num" in this routine 216 * (which is only called for floating point values) really 217 * means which floating point parameter we're looking for, 218 * ignoring everything else. 219 * 220 * Following the first 8 arguments, the remaining arguments 221 * are passed on the stack after a 16 byte scratch area 222 */ 223 if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { 224 if (arg_num < 8) { 225 reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid, 226 float_regs[arg_num], 0); 227 reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid, 228 float_regs[arg_num] + 0x8, 0); 229 return fpreg_to_double(®); 230 } else { 231 unsigned long sp = 232 ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16; 233 reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid, 234 sp + (8 * (arg_num - 8))); 235 reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid, 236 sp + (8 * (arg_num - 8)) + 0x8); 237 return fpreg_to_double(®); 238 } 239 } 240 241 /* error if we get here */ 242 fprintf(stderr, "gimme_arg called with wrong arguments\n"); 243 exit(1); 244} 245 246long 247gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { 248 union { 249 long l; 250 float f; 251 double d; 252 } cvt; 253 254 if (info->type == ARGTYPE_FLOAT) 255 cvt.f = gimme_float_arg(type, proc, info->u.float_info.float_index); 256 else if (info->type == ARGTYPE_DOUBLE) 257 cvt.d = gimme_float_arg(type, proc, info->u.double_info.float_index); 258 else 259 cvt.l = gimme_long_arg(type, proc, arg_num); 260 261 return cvt.l; 262} 263 264void 265save_register_args(enum tof type, Process *proc) { 266} 267 268void 269get_arch_dep(Process *proc) { 270} 271