regs.c revision 912a0f75b3521803fa724a55f0e883c134c7b4e9
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 27#include "backend.h" 28#include "proc.h" 29 30#define PC_OFF (32 * 4) 31 32int 33aarch64_read_gregs(struct process *proc, struct user_pt_regs *regs) 34{ 35 *regs = (struct user_pt_regs) {}; 36 struct iovec iovec; 37 iovec.iov_base = regs; 38 iovec.iov_len = sizeof *regs; 39 return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 40 ? -1 : 0; 41} 42 43int 44aarch64_write_gregs(struct process *proc, struct user_pt_regs *regs) 45{ 46 struct iovec iovec; 47 iovec.iov_base = regs; 48 iovec.iov_len = sizeof *regs; 49 return ptrace(PTRACE_SETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 50 ? -1 : 0; 51} 52 53int 54aarch64_read_fregs(struct process *proc, struct user_fpsimd_state *regs) 55{ 56 *regs = (struct user_fpsimd_state) {}; 57 struct iovec iovec; 58 iovec.iov_base = regs; 59 iovec.iov_len = sizeof *regs; 60 return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0 61 ? -1 : 0; 62} 63 64arch_addr_t 65get_instruction_pointer(struct process *proc) 66{ 67 struct user_pt_regs regs; 68 if (aarch64_read_gregs(proc, ®s) < 0) { 69 fprintf(stderr, "get_instruction_pointer: " 70 "Couldn't read registers of %d.\n", proc->pid); 71 return 0; 72 } 73 74 /* 75 char buf[128]; 76 sprintf(buf, "cat /proc/%d/maps", proc->pid); 77 system(buf); 78 */ 79 80 /* XXX double cast */ 81 return (arch_addr_t) (uintptr_t) regs.pc; 82} 83 84void 85set_instruction_pointer(struct process *proc, arch_addr_t addr) 86{ 87 struct user_pt_regs regs; 88 if (aarch64_read_gregs(proc, ®s) < 0) { 89 fprintf(stderr, "get_instruction_pointer: " 90 "Couldn't read registers of %d.\n", proc->pid); 91 return; 92 } 93 94 /* XXX double cast */ 95 regs.pc = (uint64_t) (uintptr_t) addr; 96 97 if (aarch64_write_gregs(proc, ®s) < 0) { 98 fprintf(stderr, "get_instruction_pointer: " 99 "Couldn't write registers of %d.\n", proc->pid); 100 return; 101 } 102} 103 104arch_addr_t 105get_stack_pointer(struct process *proc) 106{ 107 struct user_pt_regs regs; 108 if (aarch64_read_gregs(proc, ®s) < 0) { 109 fprintf(stderr, "get_stack_pointer: " 110 "Couldn't read registers of %d.\n", proc->pid); 111 return 0; 112 } 113 114 /* XXX double cast */ 115 return (arch_addr_t) (uintptr_t) regs.sp; 116} 117 118arch_addr_t 119get_return_addr(struct process *proc, arch_addr_t stack_pointer) 120{ 121 struct user_pt_regs regs; 122 if (aarch64_read_gregs(proc, ®s) < 0) { 123 fprintf(stderr, "get_return_addr: " 124 "Couldn't read registers of %d.\n", proc->pid); 125 return 0; 126 } 127 128 /* XXX double cast */ 129 return (arch_addr_t) (uintptr_t) regs.regs[30]; 130} 131