trace.c revision 305945b2523ea87907952eefd7300cfb9f1a0235
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2010,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2011 Andreas Schwab 5 * Copyright (C) 2002,2004,2008,2009 Juan Cespedes 6 * Copyright (C) 2008 Luis Machado, IBM Corporation 7 * Copyright (C) 2006 Ian Wienand 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * 02110-1301 USA 23 */ 24 25#include "config.h" 26 27#include <assert.h> 28#include <elf.h> 29#include <errno.h> 30#include <signal.h> 31#include <string.h> 32 33#include "backend.h" 34#include "breakpoint.h" 35#include "common.h" 36#include "insn.h" 37#include "proc.h" 38#include "ptrace.h" 39#include "type.h" 40 41#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 42# define PTRACE_PEEKUSER PTRACE_PEEKUSR 43#endif 44 45#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 46# define PTRACE_POKEUSER PTRACE_POKEUSR 47#endif 48 49void 50get_arch_dep(Process *proc) { 51#ifdef __powerpc64__ 52 proc->mask_32bit = (proc->e_machine == EM_PPC); 53#endif 54} 55 56#define SYSCALL_INSN 0x44000002 57 58/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ 59int 60syscall_p(Process *proc, int status, int *sysnum) { 61 if (WIFSTOPPED(status) 62 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 63 long pc = (long)get_instruction_pointer(proc); 64 int insn = 65 (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long), 66 0); 67 68 if (insn == SYSCALL_INSN) { 69 *sysnum = 70 (int)ptrace(PTRACE_PEEKUSER, proc->pid, 71 sizeof(long) * PT_R0, 0); 72 if (proc->callstack_depth > 0 && 73 proc->callstack[proc->callstack_depth - 1].is_syscall && 74 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 75 return 2; 76 } 77 return 1; 78 } 79 } 80 return 0; 81} 82 83/* The atomic skip code is mostly taken from GDB. */ 84 85/* In plt.h. XXX make this official interface. */ 86int read_target_4(struct Process *proc, arch_addr_t addr, uint32_t *lp); 87 88int 89arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp, 90 int (*add_cb)(void *addr, void *data), 91 void *add_cb_data) 92{ 93 arch_addr_t ip = get_instruction_pointer(proc); 94 struct breakpoint *other = address2bpstruct(proc->leader, ip); 95 96 debug(1, "arch_atomic_singlestep pid=%d addr=%p %s(%p)", 97 proc->pid, ip, breakpoint_name(sbp), sbp->addr); 98 99 /* If the original instruction was lwarx/ldarx, we can't 100 * single-step over it, instead we have to execute the whole 101 * atomic block at once. */ 102 union { 103 uint32_t insn; 104 char buf[BREAKPOINT_LENGTH]; 105 } u; 106 if (other != NULL) { 107 memcpy(u.buf, sbp->orig_value, BREAKPOINT_LENGTH); 108 } else if (read_target_4(proc, ip, &u.insn) < 0) { 109 fprintf(stderr, "couldn't read instruction at IP %p\n", ip); 110 /* Do the normal singlestep. */ 111 return 1; 112 } 113 114 if ((u.insn & LWARX_MASK) != LWARX_INSTRUCTION 115 && (u.insn & LWARX_MASK) != LDARX_INSTRUCTION) 116 return 1; 117 118 debug(1, "singlestep over atomic block at %p", ip); 119 120 int insn_count; 121 arch_addr_t addr = ip; 122 for (insn_count = 0; ; ++insn_count) { 123 addr += 4; 124 unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 125 if (l == (unsigned long)-1 && errno) 126 return -1; 127 uint32_t insn; 128#ifdef __powerpc64__ 129 insn = l >> 32; 130#else 131 insn = l; 132#endif 133 134 /* If a conditional branch is found, put a breakpoint 135 * in its destination address. */ 136 if ((insn & BRANCH_MASK) == BC_INSN) { 137 arch_addr_t branch_addr = ppc_branch_dest(addr, insn); 138 debug(1, "pid=%d, branch in atomic block from %p to %p", 139 proc->pid, addr, branch_addr); 140 if (add_cb(branch_addr, add_cb_data) < 0) 141 return -1; 142 } 143 144 /* Assume that the atomic sequence ends with a 145 * stwcx/stdcx instruction. */ 146 if ((insn & STWCX_MASK) == STWCX_INSTRUCTION 147 || (insn & STWCX_MASK) == STDCX_INSTRUCTION) { 148 debug(1, "pid=%d, found end of atomic block %p at %p", 149 proc->pid, ip, addr); 150 break; 151 } 152 153 /* Arbitrary cut-off. If we didn't find the 154 * terminating instruction by now, just give up. */ 155 if (insn_count > 16) { 156 fprintf(stderr, "[%d] couldn't find end of atomic block" 157 " at %p\n", proc->pid, ip); 158 return -1; 159 } 160 } 161 162 /* Put the breakpoint to the next instruction. */ 163 addr += 4; 164 if (add_cb(addr, add_cb_data) < 0) 165 return -1; 166 167 debug(1, "PTRACE_CONT"); 168 ptrace(PTRACE_CONT, proc->pid, 0, 0); 169 return 0; 170} 171 172size_t 173arch_type_sizeof(struct Process *proc, struct arg_type_info *info) 174{ 175 if (proc == NULL) 176 return (size_t)-2; 177 178 switch (info->type) { 179 case ARGTYPE_VOID: 180 return 0; 181 182 case ARGTYPE_CHAR: 183 return 1; 184 185 case ARGTYPE_SHORT: 186 case ARGTYPE_USHORT: 187 return 2; 188 189 case ARGTYPE_INT: 190 case ARGTYPE_UINT: 191 return 4; 192 193 case ARGTYPE_LONG: 194 case ARGTYPE_ULONG: 195 case ARGTYPE_POINTER: 196 return proc->e_machine == EM_PPC64 ? 8 : 4; 197 198 case ARGTYPE_FLOAT: 199 return 4; 200 case ARGTYPE_DOUBLE: 201 return 8; 202 203 case ARGTYPE_ARRAY: 204 case ARGTYPE_STRUCT: 205 /* Use default value. */ 206 return (size_t)-2; 207 208 default: 209 assert(info->type != info->type); 210 abort(); 211 break; 212 } 213} 214 215size_t 216arch_type_alignof(struct Process *proc, struct arg_type_info *info) 217{ 218 if (proc == NULL) 219 return (size_t)-2; 220 221 switch (info->type) { 222 default: 223 assert(info->type != info->type); 224 abort(); 225 break; 226 227 case ARGTYPE_CHAR: 228 case ARGTYPE_SHORT: 229 case ARGTYPE_USHORT: 230 case ARGTYPE_INT: 231 case ARGTYPE_UINT: 232 case ARGTYPE_LONG: 233 case ARGTYPE_ULONG: 234 case ARGTYPE_POINTER: 235 case ARGTYPE_FLOAT: 236 case ARGTYPE_DOUBLE: 237 /* On both PPC and PPC64, fundamental types have the 238 * same alignment as size. */ 239 return arch_type_sizeof(proc, info); 240 241 case ARGTYPE_ARRAY: 242 case ARGTYPE_STRUCT: 243 /* Use default value. */ 244 return (size_t)-2; 245 } 246} 247