trace.c revision 5b5c256d0e9076e745908a43acc46353265a5608
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2001,2005 IBM Corp. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of the 9 * License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19 * 02110-1301 USA 20 */ 21 22#include "config.h" 23 24#include <asm/ptrace.h> 25#include <sys/ptrace.h> 26#include <sys/types.h> 27#include <sys/wait.h> 28#include <assert.h> 29#include <errno.h> 30#include <signal.h> 31#include <stdlib.h> 32 33#include "common.h" 34#include "proc.h" 35#include "type.h" 36 37#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 38# define PTRACE_PEEKUSER PTRACE_PEEKUSR 39#endif 40 41#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 42# define PTRACE_POKEUSER PTRACE_POKEUSR 43#endif 44 45void 46get_arch_dep(Process *proc) { 47#ifdef __s390x__ 48 unsigned long psw; 49 50 if (proc->arch_ptr) 51 return; 52 53 psw = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWMASK, 0); 54 55 if ((psw & 0x000000180000000) == 0x000000080000000) { 56 proc->mask_32bit = 1; 57 proc->personality = 1; 58 } 59 60 proc->arch_ptr = (void *)1; 61#endif 62} 63 64/* Returns 1 if syscall, 2 if sysret, 0 otherwise. 65 */ 66int 67syscall_p(Process *proc, int status, int *sysnum) { 68 long pc, opcode, offset_reg, scno, tmp; 69 void *svc_addr; 70 int gpr_offset[16] = { PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3, 71 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7, 72 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11, 73 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15 74 }; 75 76 if (WIFSTOPPED(status) 77 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 78 79 /* 80 * If we have PTRACE_O_TRACESYSGOOD and we have the new style 81 * of passing the system call number to user space via PT_GPR2 82 * then the task is quite easy. 83 */ 84 85 *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); 86 87 if (proc->tracesysgood) { 88 /* System call was encountered... */ 89 if (proc->callstack_depth > 0 && 90 proc->callstack[proc->callstack_depth - 91 1].is_syscall) { 92 /* syscall exit */ 93 *sysnum = 94 proc->callstack[proc->callstack_depth - 95 1].c_un.syscall; 96 return 2; 97 } else { 98 /* syscall enter */ 99 if (*sysnum != -ENOSYS) 100 return 1; 101 } 102 } 103 104 /* 105 * At least one of the two requirements mentioned above is not 106 * met. Therefore the fun part starts here: 107 * We try to do some instruction decoding without even knowing 108 * the instruction code length of the last instruction executed. 109 * Needs to be done to get the system call number or to decide 110 * if we reached a breakpoint or even checking for a completely 111 * unrelated instruction. 112 * Just a heuristic that most of the time appears to work... 113 */ 114 115 pc = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0); 116 opcode = ptrace(PTRACE_PEEKTEXT, proc->pid, 117 (char *)(pc - sizeof(long)), 0); 118 119 if ((opcode & 0xffff) == 0x0001) { 120 /* Breakpoint */ 121 return 0; 122 } else if ((opcode & 0xff00) == 0x0a00) { 123 /* SVC opcode */ 124 scno = opcode & 0xff; 125 } else if ((opcode & 0xff000000) == 0x44000000) { 126 /* Instruction decoding of EXECUTE... */ 127 svc_addr = (void *)(opcode & 0xfff); 128 129 offset_reg = (opcode & 0x000f0000) >> 16; 130 if (offset_reg) 131 svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, 132 gpr_offset[offset_reg], 0); 133 134 offset_reg = (opcode & 0x0000f000) >> 12; 135 if (offset_reg) 136 svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, 137 gpr_offset[offset_reg], 0); 138 139 scno = ptrace(PTRACE_PEEKTEXT, proc->pid, svc_addr, 0); 140#ifdef __s390x__ 141 scno >>= 48; 142#else 143 scno >>= 16; 144#endif 145 if ((scno & 0xff00) != 0x0a000) 146 return 0; 147 148 tmp = 0; 149 offset_reg = (opcode & 0x00f00000) >> 20; 150 if (offset_reg) 151 tmp = ptrace(PTRACE_PEEKUSER, proc->pid, 152 gpr_offset[offset_reg], 0); 153 154 scno = (scno | tmp) & 0xff; 155 } else { 156 /* No opcode related to syscall handling */ 157 return 0; 158 } 159 160 if (scno == 0) 161 scno = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR1, 0); 162 163 *sysnum = scno; 164 165 /* System call was encountered... */ 166 if (proc->callstack_depth > 0 && 167 proc->callstack[proc->callstack_depth - 1].is_syscall) { 168 return 2; 169 } else { 170 return 1; 171 } 172 } 173 /* Unknown status... */ 174 return 0; 175} 176 177size_t 178arch_type_sizeof(struct Process *proc, struct arg_type_info *info) 179{ 180 if (proc == NULL) 181 return (size_t)-2; 182 183 switch (info->type) { 184 case ARGTYPE_VOID: 185 return 0; 186 187 case ARGTYPE_CHAR: 188 return 1; 189 190 case ARGTYPE_SHORT: 191 case ARGTYPE_USHORT: 192 return 2; 193 194 case ARGTYPE_INT: 195 case ARGTYPE_UINT: 196 return 4; 197 198 case ARGTYPE_LONG: 199 case ARGTYPE_ULONG: 200 case ARGTYPE_POINTER: 201 return proc->e_class == ELFCLASS64 ? 8 : 4; 202 203 case ARGTYPE_FLOAT: 204 return 4; 205 case ARGTYPE_DOUBLE: 206 return 8; 207 208 case ARGTYPE_ARRAY: 209 case ARGTYPE_STRUCT: 210 /* Use default value. */ 211 return (size_t)-2; 212 213 default: 214 assert(info->type != info->type); 215 abort(); 216 } 217} 218 219size_t 220arch_type_alignof(struct Process *proc, struct arg_type_info *info) 221{ 222 if (proc == NULL) 223 return (size_t)-2; 224 225 switch (info->type) { 226 default: 227 assert(info->type != info->type); 228 break; 229 230 case ARGTYPE_CHAR: 231 return 1; 232 233 case ARGTYPE_SHORT: 234 case ARGTYPE_USHORT: 235 return 2; 236 237 case ARGTYPE_INT: 238 case ARGTYPE_UINT: 239 return 4; 240 241 case ARGTYPE_LONG: 242 case ARGTYPE_ULONG: 243 case ARGTYPE_POINTER: 244 return proc->e_class == ELFCLASS64 ? 8 : 4; 245 246 case ARGTYPE_FLOAT: 247 return 4; 248 case ARGTYPE_DOUBLE: 249 return 8; 250 251 case ARGTYPE_ARRAY: 252 case ARGTYPE_STRUCT: 253 /* Use default value. */ 254 return (size_t)-2; 255 } 256 abort(); 257} 258