~ubuntu-branches/ubuntu/natty/libunwind/natty

« back to all changes in this revision

Viewing changes to src/ptrace/_UPT_access_reg.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Delahaye
  • Date: 2004-05-28 14:21:39 UTC
  • Revision ID: james.westby@ubuntu.com-20040528142139-jv1eckpdf4t94f3o
Tags: upstream-0.97
ImportĀ upstreamĀ versionĀ 0.97

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libunwind - a platform-independent unwind library
 
2
   Copyright (C) 2003-2004 Hewlett-Packard Co
 
3
        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
4
 
 
5
This file is part of libunwind.
 
6
 
 
7
Permission is hereby granted, free of charge, to any person obtaining
 
8
a copy of this software and associated documentation files (the
 
9
"Software"), to deal in the Software without restriction, including
 
10
without limitation the rights to use, copy, modify, merge, publish,
 
11
distribute, sublicense, and/or sell copies of the Software, and to
 
12
permit persons to whom the Software is furnished to do so, subject to
 
13
the following conditions:
 
14
 
 
15
The above copyright notice and this permission notice shall be
 
16
included in all copies or substantial portions of the Software.
 
17
 
 
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
19
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
21
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
22
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
23
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
24
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
25
 
 
26
#include "_UPT_internal.h"
 
27
 
 
28
#if UNW_TARGET_IA64
 
29
# include <elf.h>
 
30
# ifdef HAVE_ASM_PTRACE_OFFSETS_H
 
31
#   include <asm/ptrace_offsets.h>
 
32
# endif
 
33
# include "ia64/rse.h"
 
34
#endif
 
35
 
 
36
int
 
37
_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
 
38
                 int write, void *arg)
 
39
{
 
40
  struct UPT_info *ui = arg;
 
41
  pid_t pid = ui->pid;
 
42
 
 
43
#if UNW_DEBUG
 
44
  if (write)
 
45
    Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val);
 
46
#endif
 
47
 
 
48
#if UNW_TARGET_IA64
 
49
  if ((unsigned) reg - UNW_IA64_NAT < 32)
 
50
    {
 
51
      unsigned long nat_bits, mask;
 
52
 
 
53
      /* The Linux ptrace represents the statc NaT bits as a single word.  */
 
54
      mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT);
 
55
      errno = 0;
 
56
#ifdef HAVE_TTRACE
 
57
#       warning No support for ttrace() yet.
 
58
#else
 
59
      nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0);
 
60
      if (errno)
 
61
        goto badreg;
 
62
#endif
 
63
 
 
64
      if (write)
 
65
        {
 
66
          if (*val)
 
67
            nat_bits |= mask;
 
68
          else
 
69
            nat_bits &= ~mask;
 
70
#ifdef HAVE_TTRACE
 
71
#       warning No support for ttrace() yet.
 
72
#else
 
73
          errno = 0;
 
74
          ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits);
 
75
          if (errno)
 
76
            goto badreg;
 
77
#endif
 
78
        }
 
79
      goto out;
 
80
    }
 
81
  else
 
82
    switch (reg)
 
83
      {
 
84
      case UNW_IA64_GR + 0:
 
85
        if (write)
 
86
          goto badreg;
 
87
        *val = 0;
 
88
        return 0;
 
89
 
 
90
      case UNW_REG_IP:
 
91
        {
 
92
          unsigned long ip, psr;
 
93
 
 
94
          /* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR.  */
 
95
#ifdef HAVE_TTRACE
 
96
#       warning No support for ttrace() yet.
 
97
#else
 
98
          errno = 0;
 
99
          psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0);
 
100
          if (errno)
 
101
            goto badreg;
 
102
#endif
 
103
          if (write)
 
104
            {
 
105
              ip = *val & ~0xfUL;
 
106
              psr = (psr & ~0x3UL << 41) | (*val & 0x3);
 
107
#ifdef HAVE_TTRACE
 
108
#       warning No support for ttrace() yet.
 
109
#else
 
110
              errno = 0;
 
111
              ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip);
 
112
              ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr);
 
113
              if (errno)
 
114
                goto badreg;
 
115
#endif
 
116
            }
 
117
          else
 
118
            {
 
119
#ifdef HAVE_TTRACE
 
120
#       warning No support for ttrace() yet.
 
121
#else
 
122
              errno = 0;
 
123
              ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0);
 
124
              if (errno)
 
125
                goto badreg;
 
126
#endif
 
127
              *val = ip + ((psr >> 41) & 0x3);
 
128
            }
 
129
          goto out;
 
130
        }
 
131
 
 
132
      case UNW_IA64_AR_BSPSTORE:
 
133
        reg = UNW_IA64_AR_BSP;
 
134
        break;
 
135
 
 
136
      case UNW_IA64_AR_BSP:
 
137
      case UNW_IA64_BSP:
 
138
        {
 
139
          unsigned long sof, cfm, bsp;
 
140
 
 
141
#ifdef HAVE_TTRACE
 
142
#       warning No support for ttrace() yet.
 
143
#else
 
144
          /* Account for the fact that ptrace() expects bsp to point
 
145
             _after_ the current register frame.  */
 
146
          errno = 0;
 
147
          cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
 
148
          if (errno)
 
149
            goto badreg;
 
150
#endif
 
151
          sof = (cfm & 0x7f);
 
152
 
 
153
          if (write)
 
154
            {
 
155
              bsp = ia64_rse_skip_regs (*val, sof);
 
156
#ifdef HAVE_TTRACE
 
157
#       warning No support for ttrace() yet.
 
158
#else
 
159
              errno = 0;
 
160
              ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp);
 
161
              if (errno)
 
162
                goto badreg;
 
163
#endif
 
164
            }
 
165
          else
 
166
            {
 
167
#ifdef HAVE_TTRACE
 
168
#       warning No support for ttrace() yet.
 
169
#else
 
170
              errno = 0;
 
171
              bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
 
172
              if (errno)
 
173
                goto badreg;
 
174
#endif
 
175
              *val = ia64_rse_skip_regs (bsp, -sof);
 
176
            }
 
177
          goto out;
 
178
        }
 
179
 
 
180
      case UNW_IA64_CFM:
 
181
        /* If we change CFM, we need to adjust ptrace's notion of bsp
 
182
           accordingly, so that the real bsp remains unchanged.  */
 
183
        if (write)
 
184
          {
 
185
            unsigned long new_sof, old_sof, cfm, bsp;
 
186
 
 
187
#ifdef HAVE_TTRACE
 
188
#       warning No support for ttrace() yet.
 
189
#else
 
190
            errno = 0;
 
191
            bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
 
192
            cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
 
193
#endif
 
194
            if (errno)
 
195
              goto badreg;
 
196
            old_sof = (cfm & 0x7f);
 
197
            new_sof = (*val & 0x7f);
 
198
            if (old_sof != new_sof)
 
199
              {
 
200
                bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof);
 
201
#ifdef HAVE_TTRACE
 
202
#       warning No support for ttrace() yet.
 
203
#else
 
204
                errno = 0;
 
205
                ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0);
 
206
                if (errno)
 
207
                  goto badreg;
 
208
#endif
 
209
              }
 
210
#ifdef HAVE_TTRACE
 
211
#       warning No support for ttrace() yet.
 
212
#else
 
213
            errno = 0;
 
214
            ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val);
 
215
            if (errno)
 
216
              goto badreg;
 
217
#endif
 
218
            goto out;
 
219
          }
 
220
        break;
 
221
      }
 
222
#endif
 
223
 
 
224
  if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0]))
 
225
    goto badreg;
 
226
 
 
227
#ifdef HAVE_TTRACE
 
228
#       warning No support for ttrace() yet.
 
229
#else
 
230
  errno = 0;
 
231
  if (write)
 
232
    ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val);
 
233
  else
 
234
    *val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0);
 
235
  if (errno)
 
236
    goto badreg;
 
237
#endif
 
238
 
 
239
#ifdef UNW_TARGET_IA64
 
240
 out:
 
241
#endif
 
242
#if UNW_DEBUG
 
243
  if (!write)
 
244
    Debug (16, "%s -> %lx\n", unw_regname (reg), (long) *val);
 
245
#endif
 
246
  return 0;
 
247
 
 
248
 badreg:
 
249
  Debug (1, "bad register number %u\n", reg);
 
250
  return -UNW_EBADREG;
 
251
}