Coverage Report

Created: 2025-08-29 06:11

/src/elfutils/backends/aarch64_initreg.c
Line
Count
Source (jump to first uncovered line)
1
/* Fetch live process registers from TID.
2
   Copyright (C) 2013, 2014 Red Hat, Inc.
3
   This file is part of elfutils.
4
5
   This file is free software; you can redistribute it and/or modify
6
   it under the terms of either
7
8
     * the GNU Lesser General Public License as published by the Free
9
       Software Foundation; either version 3 of the License, or (at
10
       your option) any later version
11
12
   or
13
14
     * the GNU General Public License as published by the Free
15
       Software Foundation; either version 2 of the License, or (at
16
       your option) any later version
17
18
   or both in parallel, as here.
19
20
   elfutils is distributed in the hope that it will be useful, but
21
   WITHOUT ANY WARRANTY; without even the implied warranty of
22
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23
   General Public License for more details.
24
25
   You should have received copies of the GNU General Public License and
26
   the GNU Lesser General Public License along with this program.  If
27
   not, see <http://www.gnu.org/licenses/>.  */
28
29
#ifdef HAVE_CONFIG_H
30
# include <config.h>
31
#endif
32
33
#include "system.h"
34
#include <assert.h>
35
#if defined(__aarch64__) && defined(__linux__)
36
# include <linux/uio.h>
37
# include <sys/user.h>
38
# include <sys/ptrace.h>
39
# include <asm/ptrace.h>
40
/* Deal with old glibc defining user_pt_regs instead of user_regs_struct.  */
41
# ifndef HAVE_SYS_USER_REGS
42
#  define user_regs_struct user_pt_regs
43
#  define user_fpsimd_struct user_fpsimd_state
44
# endif
45
#endif
46
47
#define BACKEND aarch64_
48
#include "libebl_CPU.h"
49
50
/*
51
 * pointer authentication masks (NT_ARM_PAC_MASK)
52
 *
53
 * Defined by Linux kernel headers since Linux 5.0. Define it here if kernel
54
 * headers are older than that, to ensure this file builds regardless.
55
 */
56
#if defined(__aarch64__) && defined(__linux__)
57
58
#ifndef NT_ARM_PAC_MASK
59
#define NT_ARM_PAC_MASK 0x406
60
#endif
61
62
#ifndef HAVE_USER_PACK_MASK
63
struct user_pac_mask {
64
  __u64 data_mask;
65
  __u64 insn_mask;
66
};
67
#endif
68
69
#endif /* __aarch64__ && __linux__ */
70
71
bool
72
aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
73
        ebl_tid_registers_t *setfunc __attribute__ ((unused)),
74
        void *arg __attribute__ ((unused)))
75
0
{
76
0
#if !defined(__aarch64__) || !defined(__linux__)
77
0
  return false;
78
#else /* __aarch64__ */
79
80
  /* General registers.  */
81
  struct user_regs_struct gregs;
82
  struct user_pac_mask pac_mask;
83
  struct iovec iovec;
84
  iovec.iov_base = &gregs;
85
  iovec.iov_len = sizeof (gregs);
86
  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
87
    return false;
88
89
  iovec.iov_base = &pac_mask;
90
  iovec.iov_len = sizeof (pac_mask);
91
  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_PAC_MASK, &iovec) != 0)
92
    pac_mask.insn_mask = 0;
93
94
  /* X0..X30 plus SP.  */
95
  if (! setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg))
96
    return false;
97
98
  /* PC.  */
99
  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg))
100
    return false;
101
102
  if (! setfunc (-2, 1, (Dwarf_Word *) &pac_mask.insn_mask, arg))
103
    return false;
104
105
  /* ELR cannot be found.  */
106
107
  /* RA_SIGN_STATE cannot be found */
108
109
  /* FP registers (only 64bits are used).  */
110
  struct user_fpsimd_struct fregs;
111
  iovec.iov_base = &fregs;
112
  iovec.iov_len = sizeof (fregs);
113
  if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
114
    return false;
115
116
  Dwarf_Word dwarf_fregs[32];
117
  for (int r = 0; r < 32; r++)
118
    dwarf_fregs[r] = fregs.vregs[r] & 0xFFFFFFFF;
119
120
  if (! setfunc (64, 32, dwarf_fregs, arg))
121
    return false;
122
123
  return true;
124
#endif /* __aarch64__ */
125
0
}