1 /* 2 * This file is part of ltrace. 3 * Copyright (C) 2014 Petr Machata, Red Hat, Inc. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 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 <sys/ptrace.h> 22 #include <asm/ptrace.h> 23 #include <linux/uio.h> 24 #include <assert.h> 25 #include <stdlib.h> 26 #include <stdio.h> 27 28 #include "backend.h" 29 #include "proc.h" 30 31 #define PC_OFF (32 * 4) 32 33 int 34 aarch64_read_gregs(struct process *proc, struct user_pt_regs *regs) 35 { 36 *regs = (struct user_pt_regs) {}; 37 struct iovec iovec; 38 iovec.iov_base = regs; 39 iovec.iov_len = sizeof *regs; 40 return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 41 ? -1 : 0; 42 } 43 44 int 45 aarch64_write_gregs(struct process *proc, struct user_pt_regs *regs) 46 { 47 struct iovec iovec; 48 iovec.iov_base = regs; 49 iovec.iov_len = sizeof *regs; 50 return ptrace(PTRACE_SETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 51 ? -1 : 0; 52 } 53 54 int 55 aarch64_read_fregs(struct process *proc, struct user_fpsimd_state *regs) 56 { 57 *regs = (struct user_fpsimd_state) {}; 58 struct iovec iovec; 59 iovec.iov_base = regs; 60 iovec.iov_len = sizeof *regs; 61 return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0 62 ? -1 : 0; 63 } 64 65 arch_addr_t 66 get_instruction_pointer(struct process *proc) 67 { 68 struct user_pt_regs regs; 69 if (aarch64_read_gregs(proc, ®s) < 0) { 70 fprintf(stderr, "get_instruction_pointer: " 71 "Couldn't read registers of %d.\n", proc->pid); 72 return 0; 73 } 74 75 /* 76 char buf[128]; 77 sprintf(buf, "cat /proc/%d/maps", proc->pid); 78 system(buf); 79 */ 80 81 /* XXX double cast */ 82 return (arch_addr_t) (uintptr_t) regs.pc; 83 } 84 85 void 86 set_instruction_pointer(struct process *proc, arch_addr_t addr) 87 { 88 struct user_pt_regs regs; 89 if (aarch64_read_gregs(proc, ®s) < 0) { 90 fprintf(stderr, "get_instruction_pointer: " 91 "Couldn't read registers of %d.\n", proc->pid); 92 return; 93 } 94 95 /* XXX double cast */ 96 regs.pc = (uint64_t) (uintptr_t) addr; 97 98 if (aarch64_write_gregs(proc, ®s) < 0) { 99 fprintf(stderr, "get_instruction_pointer: " 100 "Couldn't write registers of %d.\n", proc->pid); 101 return; 102 } 103 } 104 105 arch_addr_t 106 get_stack_pointer(struct process *proc) 107 { 108 struct user_pt_regs regs; 109 if (aarch64_read_gregs(proc, ®s) < 0) { 110 fprintf(stderr, "get_stack_pointer: " 111 "Couldn't read registers of %d.\n", proc->pid); 112 return 0; 113 } 114 115 /* XXX double cast */ 116 return (arch_addr_t) (uintptr_t) regs.sp; 117 } 118 119 arch_addr_t 120 get_return_addr(struct process *proc, arch_addr_t stack_pointer) 121 { 122 struct user_pt_regs regs; 123 if (aarch64_read_gregs(proc, ®s) < 0) { 124 fprintf(stderr, "get_return_addr: " 125 "Couldn't read registers of %d.\n", proc->pid); 126 return 0; 127 } 128 129 /* XXX double cast */ 130 return (arch_addr_t) (uintptr_t) regs.regs[30]; 131 } 132