Coverage Report

Created: 2025-08-24 06:28

/src/elfutils/backends/ppc_initreg.c
Line
Count
Source (jump to first uncovered line)
1
/* Fetch live process registers from TID.
2
   Copyright (C) 2013 Red Hat, Inc.
3
   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4
   This file is part of elfutils.
5
6
   This file is free software; you can redistribute it and/or modify
7
   it under the terms of either
8
9
     * the GNU Lesser General Public License as published by the Free
10
       Software Foundation; either version 3 of the License, or (at
11
       your option) any later version
12
13
   or
14
15
     * the GNU General Public License as published by the Free
16
       Software Foundation; either version 2 of the License, or (at
17
       your option) any later version
18
19
   or both in parallel, as here.
20
21
   elfutils is distributed in the hope that it will be useful, but
22
   WITHOUT ANY WARRANTY; without even the implied warranty of
23
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24
   General Public License for more details.
25
26
   You should have received copies of the GNU General Public License and
27
   the GNU Lesser General Public License along with this program.  If
28
   not, see <http://www.gnu.org/licenses/>.  */
29
30
#ifdef HAVE_CONFIG_H
31
# include <config.h>
32
#endif
33
34
#include <stdlib.h>
35
#if defined(__powerpc__) && defined(__linux__)
36
# include <sys/ptrace.h>
37
# include <asm/ptrace.h>
38
# ifndef PTRACE_GETREGSET
39
#  include <linux/ptrace.h>
40
# endif
41
# include <sys/user.h>
42
# include <sys/uio.h>
43
#endif
44
45
#include "system.h"
46
47
#define BACKEND ppc_
48
#include "libebl_CPU.h"
49
50
bool
51
ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
52
0
{
53
0
  switch (*regno)
54
0
  {
55
0
    case 108:
56
      // LR uses both 65 and 108 numbers, there is no consistency for it.
57
0
      *regno = 65;
58
0
      return true;
59
0
    case 0 ... 107:
60
0
    case 109 ... (114 - 1) -1:
61
0
      return true;
62
0
    case 1200 ... 1231:
63
0
      *regno = *regno - 1200 + (114 - 1);
64
0
      return true;
65
0
    default:
66
0
      return false;
67
0
  }
68
0
  abort ();
69
0
}
70
71
__typeof (ppc_dwarf_to_regno)
72
     ppc64_dwarf_to_regno
73
     __attribute__ ((alias ("ppc_dwarf_to_regno")));
74
75
bool
76
ppc_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
77
        ebl_tid_registers_t *setfunc __attribute__ ((unused)),
78
             void *arg __attribute__ ((unused)))
79
0
{
80
0
#if !defined(__powerpc__) || !defined(__linux__)
81
0
  return false;
82
#else /* __powerpc__ */
83
84
/* pt_regs for 32bit processes. Same as 64bit pt_regs but all registers
85
   are 32bit instead of 64bit long.  */
86
#define GPRS 32
87
  struct pt_regs32
88
  {
89
    uint32_t gpr[GPRS];
90
    uint32_t nip;
91
    uint32_t msr;
92
    uint32_t orig_gpr3;
93
    uint32_t ctr;
94
    uint32_t link;
95
    uint32_t xer;
96
    uint32_t ccr;
97
    uint32_t mq;
98
    uint32_t trap;
99
    uint32_t dar;
100
    uint32_t dsisr;
101
    uint32_t result;
102
  };
103
104
  struct pt_regs regs;
105
  struct pt_regs32 *regs32 = (struct pt_regs32 *) &regs;
106
  struct iovec iovec;
107
  iovec.iov_base = &regs;
108
  iovec.iov_len = sizeof (regs);
109
  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
110
    return false;
111
112
  /* Did we get the full pt_regs or less (the 32bit pt_regs)?  */
113
  bool get32 = iovec.iov_len < sizeof (struct pt_regs);
114
  Dwarf_Word dwarf_regs[GPRS];
115
  for (unsigned gpr = 0; gpr < GPRS; gpr++)
116
    dwarf_regs[gpr] = get32 ? regs32->gpr[gpr] : regs.gpr[gpr];
117
  if (! setfunc (0, GPRS, dwarf_regs, arg))
118
    return false;
119
  // LR uses both 65 and 108 numbers, there is no consistency for it.
120
  Dwarf_Word link = get32 ? regs32->link : regs.link;
121
  if (! setfunc (65, 1, &link, arg))
122
    return false;
123
  /* Registers like msr, ctr, xer, dar, dsisr etc. are probably irrelevant
124
     for CFI.  */
125
  Dwarf_Word pc = get32 ? (Dwarf_Word) regs32->nip : regs.nip;
126
  return setfunc (-1, 1, &pc, arg);
127
#endif /* __powerpc__ */
128
0
}
129
130
__typeof (ppc_set_initial_registers_tid)
131
     ppc64_set_initial_registers_tid
132
     __attribute__ ((alias ("ppc_set_initial_registers_tid")));