• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
ppc_dwarf_to_regno(Ebl * ebl,unsigned * regno)51 ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
52 {
53   switch (*regno)
54   {
55     case 108:
56       // LR uses both 65 and 108 numbers, there is no consistency for it.
57       *regno = 65;
58       return true;
59     case 0 ... 107:
60     case 109 ... (114 - 1) -1:
61       return true;
62     case 1200 ... 1231:
63       *regno = *regno - 1200 + (114 - 1);
64       return true;
65     default:
66       return false;
67   }
68   abort ();
69 }
70 
71 __typeof (ppc_dwarf_to_regno)
72      ppc64_dwarf_to_regno
73      __attribute__ ((alias ("ppc_dwarf_to_regno")));
74 
75 bool
ppc_set_initial_registers_tid(pid_t tid,ebl_tid_registers_t * setfunc,void * arg)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 {
80 #if !defined(__powerpc__) || !defined(__linux__)
81   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 }
129 
130 __typeof (ppc_set_initial_registers_tid)
131      ppc64_set_initial_registers_tid
132      __attribute__ ((alias ("ppc_set_initial_registers_tid")));
133