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 45 void 46 get_arch_dep(struct process *proc) 47 { 48 #ifdef __s390x__ 49 unsigned long psw; 50 51 if (proc->arch_ptr) 52 return; 53 54 psw = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWMASK, 0); 55 56 if ((psw & 0x000000180000000) == 0x000000080000000) { 57 proc->mask_32bit = 1; 58 proc->personality = 1; 59 } 60 61 proc->arch_ptr = (void *)1; 62 #endif 63 } 64 65 /* Returns 1 if syscall, 2 if sysret, 0 otherwise. 66 */ 67 int 68 syscall_p(struct process *proc, int status, int *sysnum) 69 { 70 long pc, opcode, offset_reg, scno, tmp; 71 void *svc_addr; 72 int gpr_offset[16] = { PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3, 73 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7, 74 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11, 75 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15 76 }; 77 78 if (WIFSTOPPED(status) 79 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 80 81 /* 82 * If we have PTRACE_O_TRACESYSGOOD and we have the new style 83 * of passing the system call number to user space via PT_GPR2 84 * then the task is quite easy. 85 */ 86 87 *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0); 88 89 if (proc->tracesysgood) { 90 /* System call was encountered... */ 91 if (proc->callstack_depth > 0 && 92 proc->callstack[proc->callstack_depth - 93 1].is_syscall) { 94 /* syscall exit */ 95 *sysnum = 96 proc->callstack[proc->callstack_depth - 97 1].c_un.syscall; 98 return 2; 99 } else { 100 /* syscall enter */ 101 if (*sysnum != -ENOSYS) 102 return 1; 103 } 104 } 105 106 /* 107 * At least one of the two requirements mentioned above is not 108 * met. Therefore the fun part starts here: 109 * We try to do some instruction decoding without even knowing 110 * the instruction code length of the last instruction executed. 111 * Needs to be done to get the system call number or to decide 112 * if we reached a breakpoint or even checking for a completely 113 * unrelated instruction. 114 * Just a heuristic that most of the time appears to work... 115 */ 116 117 pc = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0); 118 opcode = ptrace(PTRACE_PEEKTEXT, proc->pid, 119 (char *)(pc - sizeof(long)), 0); 120 121 if ((opcode & 0xffff) == 0x0001) { 122 /* Breakpoint */ 123 return 0; 124 } else if ((opcode & 0xff00) == 0x0a00) { 125 /* SVC opcode */ 126 scno = opcode & 0xff; 127 } else if ((opcode & 0xff000000) == 0x44000000) { 128 /* Instruction decoding of EXECUTE... */ 129 svc_addr = (void *)(opcode & 0xfff); 130 131 offset_reg = (opcode & 0x000f0000) >> 16; 132 if (offset_reg) 133 svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, 134 gpr_offset[offset_reg], 0); 135 136 offset_reg = (opcode & 0x0000f000) >> 12; 137 if (offset_reg) 138 svc_addr += ptrace(PTRACE_PEEKUSER, proc->pid, 139 gpr_offset[offset_reg], 0); 140 141 scno = ptrace(PTRACE_PEEKTEXT, proc->pid, svc_addr, 0); 142 #ifdef __s390x__ 143 scno >>= 48; 144 #else 145 scno >>= 16; 146 #endif 147 if ((scno & 0xff00) != 0x0a000) 148 return 0; 149 150 tmp = 0; 151 offset_reg = (opcode & 0x00f00000) >> 20; 152 if (offset_reg) 153 tmp = ptrace(PTRACE_PEEKUSER, proc->pid, 154 gpr_offset[offset_reg], 0); 155 156 scno = (scno | tmp) & 0xff; 157 } else { 158 /* No opcode related to syscall handling */ 159 return 0; 160 } 161 162 if (scno == 0) 163 scno = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR1, 0); 164 165 *sysnum = scno; 166 167 /* System call was encountered... */ 168 if (proc->callstack_depth > 0 && 169 proc->callstack[proc->callstack_depth - 1].is_syscall) { 170 return 2; 171 } else { 172 return 1; 173 } 174 } 175 /* Unknown status... */ 176 return 0; 177 } 178 179 size_t 180 arch_type_sizeof(struct process *proc, struct arg_type_info *info) 181 { 182 if (proc == NULL) 183 return (size_t)-2; 184 185 switch (info->type) { 186 case ARGTYPE_VOID: 187 return 0; 188 189 case ARGTYPE_CHAR: 190 return 1; 191 192 case ARGTYPE_SHORT: 193 case ARGTYPE_USHORT: 194 return 2; 195 196 case ARGTYPE_INT: 197 case ARGTYPE_UINT: 198 return 4; 199 200 case ARGTYPE_LONG: 201 case ARGTYPE_ULONG: 202 case ARGTYPE_POINTER: 203 return proc->e_class == ELFCLASS64 ? 8 : 4; 204 205 case ARGTYPE_FLOAT: 206 return 4; 207 case ARGTYPE_DOUBLE: 208 return 8; 209 210 case ARGTYPE_ARRAY: 211 case ARGTYPE_STRUCT: 212 /* Use default value. */ 213 return (size_t)-2; 214 215 default: 216 assert(info->type != info->type); 217 abort(); 218 } 219 } 220 221 size_t 222 arch_type_alignof(struct process *proc, struct arg_type_info *info) 223 { 224 if (proc == NULL) 225 return (size_t)-2; 226 227 switch (info->type) { 228 default: 229 assert(info->type != info->type); 230 break; 231 232 case ARGTYPE_CHAR: 233 return 1; 234 235 case ARGTYPE_SHORT: 236 case ARGTYPE_USHORT: 237 return 2; 238 239 case ARGTYPE_INT: 240 case ARGTYPE_UINT: 241 return 4; 242 243 case ARGTYPE_LONG: 244 case ARGTYPE_ULONG: 245 case ARGTYPE_POINTER: 246 return proc->e_class == ELFCLASS64 ? 8 : 4; 247 248 case ARGTYPE_FLOAT: 249 return 4; 250 case ARGTYPE_DOUBLE: 251 return 8; 252 253 case ARGTYPE_ARRAY: 254 case ARGTYPE_STRUCT: 255 /* Use default value. */ 256 return (size_t)-2; 257 } 258 abort(); 259 } 260