1912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata/* 2912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * This file is part of ltrace. 3912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * Copyright (C) 2014 Petr Machata, Red Hat, Inc. 4912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * 5912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * This program is free software; you can redistribute it and/or 6912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * modify it under the terms of the GNU General Public License as 7912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * published by the Free Software Foundation; either version 2 of the 8912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * License, or (at your option) any later version. 9912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * 10912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * This program is distributed in the hope that it will be useful, but 11912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 12912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * General Public License for more details. 14912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * 15912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * You should have received a copy of the GNU General Public License 16912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * along with this program; if not, write to the Free Software 17912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * 02110-1301 USA 19912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata */ 20912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 21912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <sys/ptrace.h> 22912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <asm/ptrace.h> 23912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <linux/uio.h> 24912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <assert.h> 25912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <stdlib.h> 266bacfc7b34be8414d01c201f1c6086e3edaa8b62dann frazier#include <stdio.h> 27912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 28912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include "backend.h" 29912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include "proc.h" 30912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 31912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#define PC_OFF (32 * 4) 32912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 33912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataint 34912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataaarch64_read_gregs(struct process *proc, struct user_pt_regs *regs) 35912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 36912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata *regs = (struct user_pt_regs) {}; 37912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct iovec iovec; 38912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_base = regs; 39912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_len = sizeof *regs; 40912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 41912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata ? -1 : 0; 42912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 43912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 44912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataint 45912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataaarch64_write_gregs(struct process *proc, struct user_pt_regs *regs) 46912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 47912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct iovec iovec; 48912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_base = regs; 49912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_len = sizeof *regs; 50912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return ptrace(PTRACE_SETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 51912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata ? -1 : 0; 52912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 53912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 54912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataint 55912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataaarch64_read_fregs(struct process *proc, struct user_fpsimd_state *regs) 56912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 57912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata *regs = (struct user_fpsimd_state) {}; 58912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct iovec iovec; 59912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_base = regs; 60912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata iovec.iov_len = sizeof *regs; 61912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0 62912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata ? -1 : 0; 63912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 64912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 65912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataarch_addr_t 66912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataget_instruction_pointer(struct process *proc) 67912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 68912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct user_pt_regs regs; 69912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata if (aarch64_read_gregs(proc, ®s) < 0) { 70912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata fprintf(stderr, "get_instruction_pointer: " 71912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata "Couldn't read registers of %d.\n", proc->pid); 72912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return 0; 73912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata } 74912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 75912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata /* 76912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata char buf[128]; 77912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata sprintf(buf, "cat /proc/%d/maps", proc->pid); 78912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata system(buf); 79912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata */ 80912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 81912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata /* XXX double cast */ 82912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return (arch_addr_t) (uintptr_t) regs.pc; 83912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 84912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 85912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machatavoid 86912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataset_instruction_pointer(struct process *proc, arch_addr_t addr) 87912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 88912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct user_pt_regs regs; 89912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata if (aarch64_read_gregs(proc, ®s) < 0) { 90912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata fprintf(stderr, "get_instruction_pointer: " 91912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata "Couldn't read registers of %d.\n", proc->pid); 92912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return; 93912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata } 94912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 95912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata /* XXX double cast */ 96912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata regs.pc = (uint64_t) (uintptr_t) addr; 97912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 98912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata if (aarch64_write_gregs(proc, ®s) < 0) { 99912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata fprintf(stderr, "get_instruction_pointer: " 100912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata "Couldn't write registers of %d.\n", proc->pid); 101912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return; 102912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata } 103912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 104912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 105912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataarch_addr_t 106912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataget_stack_pointer(struct process *proc) 107912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 108912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct user_pt_regs regs; 109912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata if (aarch64_read_gregs(proc, ®s) < 0) { 110912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata fprintf(stderr, "get_stack_pointer: " 111912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata "Couldn't read registers of %d.\n", proc->pid); 112912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return 0; 113912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata } 114912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 115912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata /* XXX double cast */ 116912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return (arch_addr_t) (uintptr_t) regs.sp; 117912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 118912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 119912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataarch_addr_t 120912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataget_return_addr(struct process *proc, arch_addr_t stack_pointer) 121912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{ 122912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata struct user_pt_regs regs; 123912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata if (aarch64_read_gregs(proc, ®s) < 0) { 124912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata fprintf(stderr, "get_return_addr: " 125912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata "Couldn't read registers of %d.\n", proc->pid); 126912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return 0; 127912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata } 128912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata 129912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata /* XXX double cast */ 130912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata return (arch_addr_t) (uintptr_t) regs.regs[30]; 131912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata} 132