Home | History | Annotate | Download | only in ia64
      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 */
     42 union 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 
     60 union 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 
     72 int
     73 syscall_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 
    144 void
    145 get_arch_dep(struct process *proc)
    146 {
    147 }
    148