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 <sys/types.h>
23 #include <sys/wait.h>
24 #include <asm/ptrace.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <errno.h>
28
29 #include "backend.h"
30 #include "proc.h"
31
32 void
get_arch_dep(struct process * proc)33 get_arch_dep(struct process *proc)
34 {
35 }
36
37 int aarch64_read_gregs(struct process *proc, struct user_pt_regs *regs);
38
39 /* The syscall instruction is:
40 * | 31 21 | 20 5 | 4 0 |
41 * | 1 1 0 1 0 1 0 0 | 0 0 0 | imm16 | 0 0 0 0 1 | */
42 #define SVC_MASK 0xffe0001f
43 #define SVC_VALUE 0xd4000001
44
45 int
syscall_p(struct process * proc,int status,int * sysnum)46 syscall_p(struct process *proc, int status, int *sysnum)
47 {
48 if (WIFSTOPPED(status)
49 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
50
51 struct user_pt_regs regs;
52 if (aarch64_read_gregs(proc, ®s) < 0) {
53 fprintf(stderr, "syscall_p: "
54 "Couldn't read registers of %d.\n", proc->pid);
55 return -1;
56 }
57
58 errno = 0;
59 unsigned long insn = (unsigned long) ptrace(PTRACE_PEEKTEXT,
60 proc->pid,
61 regs.pc - 4, 0);
62 if (insn == -1UL && errno != 0) {
63 fprintf(stderr, "syscall_p: "
64 "Couldn't peek into %d: %s\n", proc->pid,
65 strerror(errno));
66 return -1;
67 }
68
69 insn &= 0xffffffffUL;
70 if ((insn & SVC_MASK) == SVC_VALUE) {
71 *sysnum = regs.regs[8];
72
73 size_t d1 = proc->callstack_depth - 1;
74 if (proc->callstack_depth > 0
75 && proc->callstack[d1].is_syscall
76 && proc->callstack[d1].c_un.syscall == *sysnum)
77 return 2;
78
79 return 1;
80 }
81 }
82
83 return 0;
84 }
85