1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/* 2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace. 319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc. 4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 1998,2004,2008,2009 Juan Cespedes 5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Ian Wienand 6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or 8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as 9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the 10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version. 11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but 13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details. 16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License 18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software 19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA 21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */ 22e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata 23d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes#include "config.h" 24d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes 2563184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#include <string.h> 268e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <sys/types.h> 278e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <sys/wait.h> 288e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <signal.h> 298e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <sys/ptrace.h> 308e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <asm/ptrace.h> 318e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 32d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata#include "bits.h" 33f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h" 34d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata#include "proc.h" 3563184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#include "output.h" 3663184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#include "ptrace.h" 379fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#include "regs.h" 38f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata#include "type.h" 398e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 408e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 418e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes# define PTRACE_PEEKUSER PTRACE_PEEKUSR 428e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#endif 438e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 448e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 458e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes# define PTRACE_POKEUSER PTRACE_POKEUSR 468e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#endif 478e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 48f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid 49929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_arch_dep(struct process *proc) 50929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 5163184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes proc_archdep *a; 5263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes 5363184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes if (!proc->arch_ptr) 5463184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); 5563184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes a = (proc_archdep *) (proc->arch_ptr); 5663184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0); 575c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 585c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 5963184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes/* Returns 0 if not a syscall, 6063184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * 1 if syscall entry, 2 if syscall exit, 6163184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * 3 if arch-specific syscall entry, 4 if arch-specific syscall exit, 6263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * -1 on error. 638e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes */ 64f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesint 65929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasyscall_p(struct process *proc, int status, int *sysnum) 66929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 672d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (WIFSTOPPED(status) 682d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 69f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata uint32_t pc, ip; 70f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata if (arm_get_register(proc, ARM_REG_PC, &pc) < 0 71f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata || arm_get_register(proc, ARM_REG_IP, &ip) < 0) 72f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return -1; 73f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata 74c897cb796dc4a7d256cbfbf0137ef7cdff9e8ecePetr Machata pc = pc - 4; 75f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata 768e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes /* fetch the SWI instruction */ 77c897cb796dc4a7d256cbfbf0137ef7cdff9e8ecePetr Machata unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid, 78c897cb796dc4a7d256cbfbf0137ef7cdff9e8ecePetr Machata (void *)pc, 0); 792d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand 80e280a5e51b72825ab3234c532f832cd64695bc1eZach Welch if (insn == 0xef000000 || insn == 0x0f000000 81e280a5e51b72825ab3234c532f832cd64695bc1eZach Welch || (insn & 0xffff0000) == 0xdf000000) { 8263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* EABI syscall */ 83f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata uint32_t r7; 84f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata if (arm_get_register(proc, ARM_REG_R7, &r7) < 0) 85f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return -1; 86f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata *sysnum = r7; 8763184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes } else if ((insn & 0xfff00000) == 0xef900000) { 8863184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* old ABI syscall */ 8963184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes *sysnum = insn & 0xfffff; 9063184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes } else { 9163184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* TODO: handle swi<cond> variations */ 9263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* one possible reason for getting in here is that we 9363184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * are coming from a signal handler, so the current 9463184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * PC does not point to the instruction just after the 9563184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * "swi" one. */ 96c897cb796dc4a7d256cbfbf0137ef7cdff9e8ecePetr Machata output_line(proc, "unexpected instruction 0x%x at %p", 97c897cb796dc4a7d256cbfbf0137ef7cdff9e8ecePetr Machata insn, pc); 9832e8e76f492a48ee3e6284e237f958b71d4d3e71Arnaud Patard return 0; 9963184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes } 10063184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes if ((*sysnum & 0xf0000) == 0xf0000) { 10163184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* arch-specific syscall */ 10263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes *sysnum &= ~0xf0000; 10363184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes return ip ? 4 : 3; 1048e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes } 10563184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes /* ARM syscall convention: on syscall entry, ip is zero; 10663184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes * on syscall exit, ip is non-zero */ 10763184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes return ip ? 2 : 1; 1088e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes } 1098e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes return 0; 1108e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes} 1112d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand 11219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machatastatic arch_addr_t 11319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machataarm_branch_dest(const arch_addr_t pc, const uint32_t insn) 11419e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata{ 11519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata /* Bits 0-23 are signed immediate value. */ 11619e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return pc + ((((insn & 0xffffff) ^ 0x800000) - 0x800000) << 2) + 8; 11719e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata} 11819e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 1199fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata/* Addresses for calling Thumb functions have the bit 0 set. 1209fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata Here are some macros to test, set, or clear bit 0 of addresses. */ 1219fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata/* XXX double cast */ 1229fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#define IS_THUMB_ADDR(addr) ((uintptr_t)(addr) & 1) 1239fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#define MAKE_THUMB_ADDR(addr) ((arch_addr_t)((uintptr_t)(addr) | 1)) 1249fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#define UNMAKE_THUMB_ADDR(addr) ((arch_addr_t)((uintptr_t)(addr) & ~1)) 1259fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 126037f37c72e252b05c59e53826d5007d24d54ac74Petr Machataenum { 127037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata COND_ALWAYS = 0xe, 128037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata COND_NV = 0xf, 129037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata FLAG_C = 0x20000000, 130037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata}; 131037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 13219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machatastatic int 133d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machataarm_get_next_pcs(struct process *proc, 134d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata const arch_addr_t pc, arch_addr_t next_pcs[2]) 13519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata{ 1369fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t this_instr; 1379fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t status; 1389fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (proc_read_32(proc, pc, &this_instr) < 0 1399fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata || arm_get_register(proc, ARM_REG_CPSR, &status) < 0) 14019e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return -1; 14119e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 14219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata /* In theory, we sometimes don't even need to add any 14319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * breakpoints at all. If the conditional bits of the 14419e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * instruction indicate that it should not be taken, then we 14519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * can just skip it altogether without bothering. We could 1467aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata * also emulate the instruction under the breakpoint. 14719e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * 14819e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * Here, we make it as simple as possible (though We Accept 14919e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * Patches). */ 15019e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata int nr = 0; 15119e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 15219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata /* ARM can branch either relatively by using a branch 15319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata * instruction, or absolutely, by doing arbitrary arithmetic 1549fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata * with PC as the destination. */ 1559fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata const unsigned cond = BITS(this_instr, 28, 31); 1569fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata const unsigned opcode = BITS(this_instr, 24, 27); 1579fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1589fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (cond == COND_NV) 1599fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata switch (opcode) { 1609fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata arch_addr_t addr; 1619fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xa: 1629fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xb: 1639fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* Branch with Link and change to Thumb. */ 1649fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX double cast. */ 1659fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata addr = (arch_addr_t) 1669fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata ((uint32_t)arm_branch_dest(pc, this_instr) 1679fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata | (((this_instr >> 24) & 0x1) << 1)); 1689fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = MAKE_THUMB_ADDR(addr); 1699fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1709fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 1719fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata else 1729fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata switch (opcode) { 1739fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t operand1, operand2, result = 0; 1749fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x0: 1759fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x1: /* data processing */ 1769fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x2: 1779fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x3: 1789fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BITS(this_instr, 12, 15) != ARM_REG_PC) 1799fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1809fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1819fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BITS(this_instr, 22, 25) == 0 1829fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata && BITS(this_instr, 4, 7) == 9) { /* multiply */ 1839fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata invalid: 1849fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata fprintf(stderr, 1859fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata "Invalid update to pc in instruction.\n"); 1869fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1879fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 1889fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1899fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* BX <reg>, BLX <reg> */ 1909fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BITS(this_instr, 4, 27) == 0x12fff1 1919fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata || BITS(this_instr, 4, 27) == 0x12fff3) { 1929fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata enum arm_register reg = BITS(this_instr, 0, 3); 1939fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX double cast: no need to go 1949fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata * through tmp. */ 1959fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t tmp; 1969fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_register_offpc(proc, reg, &tmp) < 0) 1979fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 1989fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = (arch_addr_t)tmp; 1999fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return 0; 2009fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 2019fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2029fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* Multiply into PC. */ 2039fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_register_offpc 2049fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata (proc, BITS(this_instr, 16, 19), &operand1) < 0) 2059fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 2069fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2079fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata int c = (status & FLAG_C) ? 1 : 0; 2089fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(this_instr, 25)) { 2099fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t immval = BITS(this_instr, 0, 7); 2109fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t rotate = 2 * BITS(this_instr, 8, 11); 2119fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata operand2 = (((immval >> rotate) 2129fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata | (immval << (32 - rotate))) 2139fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata & 0xffffffff); 2149fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } else { 2159fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* operand 2 is a shifted register. */ 2169fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_shifted_register 2179fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata (proc, this_instr, c, pc, &operand2) < 0) 2189fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 2199fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 2209fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2219fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata switch (BITS(this_instr, 21, 24)) { 2229fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x0: /*and */ 2239fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 & operand2; 2249fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2259fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2269fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x1: /*eor */ 2279fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 ^ operand2; 2289fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2299fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2309fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x2: /*sub */ 2319fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 - operand2; 2329fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2339fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2349fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x3: /*rsb */ 2359fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand2 - operand1; 2369fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2379fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2389fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x4: /*add */ 2399fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 + operand2; 2409fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2419fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2429fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x5: /*adc */ 2439fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 + operand2 + c; 2449fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2459fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2469fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x6: /*sbc */ 2479fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 - operand2 + c; 2489fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2499fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2509fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x7: /*rsc */ 2519fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand2 - operand1 + c; 2529fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2539fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2549fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x8: 2559fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x9: 2569fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xa: 2579fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xb: /* tst, teq, cmp, cmn */ 2589fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* Only take the default branch. */ 2599fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = 0; 2609fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2619fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2629fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xc: /*orr */ 2639fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 | operand2; 2649fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2659fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2669fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xd: /*mov */ 2679fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* Always step into a function. */ 2689fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand2; 2699fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2709fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2719fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xe: /*bic */ 2729fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = operand1 & ~operand2; 2739fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2749fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2759fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xf: /*mvn */ 2769fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata result = ~operand2; 2779fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2789fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 2799fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2809fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX double cast */ 2819fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = (arch_addr_t)result; 2829fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2839fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2849fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x4: 2859fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x5: /* data transfer */ 2869fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x6: 2879fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0x7: 2889fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* Ignore if insn isn't load or Rn not PC. */ 2899fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (!BIT(this_instr, 20) 2909fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata || BITS(this_instr, 12, 15) != ARM_REG_PC) 2919fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 2929fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2939fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(this_instr, 22)) 2949fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata goto invalid; 2959fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 2969fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* byte write to PC */ 2979fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t base; 2989fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_register_offpc 2999fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata (proc, BITS(this_instr, 16, 19), &base) < 0) 3009fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 3019fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 3029fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(this_instr, 24)) { 3039fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* pre-indexed */ 3049fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata int c = (status & FLAG_C) ? 1 : 0; 3059fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t offset; 3069fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(this_instr, 25)) { 3079fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_shifted_register 3089fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata (proc, this_instr, c, 3099fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata pc, &offset) < 0) 3109fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 3119fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } else { 3129fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata offset = BITS(this_instr, 0, 11); 3139fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 3149fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 3159fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(this_instr, 23)) 3169fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata base += offset; 3179fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata else 3189fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata base -= offset; 3199fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 3209fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 3219fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX two double casts. */ 3229fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t next; 3239fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (proc_read_32(proc, (arch_addr_t)base, &next) < 0) 3249fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 3259fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = (arch_addr_t)next; 3269fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 3279fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 3287aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0x8: 3297aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0x9: /* block transfer */ 3307aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (!BIT(this_instr, 20)) 3317aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata break; 3327aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata /* LDM */ 3337aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (BIT(this_instr, 15)) { 3347aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata /* Loading pc. */ 3357aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata int offset = 0; 3367aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata enum arm_register rn = BITS(this_instr, 16, 19); 3377aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata uint32_t rn_val; 3387aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (arm_get_register(proc, rn, &rn_val) < 0) 3397aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata return -1; 3407aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata 3417aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata int pre = BIT(this_instr, 24); 3427aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (BIT(this_instr, 23)) { 3437aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata /* Bit U = up. */ 3447aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata unsigned reglist 3457aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata = BITS(this_instr, 0, 14); 3467aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata offset = bitcount(reglist) * 4; 3477aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (pre) 3487aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata offset += 4; 3497aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata } else if (pre) { 3507aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata offset = -4; 3517aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata } 3527aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata 3537aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata /* XXX double cast. */ 3547aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata arch_addr_t addr 3557aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata = (arch_addr_t)(rn_val + offset); 3567aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata uint32_t next; 3577aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata if (proc_read_32(proc, addr, &next) < 0) 3587aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata return -1; 3597aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata next_pcs[nr++] = (arch_addr_t)next; 3607aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata } 3617aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata break; 3627aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata 3639fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xb: /* branch & link */ 3649fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0xa: /* branch */ 3659fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = arm_branch_dest(pc, this_instr); 3669fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 3677aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata 3687aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0xc: 3697aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0xd: 3707aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0xe: /* coproc ops */ 3717aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata case 0xf: /* SWI */ 3727aa7b404588184ef9a45eeafbfc5ef4afc7fbf82Petr Machata break; 3739fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 37419e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 37519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata /* Otherwise take the next instruction. */ 3769fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (cond != COND_ALWAYS || nr == 0) 3779fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata next_pcs[nr++] = pc + 4; 37819e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return 0; 37919e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata} 38019e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 381037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata/* Return the size in bytes of the complete Thumb instruction whose 382037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata * first halfword is INST1. */ 383037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 384037f37c72e252b05c59e53826d5007d24d54ac74Petr Machatastatic int 385037f37c72e252b05c59e53826d5007d24d54ac74Petr Machatathumb_insn_size (unsigned short inst1) 386037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata{ 387037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0) 388037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 4; 389037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata else 390037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 2; 391037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata} 392037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 393d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machatastatic int 394d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machatathumb_get_next_pcs(struct process *proc, 395d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata const arch_addr_t pc, arch_addr_t next_pcs[2]) 396d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata{ 397d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata uint16_t inst1; 398d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata uint32_t status; 399d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if (proc_read_16(proc, pc, &inst1) < 0 400d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata || arm_get_register(proc, ARM_REG_CPSR, &status) < 0) 401d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata return -1; 402d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 403d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata int nr = 0; 404d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 405d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata /* We currently ignore Thumb-2 conditional execution support 406d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata * (the IT instruction). No branches are allowed in IT block, 407d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata * and it's not legal to jump in the middle of it, so unless 408d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata * we need to singlestep through large swaths of code, which 409d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata * we currently don't, we can ignore them. */ 410d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 411d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if ((inst1 & 0xff00) == 0xbd00) { /* pop {rlist, pc} */ 412d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata /* Fetch the saved PC from the stack. It's stored 413d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata * above all of the other registers. */ 414037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned offset = bitcount(BITS(inst1, 0, 7)) * 4; 415d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata uint32_t sp; 416d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata uint32_t next; 417d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata /* XXX two double casts */ 418d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if (arm_get_register(proc, ARM_REG_SP, &sp) < 0 419d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata || proc_read_32(proc, (arch_addr_t)(sp + offset), 420d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata &next) < 0) 421d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata return -1; 422d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata next_pcs[nr++] = (arch_addr_t)next; 423037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xf000) == 0xd000) { /* conditional branch */ 424037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned long cond = BITS(inst1, 8, 11); 425037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (cond != 0x0f) { /* SWI */ 426037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + (SBITS(inst1, 0, 7) << 1); 427037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (cond == COND_ALWAYS) 428037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 0; 429037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 430037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xf800) == 0xe000) { /* unconditional branch */ 431037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + (SBITS(inst1, 0, 10) << 1); 432037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (thumb_insn_size(inst1) == 4) { /* 32-bit instruction */ 433037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata unsigned short inst2; 434037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (proc_read_16(proc, pc + 2, &inst2) < 0) 435037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 436037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 437037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000) { 438037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* Branches and miscellaneous control instructions. */ 439037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 440037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if ((inst2 & 0x1000) != 0 441037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata || (inst2 & 0xd001) == 0xc000) { 442037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* B, BL, BLX. */ 443037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 444037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const int imm1 = SBITS(inst1, 0, 10); 445037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned imm2 = BITS(inst2, 0, 10); 446037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned j1 = BIT(inst2, 13); 447037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned j2 = BIT(inst2, 11); 448037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 449037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata int32_t offset 450037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata = ((imm1 << 12) + (imm2 << 1)); 451037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset ^= ((!j2) << 22) | ((!j1) << 23); 452037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 453037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 454037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t next = (uint32_t)(pc + offset); 455037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* For BLX make sure to clear the low bits. */ 456037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BIT(inst2, 12) == 0) 457037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next = next & 0xfffffffc; 458037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 459037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = (arch_addr_t)next; 460037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 0; 461037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (inst1 == 0xf3de 462037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst2 & 0xff00) == 0x3f00) { 463037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* SUBS PC, LR, #imm8. */ 464037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t next; 465037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, ARM_REG_LR, 466037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata &next) < 0) 467037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 468037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next -= inst2 & 0x00ff; 469037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 470037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = (arch_addr_t)next; 471037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 0; 472037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst2 & 0xd000) == 0x8000 473037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst1 & 0x0380) != 0x0380) { 474037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* Conditional branch. */ 475037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const int sign = SBITS(inst1, 10, 10); 476037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned imm1 = BITS(inst1, 0, 5); 477037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned imm2 = BITS(inst2, 0, 10); 478037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned j1 = BIT(inst2, 13); 479037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const unsigned j2 = BIT(inst2, 11); 480037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 481037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata int32_t offset = (sign << 20) 482037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata + (j2 << 19) + (j1 << 18); 483037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset += (imm1 << 12) + (imm2 << 1); 484037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + offset; 485037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BITS(inst1, 6, 9) == COND_ALWAYS) 486037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return 0; 487037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 488037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xfe50) == 0xe810) { 489037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata int load_pc = 1; 490037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata int offset; 491037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register rn = BITS(inst1, 0, 3); 492037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 493037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BIT(inst1, 7) && !BIT(inst1, 8)) { 494037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* LDMIA or POP */ 495037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (!BIT(inst2, 15)) 496037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata load_pc = 0; 497037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset = bitcount(inst2) * 4 - 4; 498037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (!BIT(inst1, 7) && BIT(inst1, 8)) { 499037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* LDMDB */ 500037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (!BIT(inst2, 15)) 501037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata load_pc = 0; 502037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset = -4; 503037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (BIT(inst1, 7) && BIT(inst1, 8)) { 504037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* RFEIA */ 505037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset = 0; 506037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (!BIT(inst1, 7) && !BIT(inst1, 8)) { 507037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* RFEDB */ 508037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata offset = -8; 509037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else { 510037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata load_pc = 0; 511037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 512037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 513037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (load_pc) { 514037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t addr; 515037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, rn, &addr) < 0) 516037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 517037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata arch_addr_t a = (arch_addr_t)(addr + offset); 518037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t next; 519037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (proc_read_32(proc, a, &next) < 0) 520037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 521037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 522037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = (arch_addr_t)next; 523037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 524037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xffef) == 0xea4f 525037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst2 & 0xfff0) == 0x0f00) { 526037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* MOV PC or MOVS PC. */ 527037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register rn = BITS(inst2, 0, 3); 528037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t next; 529037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, rn, &next) < 0) 530037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 531037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 532037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = (arch_addr_t)next; 533037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xff70) == 0xf850 534037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst2 & 0xf000) == 0xf000) { 535037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* LDR PC. */ 536037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register rn = BITS(inst1, 0, 3); 537037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t base; 538037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, rn, &base) < 0) 539037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 540037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 541037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata int load_pc = 1; 542037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (rn == ARM_REG_PC) { 543037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base = (base + 4) & ~(uint32_t)0x3; 544037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BIT(inst1, 7)) 545037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base += BITS(inst2, 0, 11); 546037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata else 547037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base -= BITS(inst2, 0, 11); 548037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (BIT(inst1, 7)) { 549037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base += BITS(inst2, 0, 11); 550037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if (BIT(inst2, 11)) { 551037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BIT(inst2, 10)) { 552037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (BIT(inst2, 9)) 553037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base += BITS(inst2, 0, 7); 554037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata else 555037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base -= BITS(inst2, 0, 7); 556037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 557037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst2 & 0x0fc0) == 0x0000) { 558037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const int shift = BITS(inst2, 4, 5); 559037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register rm = BITS(inst2, 0, 3); 560037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t v; 561037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, rm, &v) < 0) 562037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 563037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata base += v << shift; 564037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else { 565037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* Reserved. */ 566037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata load_pc = 0; 567037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 568037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 569037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (load_pc) { 570037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* xxx double casts */ 571037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t next; 572037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (proc_read_32(proc, 573037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata (arch_addr_t)base, &next) < 0) 574037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 575037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = (arch_addr_t)next; 576037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 577037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xfff0) == 0xe8d0 578037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst2 & 0xfff0) == 0xf000) { 579037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* TBB. */ 580037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register tbl_reg = BITS(inst1, 0, 3); 581037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register off_reg = BITS(inst2, 0, 3); 582037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 583037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t table; 584037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (tbl_reg == ARM_REG_PC) 585037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* Regcache copy of PC isn't right yet. */ 586037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 587037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata table = (uint32_t)pc + 4; 588037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata else if (arm_get_register(proc, tbl_reg, &table) < 0) 589037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 590037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 591037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t offset; 592037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, off_reg, &offset) < 0) 593037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 594037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 595037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata table += offset; 596037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint8_t length; 597037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 598037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (proc_read_8(proc, (arch_addr_t)table, &length) < 0) 599037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 600037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 601037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + 2 * length; 602037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 603037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } else if ((inst1 & 0xfff0) == 0xe8d0 604037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata && (inst2 & 0xfff0) == 0xf010) { 605037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* TBH. */ 606037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register tbl_reg = BITS(inst1, 0, 3); 607037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata const enum arm_register off_reg = BITS(inst2, 0, 3); 608037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 609037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t table; 610037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (tbl_reg == ARM_REG_PC) 611037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* Regcache copy of PC isn't right yet. */ 612037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 613037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata table = (uint32_t)pc + 4; 614037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata else if (arm_get_register(proc, tbl_reg, &table) < 0) 615037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 616037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 617037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint32_t offset; 618037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (arm_get_register(proc, off_reg, &offset) < 0) 619037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 620037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 621037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata table += 2 * offset; 622037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata uint16_t length; 623037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata /* XXX double cast */ 624037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata if (proc_read_16(proc, (arch_addr_t)table, &length) < 0) 625037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata return -1; 626037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 627037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + 2 * length; 628037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata } 629d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata } 630d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 631037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata 632d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata /* Otherwise take the next instruction. */ 633d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if (nr == 0) 634037f37c72e252b05c59e53826d5007d24d54ac74Petr Machata next_pcs[nr++] = pc + thumb_insn_size(inst1); 635d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata return 0; 636d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata} 637d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 63819e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machataenum sw_singlestep_status 63919e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machataarch_sw_singlestep(struct process *proc, struct breakpoint *sbp, 64019e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata int (*add_cb)(arch_addr_t, struct sw_singlestep_data *), 64119e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata struct sw_singlestep_data *add_cb_data) 64219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata{ 643d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata const arch_addr_t pc = get_instruction_pointer(proc); 644d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 645d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata uint32_t cpsr; 646d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if (arm_get_register(proc, ARM_REG_CPSR, &cpsr) < 0) 647d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata return SWS_FAIL; 648d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata 649d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata const unsigned thumb_p = BIT(cpsr, 5); 65019e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata arch_addr_t next_pcs[2] = {}; 651d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if ((thumb_p ? &thumb_get_next_pcs 652d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata : &arm_get_next_pcs)(proc, pc, next_pcs) < 0) 65319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return SWS_FAIL; 65419e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 65519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata int i; 65619e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata for (i = 0; i < 2; ++i) { 657d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata /* XXX double cast. */ 658d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata arch_addr_t target 659d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata = (arch_addr_t)(((uintptr_t)next_pcs[i]) | thumb_p); 660d4a5447503b7bddfb6d7667747ee1eedd20ae491Petr Machata if (next_pcs[i] != 0 && add_cb(target, add_cb_data) < 0) 66119e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return SWS_FAIL; 66219e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata } 66319e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata 66419e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata debug(1, "PTRACE_CONT"); 66519e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata ptrace(PTRACE_CONT, proc->pid, 0, 0); 66619e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata return SWS_OK; 66719e74b5815987bb4260351bc1e5ef4a1ea08b1b4Petr Machata} 668427a43ee9972763993a1241815d56921f30623efPetr Machata 669427a43ee9972763993a1241815d56921f30623efPetr Machatasize_t 670427a43ee9972763993a1241815d56921f30623efPetr Machataarch_type_sizeof(struct process *proc, struct arg_type_info *info) 671427a43ee9972763993a1241815d56921f30623efPetr Machata{ 672427a43ee9972763993a1241815d56921f30623efPetr Machata if (proc == NULL) 673427a43ee9972763993a1241815d56921f30623efPetr Machata return (size_t)-2; 674427a43ee9972763993a1241815d56921f30623efPetr Machata 675427a43ee9972763993a1241815d56921f30623efPetr Machata switch (info->type) { 676427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_VOID: 677427a43ee9972763993a1241815d56921f30623efPetr Machata return 0; 678427a43ee9972763993a1241815d56921f30623efPetr Machata 679427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_CHAR: 680427a43ee9972763993a1241815d56921f30623efPetr Machata return 1; 681427a43ee9972763993a1241815d56921f30623efPetr Machata 682427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_SHORT: 683427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_USHORT: 684427a43ee9972763993a1241815d56921f30623efPetr Machata return 2; 685427a43ee9972763993a1241815d56921f30623efPetr Machata 686427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_INT: 687427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_UINT: 688427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_LONG: 689427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_ULONG: 690427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_POINTER: 691427a43ee9972763993a1241815d56921f30623efPetr Machata return 4; 692427a43ee9972763993a1241815d56921f30623efPetr Machata 693427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_FLOAT: 694427a43ee9972763993a1241815d56921f30623efPetr Machata return 4; 695427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_DOUBLE: 696427a43ee9972763993a1241815d56921f30623efPetr Machata return 8; 697427a43ee9972763993a1241815d56921f30623efPetr Machata 698427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_ARRAY: 699427a43ee9972763993a1241815d56921f30623efPetr Machata case ARGTYPE_STRUCT: 700427a43ee9972763993a1241815d56921f30623efPetr Machata /* Use default value. */ 701427a43ee9972763993a1241815d56921f30623efPetr Machata return (size_t)-2; 702427a43ee9972763993a1241815d56921f30623efPetr Machata 703427a43ee9972763993a1241815d56921f30623efPetr Machata default: 704427a43ee9972763993a1241815d56921f30623efPetr Machata assert(info->type != info->type); 705427a43ee9972763993a1241815d56921f30623efPetr Machata abort(); 706427a43ee9972763993a1241815d56921f30623efPetr Machata } 707427a43ee9972763993a1241815d56921f30623efPetr Machata} 708427a43ee9972763993a1241815d56921f30623efPetr Machata 709427a43ee9972763993a1241815d56921f30623efPetr Machatasize_t 710427a43ee9972763993a1241815d56921f30623efPetr Machataarch_type_alignof(struct process *proc, struct arg_type_info *info) 711427a43ee9972763993a1241815d56921f30623efPetr Machata{ 712427a43ee9972763993a1241815d56921f30623efPetr Machata return arch_type_sizeof(proc, info); 713427a43ee9972763993a1241815d56921f30623efPetr Machata} 714