OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [alpha-linux-tdep.c] - Blame information for rev 842

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Target-dependent code for GNU/Linux on Alpha.
2
   Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "frame.h"
22
#include "gdb_assert.h"
23
#include "gdb_string.h"
24
#include "osabi.h"
25
#include "solib-svr4.h"
26
#include "symtab.h"
27
#include "regset.h"
28
#include "regcache.h"
29
 
30
#include "alpha-tdep.h"
31
 
32
/* Under GNU/Linux, signal handler invocations can be identified by
33
   the designated code sequence that is used to return from a signal
34
   handler.  In particular, the return address of a signal handler
35
   points to a sequence that copies $sp to $16, loads $0 with the
36
   appropriate syscall number, and finally enters the kernel.
37
 
38
   This is somewhat complicated in that:
39
     (1) the expansion of the "mov" assembler macro has changed over
40
         time, from "bis src,src,dst" to "bis zero,src,dst",
41
     (2) the kernel has changed from using "addq" to "lda" to load the
42
         syscall number,
43
     (3) there is a "normal" sigreturn and an "rt" sigreturn which
44
         has a different stack layout.
45
*/
46
 
47
static long
48
alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc)
49
{
50
  switch (alpha_read_insn (gdbarch, pc))
51
    {
52
    case 0x47de0410:            /* bis $30,$30,$16 */
53
    case 0x47fe0410:            /* bis $31,$30,$16 */
54
      return 0;
55
 
56
    case 0x43ecf400:            /* addq $31,103,$0 */
57
    case 0x201f0067:            /* lda $0,103($31) */
58
    case 0x201f015f:            /* lda $0,351($31) */
59
      return 4;
60
 
61
    case 0x00000083:            /* call_pal callsys */
62
      return 8;
63
 
64
    default:
65
      return -1;
66
    }
67
}
68
 
69
static LONGEST
70
alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
71
{
72
  long i, off;
73
 
74
  if (pc & 3)
75
    return -1;
76
 
77
  /* Guess where we might be in the sequence.  */
78
  off = alpha_linux_sigtramp_offset_1 (gdbarch, pc);
79
  if (off < 0)
80
    return -1;
81
 
82
  /* Verify that the other two insns of the sequence are as we expect.  */
83
  pc -= off;
84
  for (i = 0; i < 12; i += 4)
85
    {
86
      if (i == off)
87
        continue;
88
      if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i)
89
        return -1;
90
    }
91
 
92
  return off;
93
}
94
 
95
static int
96
alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch,
97
                            CORE_ADDR pc, char *func_name)
98
{
99
  return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0;
100
}
101
 
102
static CORE_ADDR
103
alpha_linux_sigcontext_addr (struct frame_info *this_frame)
104
{
105
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
106
  CORE_ADDR pc;
107
  ULONGEST sp;
108
  long off;
109
 
110
  pc = get_frame_pc (this_frame);
111
  sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM);
112
 
113
  off = alpha_linux_sigtramp_offset (gdbarch, pc);
114
  gdb_assert (off >= 0);
115
 
116
  /* __NR_rt_sigreturn has a couple of structures on the stack.  This is:
117
 
118
        struct rt_sigframe {
119
          struct siginfo info;
120
          struct ucontext uc;
121
        };
122
 
123
        offsetof (struct rt_sigframe, uc.uc_mcontext);
124
  */
125
  if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f)
126
    return sp + 176;
127
 
128
  /* __NR_sigreturn has the sigcontext structure at the top of the stack.  */
129
  return sp;
130
}
131
 
132
/* Supply register REGNUM from the buffer specified by GREGS and LEN
133
   in the general-purpose register set REGSET to register cache
134
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
135
 
136
static void
137
alpha_linux_supply_gregset (const struct regset *regset,
138
                            struct regcache *regcache,
139
                            int regnum, const void *gregs, size_t len)
140
{
141
  const gdb_byte *regs = gregs;
142
  int i;
143
  gdb_assert (len >= 32 * 8);
144
 
145
  for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
146
    {
147
      if (regnum == i || regnum == -1)
148
        regcache_raw_supply (regcache, i, regs + i * 8);
149
    }
150
 
151
  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
152
    regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
153
 
154
  if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
155
    regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
156
                         len >= 33 * 8 ? regs + 32 * 8 : NULL);
157
}
158
 
159
/* Supply register REGNUM from the buffer specified by FPREGS and LEN
160
   in the floating-point register set REGSET to register cache
161
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
162
 
163
static void
164
alpha_linux_supply_fpregset (const struct regset *regset,
165
                             struct regcache *regcache,
166
                             int regnum, const void *fpregs, size_t len)
167
{
168
  const gdb_byte *regs = fpregs;
169
  int i;
170
  gdb_assert (len >= 32 * 8);
171
 
172
  for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
173
    {
174
      if (regnum == i || regnum == -1)
175
        regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
176
    }
177
 
178
  if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
179
    regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
180
}
181
 
182
static struct regset alpha_linux_gregset =
183
{
184
  NULL,
185
  alpha_linux_supply_gregset
186
};
187
 
188
static struct regset alpha_linux_fpregset =
189
{
190
  NULL,
191
  alpha_linux_supply_fpregset
192
};
193
 
194
/* Return the appropriate register set for the core section identified
195
   by SECT_NAME and SECT_SIZE.  */
196
 
197
static const struct regset *
198
alpha_linux_regset_from_core_section (struct gdbarch *gdbarch,
199
                                      const char *sect_name, size_t sect_size)
200
{
201
  if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8)
202
    return &alpha_linux_gregset;
203
 
204
  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8)
205
    return &alpha_linux_fpregset;
206
 
207
  return NULL;
208
}
209
 
210
static void
211
alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
212
{
213
  struct gdbarch_tdep *tdep;
214
 
215
  /* Hook into the DWARF CFI frame unwinder.  */
216
  alpha_dwarf2_init_abi (info, gdbarch);
217
 
218
  /* Hook into the MDEBUG frame unwinder.  */
219
  alpha_mdebug_init_abi (info, gdbarch);
220
 
221
  tdep = gdbarch_tdep (gdbarch);
222
  tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset;
223
  tdep->sigcontext_addr = alpha_linux_sigcontext_addr;
224
  tdep->pc_in_sigtramp = alpha_linux_pc_in_sigtramp;
225
  tdep->jb_pc = 2;
226
  tdep->jb_elt_size = 8;
227
 
228
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
229
 
230
  set_solib_svr4_fetch_link_map_offsets
231
    (gdbarch, svr4_lp64_fetch_link_map_offsets);
232
 
233
  /* Enable TLS support.  */
234
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
235
                                             svr4_fetch_objfile_link_map);
236
 
237
  set_gdbarch_regset_from_core_section
238
    (gdbarch, alpha_linux_regset_from_core_section);
239
}
240
 
241
/* Provide a prototype to silence -Wmissing-prototypes.  */
242
extern initialize_file_ftype _initialize_alpha_linux_tdep;
243
 
244
void
245
_initialize_alpha_linux_tdep (void)
246
{
247
  gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
248
                          alpha_linux_init_abi);
249
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.