trace.c revision 9e1e969838d9cc520abb96038aa98520c08c80b9
1#include "config.h" 2 3#include <sys/types.h> 4#include <sys/wait.h> 5#include <signal.h> 6#include <sys/ptrace.h> 7#include <asm/ptrace.h> 8#include <elf.h> 9#include <errno.h> 10#include <string.h> 11 12#include "proc.h" 13#include "common.h" 14#include "ptrace.h" 15#include "breakpoint.h" 16 17#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 18# define PTRACE_PEEKUSER PTRACE_PEEKUSR 19#endif 20 21#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 22# define PTRACE_POKEUSER PTRACE_POKEUSR 23#endif 24 25void 26get_arch_dep(Process *proc) { 27 if (proc->arch_ptr == NULL) { 28 proc->arch_ptr = malloc(sizeof(proc_archdep)); 29#ifdef __powerpc64__ 30 proc->mask_32bit = (proc->e_machine == EM_PPC); 31#endif 32 } 33 34 proc_archdep *a = (proc_archdep *) (proc->arch_ptr); 35 a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0) 36 && (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &a->fpregs) >= 0); 37} 38 39#define SYSCALL_INSN 0x44000002 40 41unsigned int greg = 3; 42unsigned int freg = 1; 43 44/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ 45int 46syscall_p(Process *proc, int status, int *sysnum) { 47 if (WIFSTOPPED(status) 48 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 49 long pc = (long)get_instruction_pointer(proc); 50 int insn = 51 (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long), 52 0); 53 54 if (insn == SYSCALL_INSN) { 55 *sysnum = 56 (int)ptrace(PTRACE_PEEKUSER, proc->pid, 57 sizeof(long) * PT_R0, 0); 58 if (proc->callstack_depth > 0 && 59 proc->callstack[proc->callstack_depth - 1].is_syscall && 60 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 61 return 2; 62 } 63 return 1; 64 } 65 } 66 return 0; 67} 68 69static long 70gimme_arg_regset(enum tof type, Process *proc, int arg_num, arg_type_info *info, 71 gregset_t *regs, fpregset_t *fpregs) 72{ 73 union { long val; float fval; double dval; } cvt; 74 75 if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) { 76 if (freg <= 13 || (proc->mask_32bit && freg <= 8)) { 77 double val = GET_FPREG(*fpregs, freg); 78 79 if (info->type == ARGTYPE_FLOAT) 80 cvt.fval = val; 81 else 82 cvt.dval = val; 83 84 freg++; 85 greg++; 86 87 return cvt.val; 88 } 89 } 90 else if (greg <= 10) 91 return (*regs)[greg++]; 92 else { 93#ifdef __powerpc64__ 94 if (proc->mask_32bit) 95 return ptrace (PTRACE_PEEKDATA, proc->pid, 96 proc->stack_pointer + 8 + 97 sizeof (int) * (arg_num - 8), 0) >> 32; 98 else 99 return ptrace (PTRACE_PEEKDATA, proc->pid, 100 proc->stack_pointer + 112 + 101 sizeof (long) * (arg_num - 8), 0); 102#else 103 return ptrace (PTRACE_PEEKDATA, proc->pid, 104 proc->stack_pointer + 8 + 105 sizeof (long) * (arg_num - 8), 0); 106#endif 107 } 108 109 return 0; 110} 111 112static long 113gimme_retval(Process *proc, int arg_num, arg_type_info *info, 114 gregset_t *regs, fpregset_t *fpregs) 115{ 116 union { long val; float fval; double dval; } cvt; 117 if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) { 118 double val = GET_FPREG(*fpregs, 1); 119 120 if (info->type == ARGTYPE_FLOAT) 121 cvt.fval = val; 122 else 123 cvt.dval = val; 124 125 return cvt.val; 126 } 127 else 128 return (*regs)[3]; 129} 130 131/* Grab functions arguments based on the PPC64 ABI. */ 132long 133gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) 134{ 135 proc_archdep *arch = (proc_archdep *)proc->arch_ptr; 136 if (arch == NULL || !arch->valid) 137 return -1; 138 139 /* Check if we're entering a new function call to list parameters. If 140 so, initialize the register control variables to keep track of where 141 the parameters were stored. */ 142 if ((type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) 143 && arg_num == 0) { 144 /* Initialize the set of registrers for parameter passing. */ 145 greg = 3; 146 freg = 1; 147 } 148 149 150 if (type == LT_TOF_FUNCTIONR) { 151 if (arg_num == -1) 152 return gimme_retval(proc, arg_num, info, 153 &arch->regs, &arch->fpregs); 154 else 155 return gimme_arg_regset(type, proc, arg_num, info, 156 &arch->regs_copy, 157 &arch->fpregs_copy); 158 } 159 else 160 return gimme_arg_regset(type, proc, arg_num, info, 161 &arch->regs, &arch->fpregs); 162} 163 164void 165save_register_args(enum tof type, Process *proc) { 166 proc_archdep *arch = (proc_archdep *)proc->arch_ptr; 167 if (arch == NULL || !arch->valid) 168 return; 169 170 memcpy(&arch->regs_copy, &arch->regs, sizeof(arch->regs)); 171 memcpy(&arch->fpregs_copy, &arch->fpregs, sizeof(arch->fpregs)); 172} 173 174/* Read a single long from the process's memory address 'addr'. */ 175int 176arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 177 long pointed_to; 178 179 errno = 0; 180 181 pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); 182 183 if (pointed_to == -1 && errno) 184 return -errno; 185 186#if SIZEOF_LONG == 8 187 /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we 188 need to shift the long values returned by ptrace to end up with 189 the correct value. */ 190 191 if (info) { 192 if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER 193 || info->type == ARGTYPE_STRING))) { 194 pointed_to = (long) (((unsigned long) pointed_to) >> 32); 195 } 196 } 197#endif 198 199 *result = pointed_to; 200 return 0; 201} 202 203/* The atomic skip code is mostly taken from GDB. */ 204 205/* Instruction masks used during single-stepping of atomic 206 * sequences. This was lifted from GDB. */ 207#define LWARX_MASK 0xfc0007fe 208#define LWARX_INSTRUCTION 0x7c000028 209#define LDARX_INSTRUCTION 0x7c0000A8 210#define STWCX_MASK 0xfc0007ff 211#define STWCX_INSTRUCTION 0x7c00012d 212#define STDCX_INSTRUCTION 0x7c0001ad 213#define BC_MASK 0xfc000000 214#define BC_INSTRUCTION 0x40000000 215 216int 217arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp, 218 int (*add_cb)(void *addr, void *data), 219 void *add_cb_data) 220{ 221 void *addr = sbp->addr; 222 debug(1, "pid=%d addr=%p", proc->pid, addr); 223 224 /* If the original instruction was lwarx/ldarx, we can't 225 * single-step over it, instead we have to execute the whole 226 * atomic block at once. */ 227 union { 228 uint32_t insn; 229 char buf[4]; 230 } u; 231 memcpy(u.buf, sbp->orig_value, BREAKPOINT_LENGTH); 232 233 if ((u.insn & LWARX_MASK) != LWARX_INSTRUCTION 234 && (u.insn & LWARX_MASK) != LDARX_INSTRUCTION) 235 return 1; 236 237 int insn_count; 238 for (insn_count = 0; ; ++insn_count) { 239 addr += 4; 240 unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 241 if (l == (unsigned long)-1 && errno) 242 return -1; 243 uint32_t insn; 244#ifdef __powerpc64__ 245 insn = l >> 32; 246#else 247 insn = l; 248#endif 249 250 /* If we hit a branch instruction, give up. The 251 * computation could escape that way and we'd have to 252 * treat that case specially. */ 253 if ((insn & BC_MASK) == BC_INSTRUCTION) { 254 debug(1, "pid=%d, found branch at %p, giving up", 255 proc->pid, addr); 256 return -1; 257 } 258 259 if ((insn & STWCX_MASK) == STWCX_INSTRUCTION 260 || (insn & STWCX_MASK) == STDCX_INSTRUCTION) { 261 debug(1, "pid=%d, found end of atomic block at %p", 262 proc->pid, addr); 263 break; 264 } 265 266 /* Arbitrary cut-off. If we didn't find the 267 * terminating instruction by now, just give up. */ 268 if (insn_count > 16) { 269 debug(1, "pid=%d, couldn't find end of atomic block", 270 proc->pid); 271 return -1; 272 } 273 } 274 275 /* Put the breakpoint to the next instruction. */ 276 addr += 4; 277 if (add_cb(addr, add_cb_data) < 0) 278 return -1; 279 280 debug(1, "PTRACE_CONT"); 281 ptrace(PTRACE_CONT, proc->pid, 0, 0); 282 return 0; 283} 284