1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/* 2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace. 39fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata * Copyright (C) 2013 Petr Machata, Red Hat Inc. 4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes 5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2009 Juan Cespedes 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 258e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <sys/types.h> 268e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <sys/ptrace.h> 278e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#include <asm/ptrace.h> 289fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#include <errno.h> 298e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 30366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h" 31f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h" 329fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata#include "regs.h" 335c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 348e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 358e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes# define PTRACE_PEEKUSER PTRACE_PEEKUSR 368e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#endif 378e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 388e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 398e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes# define PTRACE_POKEUSER PTRACE_POKEUSR 408e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes#endif 418e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 429fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataint 439fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataarm_get_register(struct process *proc, enum arm_register reg, uint32_t *lp) 449fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata{ 459fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata errno = 0; 466b9664af2e87596055eaab59492e79bfd1527dabPetr Machata long l = ptrace(PTRACE_PEEKUSER, proc->pid, (void *)(reg * 4L), 0); 479fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (l == -1 && errno != 0) 489fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 499fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata *lp = (uint32_t)l; 509fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return 0; 519fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata} 529fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 539fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataint 54f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataarm_set_register(struct process *proc, enum arm_register reg, uint32_t lp) 55f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata{ 56f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return ptrace(PTRACE_PEEKUSER, proc->pid, 57f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata (void *)(reg * 4L), (void *)lp); 58f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata} 59f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata 60f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataint 619fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataarm_get_register_offpc(struct process *proc, enum arm_register reg, 629fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t *lp) 639fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata{ 649fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_register(proc, reg, lp) < 0) 659fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 669fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (reg == ARM_REG_PC) 679fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata *lp += 8; 689fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return 0; 699fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata} 709fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 719fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataint 729fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machataarm_get_shifted_register(struct process *proc, uint32_t inst, int carry, 739fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata arch_addr_t pc_val, uint32_t *lp) 749fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata{ 759fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata enum arm_register rm = BITS(inst, 0, 3); 769fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata unsigned long shifttype = BITS(inst, 5, 6); 779fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 789fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t shift; 799fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (BIT(inst, 4)) { 809fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (arm_get_register_offpc(proc, BITS(inst, 8, 11), &shift) < 0) 819fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 829fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata shift &= 0xff; 839fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } else { 849fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata shift = BITS(inst, 7, 11); 859fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 869fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 879fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t res; 889fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (rm == ARM_REG_PC) 899fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* xxx double cast */ 909fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = (uintptr_t)pc_val + (BIT(inst, 4) ? 12 : 8); 919fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata else if (arm_get_register(proc, rm, &res) < 0) 929fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return -1; 939fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 949fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata switch (shifttype) { 959fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 0: /* LSL */ 969fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = shift >= 32 ? 0 : res << shift; 979fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 989fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 999fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 1: /* LSR */ 1009fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = shift >= 32 ? 0 : res >> shift; 1019fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1029fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1039fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 2: /* ASR */ 1049fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (shift >= 32) 1059fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata shift = 31; 1069fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = ((res & 0x80000000L) 1079fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata ? ~((~res) >> shift) : res >> shift); 1089fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1099fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1109fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata case 3: /* ROR/RRX */ 1119fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata shift &= 31; 1129fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata if (shift == 0) 1139fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = (res >> 1) | (carry ? 0x80000000L : 0); 1149fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata else 1159fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata res = (res >> shift) | (res << (32 - shift)); 1169fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata break; 1179fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata } 1189fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 1199fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata *lp = res & 0xffffffff; 1209fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return 0; 1219fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata} 1229fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata 123f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machatastatic arch_addr_t 124f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataget_register_nocheck(struct process *proc, enum arm_register r) 125929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 1269fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata uint32_t reg; 127f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata if (arm_get_register(proc, r, ®) < 0) 1289fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX double cast. */ 1299fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return (arch_addr_t)-1; 1309fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata /* XXX double cast. */ 1319fa2b1850e664aa70a9559e41befca1a5975f08cPetr Machata return (arch_addr_t)(uintptr_t)reg; 1328e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes} 1338e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 134f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataarch_addr_t 135f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataget_instruction_pointer(struct process *proc) 136f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata{ 137f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return get_register_nocheck(proc, ARM_REG_PC); 138f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata} 139f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata 140f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid 141f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machataset_instruction_pointer(struct process *proc, arch_addr_t addr) 142929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 143f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata /* XXX double cast. */ 144f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata arm_set_register(proc, ARM_REG_PC, (uint32_t)addr); 1458f8282f72eaeadc5419cd5470100e8dcaba5b7fdJuan Cespedes} 1468f8282f72eaeadc5419cd5470100e8dcaba5b7fdJuan Cespedes 147f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid * 148929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_stack_pointer(struct process *proc) 149929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 150f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return get_register_nocheck(proc, ARM_REG_SP); 1518e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes} 1528e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes 153f9d93c50bd246ea7fd42e0c8ad24aa01467e76acPetr Machataarch_addr_t 154f9d93c50bd246ea7fd42e0c8ad24aa01467e76acPetr Machataget_return_addr(struct process *proc, arch_addr_t stack_pointer) 155929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 156f25af517a06521f69fbc53eaf3c245a7a2298c75Petr Machata return get_register_nocheck(proc, ARM_REG_LR); 1578e3e082c27716245619721207cd5067d8c6271f9Juan Cespedes} 158