1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2008,2009 Juan Cespedes 4 * Copyright (C) 2006 Steve Fink 5 * Copyright (C) 2006 Ian Wienand 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 23#include "config.h" 24 25#include <stdlib.h> 26#include <stddef.h> 27#include <sys/types.h> 28#include <sys/wait.h> 29#include <signal.h> 30#include <sys/ptrace.h> 31#include <string.h> 32#include <asm/ptrace_offsets.h> 33#include <asm/rse.h> 34#include <errno.h> 35 36#include "proc.h" 37#include "common.h" 38#include "type.h" 39 40/* What we think of as a bundle, ptrace thinks of it as two unsigned 41 * longs */ 42union bundle_t { 43 /* An IA64 instruction bundle has a 5 bit header describing the 44 * type of bundle, then 3 41 bit instructions 45 */ 46 struct { 47 struct { 48 unsigned long template:5; 49 unsigned long slot0:41; 50 unsigned long bot_slot1:18; 51 } word0; 52 struct { 53 unsigned long top_slot1:23; 54 unsigned long slot2:41; 55 } word1; 56 } bitmap; 57 unsigned long code[2]; 58}; 59 60union cfm_t { 61 struct { 62 unsigned long sof:7; 63 unsigned long sol:7; 64 unsigned long sor:4; 65 unsigned long rrb_gr:7; 66 unsigned long rrb_fr:7; 67 unsigned long rrb_pr:6; 68 } cfm; 69 unsigned long value; 70}; 71 72int 73syscall_p(struct process *proc, int status, int *sysnum) 74{ 75 if (WIFSTOPPED(status) 76 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 77 long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0); 78 if (l == -1 && errno) 79 return -1; 80 unsigned long slot = ((unsigned long)l >> 41) & 0x3; 81 unsigned long ip = 82 ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0); 83 84 /* r15 holds the system call number */ 85 unsigned long r15 = 86 ptrace(PTRACE_PEEKUSER, proc->pid, PT_R15, 0); 87 unsigned long insn; 88 89 union bundle_t bundle; 90 91 /* On fault, the IP has moved forward to the next 92 * slot. If that is zero, then the actual place we 93 * broke was in the previous bundle, so wind back the 94 * IP. 95 */ 96 if (slot == 0) 97 ip = ip - 16; 98 bundle.code[0] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); 99 bundle.code[1] = ptrace(PTRACE_PEEKTEXT, proc->pid, ip + 8, 0); 100 101 unsigned long bot = 0UL | bundle.bitmap.word0.bot_slot1; 102 unsigned long top = 0UL | bundle.bitmap.word1.top_slot1; 103 104 /* handle the rollback, slot 0 is actually slot 2 of 105 * the previous instruction (see above) */ 106 switch (slot) { 107 case 0: 108 insn = bundle.bitmap.word1.slot2; 109 break; 110 case 1: 111 insn = bundle.bitmap.word0.slot0; 112 break; 113 case 2: 114 /* make sure we're shifting about longs */ 115 insn = 0UL | bot | (top << 18UL); 116 break; 117 default: 118 printf("Ummm, can't find instruction slot?\n"); 119 exit(1); 120 } 121 122 /* We need to support both the older break instruction 123 * type syscalls, and the new epc type ones. 124 * 125 * Bit 20 of the break constant is encoded in the "i" 126 * bit (bit 36) of the instruction, hence you should 127 * see 0x1000000000. 128 * 129 * An EPC call is just 0x1ffffffffff 130 */ 131 if (insn == 0x1000000000 || insn == 0x1ffffffffff) { 132 *sysnum = r15; 133 if (proc->callstack_depth > 0 && 134 proc->callstack[proc->callstack_depth - 1].is_syscall && 135 proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 136 return 2; 137 } 138 return 1; 139 } 140 } 141 return 0; 142} 143 144void 145get_arch_dep(struct process *proc) 146{ 147} 148