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 33int 34aarch64_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 44int 45aarch64_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 54int 55aarch64_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 65arch_addr_t 66get_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 85void 86set_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 105arch_addr_t 106get_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 119arch_addr_t 120get_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