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 <sys/types.h>
23912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <sys/wait.h>
24912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <asm/ptrace.h>
25912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <string.h>
266bacfc7b34be8414d01c201f1c6086e3edaa8b62dann frazier#include <stdio.h>
27912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include <errno.h>
28912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
29912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include "backend.h"
30912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#include "proc.h"
31912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
32912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machatavoid
33912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataget_arch_dep(struct process *proc)
34912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{
35912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata}
36912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
37912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataint aarch64_read_gregs(struct process *proc, struct user_pt_regs *regs);
38912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
39912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata/* The syscall instruction is:
40912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * | 31                   21 | 20    5 | 4       0 |
41912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata * | 1 1 0 1 0 1 0 0 | 0 0 0 |  imm16  | 0 0 0 0 1 | */
42912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#define SVC_MASK  0xffe0001f
43912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata#define SVC_VALUE 0xd4000001
44912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
45912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machataint
46912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machatasyscall_p(struct process *proc, int status, int *sysnum)
47912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata{
48912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata	if (WIFSTOPPED(status)
49912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
50912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
51912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		struct user_pt_regs regs;
52912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		if (aarch64_read_gregs(proc, &regs) < 0) {
53912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			fprintf(stderr, "syscall_p: "
54912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata				"Couldn't read registers of %d.\n", proc->pid);
55912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			return -1;
56912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		}
57912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
58912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		errno = 0;
59912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		unsigned long insn = (unsigned long) ptrace(PTRACE_PEEKTEXT,
60912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata							    proc->pid,
61912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata							    regs.pc - 4, 0);
62912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		if (insn == -1UL && errno != 0) {
63912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			fprintf(stderr, "syscall_p: "
64912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata				"Couldn't peek into %d: %s\n", proc->pid,
65912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata				strerror(errno));
66912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			return -1;
67912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		}
68912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
69912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		insn &= 0xffffffffUL;
70912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		if ((insn & SVC_MASK) == SVC_VALUE) {
71912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			*sysnum = regs.regs[8];
72912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
73912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			size_t d1 = proc->callstack_depth - 1;
74912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			if (proc->callstack_depth > 0
75912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			    && proc->callstack[d1].is_syscall
76912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			    && proc->callstack[d1].c_un.syscall == *sysnum)
77912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata				return 2;
78912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
79912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata			return 1;
80912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata		}
81912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata	}
82912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata
83912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata	return 0;
84912a0f75b3521803fa724a55f0e883c134c7b4e9Petr Machata}
85