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