trace.c revision af9e30ec852a24f52a36775154ff79cc4be0193d
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 <sys/types.h> 28#include <sys/wait.h> 29#include <signal.h> 30#include <sys/ptrace.h> 31#include <asm/ptrace.h> 32#include <elf.h> 33#include <errno.h> 34#include <string.h> 35 36#include "proc.h" 37#include "common.h" 38#include "ptrace.h" 39#include "breakpoint.h" 40#include "type.h" 41#include "backend.h" 42 43#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 44# define PTRACE_PEEKUSER PTRACE_PEEKUSR 45#endif 46 47#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 48# define PTRACE_POKEUSER PTRACE_POKEUSR 49#endif 50 51void 52get_arch_dep(Process *proc) { 53 if (proc->arch_ptr == NULL) { 54 proc->arch_ptr = malloc(sizeof(proc_archdep)); 55#ifdef __powerpc64__ 56 proc->mask_32bit = (proc->e_machine == EM_PPC); 57#endif 58 } 59 60 proc_archdep *a = (proc_archdep *) (proc->arch_ptr); 61 a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0) 62 && (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &a->fpregs) >= 0); 63} 64 65#define SYSCALL_INSN 0x44000002 66 67/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */ 68int 69syscall_p(Process *proc, int status, int *sysnum) { 70 if (WIFSTOPPED(status) 71 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 72 long pc = (long)get_instruction_pointer(proc); 73 int insn = 74 (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long), 75 0); 76 77 if (insn == SYSCALL_INSN) { 78 *sysnum = 79 (int)ptrace(PTRACE_PEEKUSER, proc->pid, 80 sizeof(long) * PT_R0, 0); 81 if (proc->callstack_depth > 0 && 82 proc->callstack[proc->callstack_depth - 1].is_syscall && 83 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 84 return 2; 85 } 86 return 1; 87 } 88 } 89 return 0; 90} 91 92/* The atomic skip code is mostly taken from GDB. */ 93 94/* Instruction masks used during single-stepping of atomic 95 * sequences. This was lifted from GDB. */ 96#define LWARX_MASK 0xfc0007fe 97#define LWARX_INSTRUCTION 0x7c000028 98#define LDARX_INSTRUCTION 0x7c0000A8 99#define STWCX_MASK 0xfc0007ff 100#define STWCX_INSTRUCTION 0x7c00012d 101#define STDCX_INSTRUCTION 0x7c0001ad 102#define BC_MASK 0xfc000000 103#define BC_INSN 0x40000000 104#define BRANCH_MASK 0xfc000000 105 106/* In plt.h. XXX make this official interface. */ 107int read_target_4(struct Process *proc, target_address_t addr, uint32_t *lp); 108 109int 110arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp, 111 int (*add_cb)(void *addr, void *data), 112 void *add_cb_data) 113{ 114 target_address_t ip = get_instruction_pointer(proc); 115 struct breakpoint *other = address2bpstruct(proc->leader, ip); 116 117 debug(1, "arch_atomic_singlestep pid=%d addr=%p %s(%p)", 118 proc->pid, ip, breakpoint_name(sbp), sbp->addr); 119 120 /* If the original instruction was lwarx/ldarx, we can't 121 * single-step over it, instead we have to execute the whole 122 * atomic block at once. */ 123 union { 124 uint32_t insn; 125 char buf[BREAKPOINT_LENGTH]; 126 } u; 127 if (other != NULL) { 128 memcpy(u.buf, sbp->orig_value, BREAKPOINT_LENGTH); 129 } else if (read_target_4(proc, ip, &u.insn) < 0) { 130 fprintf(stderr, "couldn't read instruction at IP %p\n", ip); 131 /* Do the normal singlestep. */ 132 return 1; 133 } 134 135 if ((u.insn & LWARX_MASK) != LWARX_INSTRUCTION 136 && (u.insn & LWARX_MASK) != LDARX_INSTRUCTION) 137 return 1; 138 139 debug(1, "singlestep over atomic block at %p", ip); 140 141 int insn_count; 142 target_address_t addr = ip; 143 for (insn_count = 0; ; ++insn_count) { 144 addr += 4; 145 unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 146 if (l == (unsigned long)-1 && errno) 147 return -1; 148 uint32_t insn; 149#ifdef __powerpc64__ 150 insn = l >> 32; 151#else 152 insn = l; 153#endif 154 155 /* If a conditional branch is found, put a breakpoint 156 * in its destination address. */ 157 if ((insn & BRANCH_MASK) == BC_INSN) { 158 int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000; 159 int absolute = insn & 2; 160 161 /* XXX drop the following casts. */ 162 target_address_t branch_addr; 163 if (absolute) 164 branch_addr = (void *)(uintptr_t)immediate; 165 else 166 branch_addr = addr + (uintptr_t)immediate; 167 168 debug(1, "pid=%d, branch in atomic block from %p to %p", 169 proc->pid, addr, branch_addr); 170 if (add_cb(branch_addr, add_cb_data) < 0) 171 return -1; 172 } 173 174 /* Assume that the atomic sequence ends with a 175 * stwcx/stdcx instruction. */ 176 if ((insn & STWCX_MASK) == STWCX_INSTRUCTION 177 || (insn & STWCX_MASK) == STDCX_INSTRUCTION) { 178 debug(1, "pid=%d, found end of atomic block %p at %p", 179 proc->pid, ip, addr); 180 break; 181 } 182 183 /* Arbitrary cut-off. If we didn't find the 184 * terminating instruction by now, just give up. */ 185 if (insn_count > 16) { 186 fprintf(stderr, "[%d] couldn't find end of atomic block" 187 " at %p\n", proc->pid, ip); 188 return -1; 189 } 190 } 191 192 /* Put the breakpoint to the next instruction. */ 193 addr += 4; 194 if (add_cb(addr, add_cb_data) < 0) 195 return -1; 196 197 debug(1, "PTRACE_CONT"); 198 ptrace(PTRACE_CONT, proc->pid, 0, 0); 199 return 0; 200} 201 202size_t 203arch_type_sizeof(struct Process *proc, struct arg_type_info *info) 204{ 205 if (proc == NULL) 206 return (size_t)-2; 207 208 switch (info->type) { 209 case ARGTYPE_VOID: 210 return 0; 211 212 case ARGTYPE_CHAR: 213 return 1; 214 215 case ARGTYPE_SHORT: 216 case ARGTYPE_USHORT: 217 return 2; 218 219 case ARGTYPE_INT: 220 case ARGTYPE_UINT: 221 return 4; 222 223 case ARGTYPE_LONG: 224 case ARGTYPE_ULONG: 225 case ARGTYPE_POINTER: 226 return proc->e_machine == EM_PPC64 ? 8 : 4; 227 228 case ARGTYPE_FLOAT: 229 return 4; 230 case ARGTYPE_DOUBLE: 231 return 8; 232 233 case ARGTYPE_ARRAY: 234 case ARGTYPE_STRUCT: 235 /* Use default value. */ 236 return (size_t)-2; 237 } 238 assert(info->type != info->type); 239 abort(); 240} 241 242size_t 243arch_type_alignof(struct Process *proc, struct arg_type_info *info) 244{ 245 if (proc == NULL) 246 return (size_t)-2; 247 248 switch (info->type) { 249 case ARGTYPE_VOID: 250 assert(info->type != ARGTYPE_VOID); 251 break; 252 253 case ARGTYPE_CHAR: 254 case ARGTYPE_SHORT: 255 case ARGTYPE_USHORT: 256 case ARGTYPE_INT: 257 case ARGTYPE_UINT: 258 case ARGTYPE_LONG: 259 case ARGTYPE_ULONG: 260 case ARGTYPE_POINTER: 261 case ARGTYPE_FLOAT: 262 case ARGTYPE_DOUBLE: 263 /* On both PPC and PPC64, fundamental types have the 264 * same alignment as size. */ 265 return arch_type_sizeof(proc, info); 266 267 case ARGTYPE_ARRAY: 268 case ARGTYPE_STRUCT: 269 /* Use default value. */ 270 return (size_t)-2; 271 } 272 assert(info->type != info->type); 273 abort(); 274} 275