trace.c revision f670eea50e959eeb9da53d70cad8d43c19494ef0
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 11#include "common.h" 12 13#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 14# define PTRACE_PEEKUSER PTRACE_PEEKUSR 15#endif 16 17#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 18# define PTRACE_POKEUSER PTRACE_POKEUSR 19#endif 20 21void 22get_arch_dep(Process *proc) { 23#ifdef __powerpc64__ 24 if (proc->arch_ptr) 25 return; 26 proc->mask_32bit = (proc->e_machine == EM_PPC); 27 proc->arch_ptr = (void *)1; 28#endif 29} 30 31/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ 32#define SYSCALL_INSN 0x44000002 33 34unsigned int greg = 3; 35unsigned int freg = 1; 36unsigned int vreg = 2; 37 38int 39syscall_p(Process *proc, int status, int *sysnum) { 40 if (WIFSTOPPED(status) 41 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 42 long pc = (long)get_instruction_pointer(proc); 43 int insn = 44 (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long), 45 0); 46 47 if (insn == SYSCALL_INSN) { 48 *sysnum = 49 (int)ptrace(PTRACE_PEEKUSER, proc->pid, 50 sizeof(long) * PT_R0, 0); 51 if (proc->callstack_depth > 0 && 52 proc->callstack[proc->callstack_depth - 1].is_syscall && 53 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 54 return 2; 55 } 56 return 1; 57 } 58 } 59 return 0; 60} 61 62/* Grab functions arguments based on the PPC64 ABI. */ 63long 64gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) { 65 long data; 66 67 if (type == LT_TOF_FUNCTIONR) { 68 if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) 69 return ptrace (PTRACE_PEEKUSER, proc->pid, 70 sizeof (long) * (PT_FPR0 + 1), 0); 71 else 72 return ptrace (PTRACE_PEEKUSER, proc->pid, 73 sizeof (long) * PT_R3, 0); 74 } 75 76 /* Check if we're entering a new function call to list parameters. If 77 so, initialize the register control variables to keep track of where 78 the parameters were stored. */ 79 if (type == LT_TOF_FUNCTION && arg_num == 0) { 80 /* Initialize the set of registrers for parameter passing. */ 81 greg = 3; 82 freg = 1; 83 vreg = 2; 84 } 85 86 if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) { 87 if (freg <= 13 || (proc->mask_32bit && freg <= 8)) { 88 data = ptrace (PTRACE_PEEKUSER, proc->pid, 89 sizeof (long) * (PT_FPR0 + freg), 0); 90 91 if (info->type == ARGTYPE_FLOAT) { 92 /* float values passed in FP registers are automatically 93 promoted to double. We need to convert it back to float 94 before printing. */ 95 union { long val; float fval; double dval; } cvt; 96 cvt.val = data; 97 cvt.fval = (float) cvt.dval; 98 data = cvt.val; 99 } 100 101 freg++; 102 greg++; 103 104 return data; 105 } 106 } 107 else if (greg <= 10) { 108 data = ptrace (PTRACE_PEEKUSER, proc->pid, 109 sizeof (long) * greg, 0); 110 greg++; 111 112 return data; 113 } 114 else 115 return ptrace (PTRACE_PEEKDATA, proc->pid, 116 proc->stack_pointer + sizeof (long) * 117 (arg_num - 8), 0); 118 119 return 0; 120} 121 122void 123save_register_args(enum tof type, Process *proc) { 124} 125 126/* Read a single long from the process's memory address 'addr'. */ 127int 128arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 129 long pointed_to; 130 131 errno = 0; 132 133 pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); 134 135 if (pointed_to == -1 && errno) 136 return -errno; 137 138 /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we 139 need to shift the long values returned by ptrace to end up with 140 the correct value. */ 141 142 if (info) { 143 if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER 144 || info->type == ARGTYPE_STRING))) { 145 pointed_to = pointed_to >> 32; 146 147 /* Make sure we have nothing in the upper word so we can 148 do a explicit cast from long to int later in the code. */ 149 pointed_to &= 0x00000000ffffffff; 150 } 151 } 152 153 *result = pointed_to; 154 return 0; 155} 156