1a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/* 2a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This file is part of ltrace. 3a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 4a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Copyright (C) 2013 Imagination Technologies Ltd. 5a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 6a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This program is free software; you can redistribute it and/or 7a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * modify it under the terms of the GNU General Public License 8a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * version 2 as published by the Free Software Foundation. 9a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 10a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * This program is distributed in the hope that it will be useful, but 11a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * WITHOUT ANY WARRANTY; without even the implied warranty of 12a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * General Public License for more details. 14a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 15a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * You should have received a copy of the GNU General Public License 16a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * along with this program; if not, write to the Free Software 17a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 02110-1301 USA 19a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 20a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 21a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "config.h" 22a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 23a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/types.h> 24a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/wait.h> 25a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <signal.h> 26a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <sys/ptrace.h> 27a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <linux/uio.h> 28a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <asm/ptrace.h> 29a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include <assert.h> 30a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 31a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "proc.h" 32a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#include "common.h" 33a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 34a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define METAG_INSN_SIZE 4 35a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define N_UNITS 2 36a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras#define REG_SIZE 4 37a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 38a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/* unit codes */ 39a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasenum metag_unitnum { 40a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_CT, /* 0x0 */ 41a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_D0, 42a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_D1, 43a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_A0, 44a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_A1, /* 0x4 */ 45a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_PC, 46a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_RA, 47a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_TR, 48a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_TT, /* 0x8 */ 49a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_FX, 50a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_MAX, 51a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}; 52a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 53a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/** 54a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras \param proc The process that had an event. 55a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 56a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras Called by \c next_event() right after the return from wait. 57a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 58a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasvoid 59a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasget_arch_dep(struct process *proc) 60a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 61a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 62a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 63a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 64a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/** 65a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras \param proc Process that had event. 66a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras \param status From \c\ waitpid(). 67a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras \param sysnum 0-based syscall number. 68a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras \return 1 if syscall, 2 if sysret, 0 otherwise. 69a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 70a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras Called by \c next_event() after the call to get_arch_dep(). 71a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 72a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 73a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasint 74a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrassyscall_p(struct process *proc, int status, int *sysnum) 75a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 76a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (WIFSTOPPED(status) 77a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 78a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct user_gp_regs regs; 79a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct iovec iov; 80a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 81a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Get GP registers. */ 82a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 83a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 84a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, 85a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras (long)&iov)) 86a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return -1; 87a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 88a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Fetch the SWITCH instruction. */ 89a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unsigned int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, regs.pc, 90a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 0); 91a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras *sysnum = regs.dx[0][1]; 92a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 93a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (insn != 0xaf440001) { 94a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Check if we're returning from the system call. */ 95a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras insn = ptrace(PTRACE_PEEKTEXT, proc->pid, regs.pc - 4, 96a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 0); 97a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (insn == 0xaf440001) 98a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 2; 99a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 100a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 101a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 102a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 103a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (*sysnum >= 0) 104a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 1; 105a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 106a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 107a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 108a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 109a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras/* 2-bit base unit (BU) mapping. */ 110a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic enum metag_unitnum metag_bu_map[4] = { 111a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_A1, 112a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_D0, 113a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_D1, 114a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras METAG_UNIT_A0, 115a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras}; 116a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 117a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic int 118a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasget_regval_from_unit(enum metag_unitnum unit, unsigned int reg, 119a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct user_gp_regs *regs) 120a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 121a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* 122a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Check if reg has a sane value. 123a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * We do have N_UNITS, each one having X registers 124a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * and each register is REG_SIZE bytes. 125a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 126a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if ((unit == METAG_UNIT_A0) || (unit == METAG_UNIT_A1)) { 127a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (reg >= ((sizeof(regs->ax)/N_UNITS/REG_SIZE))) 128a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto bad_reg; 129a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((unit == METAG_UNIT_D0) || (unit == METAG_UNIT_D1)) { 130a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (reg >= ((sizeof(regs->dx)/N_UNITS/REG_SIZE))) 131a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto bad_reg; 132a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 133a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 134a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras switch(unit) { 135a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_A1: 136a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return regs->ax[reg][1]; 137a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_D0: 138a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return regs->dx[reg][0]; 139a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_D1: 140a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return regs->dx[reg][1]; 141a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_A0: 142a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return regs->ax[reg][0]; 143a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* We really shouldn't be here. */ 144a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras default: 145a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras assert(unit != unit); 146a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras abort(); 147a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 148a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 149a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 150a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasbad_reg: 151a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, 152a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras "Reading from register %d of unit %d is not implemented.", 153a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg, unit); 154a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 155a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 156a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 157a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 158a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasstatic int 159a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasmetag_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc) 160a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 161a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras uint32_t inst; 162a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras int nr = 0, imm, reg_val; 163a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unsigned int unit = 0, reg; 164a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct user_gp_regs regs; 165a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct iovec iov; 166a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 167a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras inst = ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0); 168a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 169a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (inst == 0xa0fffffe) { /* NOP (Special branch instruction) */ 170a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + 4; 171a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((inst & 0xff000000) == 0xa0000000) { 172a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Matching 0xA 0x0 for opcode for B #S19 or B<cc> #S19. 173a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 174a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Potential Targets: 175a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * - pc + #S19 * METAG_INSN_SIZE if R=1 or <CC> true 176a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * - pc + 4 */ 177a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras imm = ((inst << 8) >> 13) * METAG_INSN_SIZE; 178a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + imm; 179a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + 4; 180a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((inst & 0xff000000) == 0xac000000) { 181a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Matching 0xA 0xC for opcode. 182a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * JUMP BBx.r,#X16 or CALL BBx.r,#X16 183a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 184a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * pc = reg + #x16 (aligned) */ 185a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras imm = (inst >> 3) & 0xffff; 186a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg = (inst >> 19) & 0x1f; 187a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = metag_bu_map[inst & 0x3]; 188a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 189a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 190a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, 191a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras NT_PRSTATUS, (long)&iov)) 192a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto ptrace_fail; 193a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 194a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg_val = get_regval_from_unit(unit, reg, ®s); 195a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = (reg_val + imm) & -METAG_INSN_SIZE; 196a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((inst & 0xff000000) == 0xab000000) { 197a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Matching 0xA 0xB for opcode. 198a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 199a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * CALLR BBx.r,#S19 */ 200a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras imm = ((inst << 8) >> 13) * METAG_INSN_SIZE; 201a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + imm; 202a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((inst & 0xff0001e0) == 0xa30000a0) { 203a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* 204a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Matching 0xA 0x3 for opcode and then 205a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Ud (bit 8-5) = 0x5 = METAG_UNIT_PC 206a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 207a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Potential MOV PC,.. or SWAP<cc> PC,.. or SWAP<cc> ..,PC 208a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 209a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 210a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 211a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 212a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, 213a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras NT_PRSTATUS, (long)&iov)) 214a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto ptrace_fail; 215a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 216a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* 217a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Maybe PC is the source register for a SWAP? 218a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * bit9 = 1 and bit13-10(Us) == METAG_UNIT_PC 219a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras */ 220a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (((inst >> 9 ) & 0x1) && 221a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras (((inst >> 10) & 0xf) == METAG_UNIT_PC)) { 222a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* PC will get its value from the 223a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * destination register. */ 224a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg = (inst >> 14) & 0x1f; 225a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = (inst >> 5) & 0xf; 226a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else { /* PC is the destination register. 227a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * Find the source register. */ 228a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg = (inst >> 19) & 0x1f; 229a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = (inst >> 10) & 0xf; 230a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 231a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 232a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras switch(unit) { 233a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_D0: 234a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_D1: 235a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_A0: 236a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_A1: 237a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg_val = get_regval_from_unit(unit, reg, ®s); 238a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras break; 239a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case METAG_UNIT_PC: 240a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg_val = regs.pc; 241a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras break; 242a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras default: 243a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto unhandled; 244a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 245a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = reg_val; 246a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* In case it is a conditional instruction. */ 247a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + 4; 248a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if ((inst & 0xff00001f) == 0xc600000a){ 249a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Matching 0xC 0x{4,6} for opcode 250a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * and UD == 0x5 == METAG_UNIT_PC 251a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * 252a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * GETD PC, [A0.r + #S6] or 253a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras * GETD PC, [A0.r + A0.r] */ 254a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = metag_bu_map[(inst >> 5) & 0x3]; 255a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 256a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 257a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg = (inst >> 14) & 0x1f; 258a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras imm = (inst << 18) >> 5; /* sign-extend it */ 259a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, 260a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras NT_PRSTATUS, (long)&iov)) 261a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto ptrace_fail; 262a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg_val = get_regval_from_unit(unit, reg, ®s) + imm; 263a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* See where reg_val actually points to. */ 264a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = ptrace(PTRACE_PEEKTEXT, proc->pid, reg_val, 0); 265a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else if (((inst & 0xfe0001e0) == 0x840000a0) || /* ADDcc R, A, R */ 266a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xfe00003f) == 0x8600002a) || /* ADD R, A, #X8 */ 267a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xfe0001e0) == 0x8c0000a0) || /* SUBcc R, A, R */ 268a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xfe00003f) == 0x8e00002a) || /* SUB R, A, #X8 */ 269a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xf40001e0) == 0x040000a0) || /* ADDcc R, D, D */ 270a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xfe00003f) == 0x0600002a) || /* ADD R, D, #X8 */ 271a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xf40001e0) == 0x140000a0) || /* SUBcc R, D, D */ 272a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ((inst & 0xf600003f) == 0x1600002a)) { /* SUB R, D, #X8 */ 273a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 274a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* bits4-1(Ud) == METAG_UNIT_PC */ 275a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 276a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras int src1, src2, pc_src1 = 0, pc_src2 = 0, is_aunit = 0; 277a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras int umask = 0, optype = 0; 278a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 279a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Look for O2R bit */ 280a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if ((((inst >> 24) & 0x6) == 0x4) && (inst & 0x1)) 281a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto unhandled; 282a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 283a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 284a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 285a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, 286a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras NT_PRSTATUS, (long)&iov)) 287a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto ptrace_fail; 288a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 289a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Figure out unit for source registers based on the opcode. */ 290a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras switch((inst >> 28) & 0xf) { 291a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case 0: /* ADD<cc> Rx.r, Dx.r, De.r|#X8 */ 292a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case 1: /* SUB<cc> Rx.r, Dx.r, De.r|#X8 */ 293a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = METAG_UNIT_D0 + ((inst >> 24) & 0x1); 294a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras is_aunit = 0; 295a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras umask = 0x1f; 296a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras optype = (inst >> 28) & 0x1; 297a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras break; 298a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras case 8: 299a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras unit = METAG_UNIT_A0 + ((inst >> 24) & 0x1); 300a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras is_aunit = 1; 301a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras umask = 0xf; 302a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras optype = (inst >> 27) & 0x1; 303a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras break; 304a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 305a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 306a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Get pc bits (if any). */ 307a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (is_aunit) { 308a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras pc_src1 = (inst >> 18) & 0x1; 309a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras pc_src2 = (inst >> 13) & 0x1; 310a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 311a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 312a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Determine ADD|SUB format. Immediate or register ? */ 313a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if ((inst >> 25) & 0x1) { /* ADD|SUB cc PC, X, #imm8 */ 314a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src2 = (inst >> 6) & 0xff; /* so we can share code. */ 315a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras reg = (inst >> 14) & umask; 316a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (pc_src1) /* This can only be true for AU ops. */ 317a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src1 = regs.pc; 318a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras else /* This covers both AU an DU ops. */ 319a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src1 = get_regval_from_unit(unit, reg, ®s); 320a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else { /* ADD|SUB cc PC, X, X */ 321a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (pc_src1) 322a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src1 = regs.pc; 323a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras else 324a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src1 = get_regval_from_unit(unit, (inst >> 14) 325a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras & umask, ®s); 326a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (pc_src2) 327a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src2 = regs.pc; 328a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras else 329a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras src2 = get_regval_from_unit(unit, (inst >> 9) 330a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras & umask, ®s); 331a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 332a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 333a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Construct the new PC. */ 334a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (optype) 335a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* SUB */ 336a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = src1 - src2; 337a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras else /* ADD */ 338a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = src1 + src2; 339a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Conditional instruction so PC may not change. */ 340a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + 4; 341a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else { 342a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras newpc[nr++] = pc + 4; 343a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 344a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 345a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (nr <= 0 || nr > 2) 346a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto fail; 347a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (nr == 2 && newpc[1] == 0) 348a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras goto fail; 349a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 350a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return nr; 351a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 352a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasptrace_fail: 353a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "Failed to read the registers pid=%d @ pc=0x%08x\n", 354a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras proc->pid, pc); 355a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 356a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasunhandled: 357a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "Unhandled instruction: pc=0x%08x, inst=0x%08x\n", 358a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras pc, inst); 359a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 360a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasfail: 361a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "nr=%d pc=0x%08x\n", nr, pc); 362a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "newpc=0x%08x 0x%08x\n", newpc[0], newpc[1]); 363a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 364a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 365a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 366a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 367a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasenum sw_singlestep_status 368a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasarch_sw_singlestep(struct process *proc, struct breakpoint *bp, 369a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras int (*add_cb)(arch_addr_t, struct sw_singlestep_data *), 370a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct sw_singlestep_data *add_cb_data) 371a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 372a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras arch_addr_t pc = get_instruction_pointer(proc); 373a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras uint32_t newpcs[2]; 374a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras int nr; 375a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 376a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras nr = metag_next_pcs(proc, (uint32_t)pc, newpcs); 377a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 378a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras while (nr-- > 0) { 379a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras arch_addr_t baddr = (arch_addr_t) newpcs[nr]; 380a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (dict_find(proc->leader->breakpoints, &baddr) != NULL) { 381a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "skip %p %p\n", baddr, add_cb_data); 382a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras continue; 383a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 384a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 385a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (add_cb(baddr, add_cb_data) < 0) 386a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return SWS_FAIL; 387a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 388a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 389a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ptrace(PTRACE_SYSCALL, proc->pid, 0, 0); 390a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return SWS_OK; 391a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 392a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 393a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandraslong 394a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandrasgimme_arg(enum tof type, struct process *proc, int arg_num, 395a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct arg_type_info *info) 396a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras{ 397a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras long ret; 398a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct user_gp_regs regs; 399a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras struct iovec iov; 400a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 401a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* get GP registers */ 402a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_base = ®s; 403a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras iov.iov_len = sizeof(regs); 404a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, (long)&iov)) 405a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 406a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 407a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras debug(2, "type %d arg %d arg",type, arg_num); 408a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL) { 409a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (arg_num < 6) { 410a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras /* Args go backwards starting from D1Ar1 (D1.3) */ 411a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras ret = ((unsigned long *)®s.dx[3][1])[-arg_num]; 412a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras debug(2,"ret = %#lx",ret); 413a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return ret; 414a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } else { 415a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 416a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 417a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 418a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (arg_num >= 0) { 419a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr,"args on return?"); 420a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 421a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras if (type == LT_TOF_FUNCTIONR || type == LT_TOF_SYSCALLR) { 422a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return regs.dx[0][0]; /* D0Re0 (D0.0) */ 423a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras } 424a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 425a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras fprintf(stderr, "gimme_arg called with wrong arguments\n"); 426a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras 427a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras return 0; 428a193452188e51f233677e3f2607d9a61a789a1dfMarkos Chandras} 429