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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [sparcobsd-tdep.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* Target-dependent code for OpenBSD/sparc.
2
 
3
   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "defs.h"
22
#include "floatformat.h"
23
#include "frame.h"
24
#include "frame-unwind.h"
25
#include "gdbcore.h"
26
#include "osabi.h"
27
#include "regcache.h"
28
#include "symtab.h"
29
#include "trad-frame.h"
30
 
31
#include "gdb_assert.h"
32
 
33
#include "obsd-tdep.h"
34
#include "sparc-tdep.h"
35
#include "solib-svr4.h"
36
#include "bsd-uthread.h"
37
 
38
/* Signal trampolines.  */
39
 
40
/* The OpenBSD kernel maps the signal trampoline at some random
41
   location in user space, which means that the traditional BSD way of
42
   detecting it won't work.
43
 
44
   The signal trampoline will be mapped at an address that is page
45
   aligned.  We recognize the signal trampoline by looking for the
46
   sigreturn system call.  */
47
 
48
static const int sparc32obsd_page_size = 4096;
49
 
50
static int
51
sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
52
{
53
  CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
54
  unsigned long insn;
55
 
56
  if (name)
57
    return 0;
58
 
59
  /* Check for "restore %g0, SYS_sigreturn, %g1".  */
60
  insn = sparc_fetch_instruction (start_pc + 0xec);
61
  if (insn != 0x83e82067)
62
    return 0;
63
 
64
  /* Check for "t ST_SYSCALL".  */
65
  insn = sparc_fetch_instruction (start_pc + 0xf4);
66
  if (insn != 0x91d02000)
67
    return 0;
68
 
69
  return 1;
70
}
71
 
72
static struct sparc_frame_cache *
73
sparc32obsd_sigtramp_frame_cache (struct frame_info *this_frame,
74
                                  void **this_cache)
75
{
76
  struct sparc_frame_cache *cache;
77
  CORE_ADDR addr;
78
 
79
  if (*this_cache)
80
    return *this_cache;
81
 
82
  cache = sparc_frame_cache (this_frame, this_cache);
83
  gdb_assert (cache == *this_cache);
84
 
85
  /* If we couldn't find the frame's function, we're probably dealing
86
     with an on-stack signal trampoline.  */
87
  if (cache->pc == 0)
88
    {
89
      cache->pc = get_frame_pc (this_frame);
90
      cache->pc &= ~(sparc32obsd_page_size - 1);
91
 
92
      /* Since we couldn't find the frame's function, the cache was
93
         initialized under the assumption that we're frameless.  */
94
      cache->frameless_p = 0;
95
      addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
96
      cache->base = addr;
97
    }
98
 
99
  cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame);
100
 
101
  return cache;
102
}
103
 
104
static void
105
sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame,
106
                                    void **this_cache,
107
                                    struct frame_id *this_id)
108
{
109
  struct sparc_frame_cache *cache =
110
    sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
111
 
112
  (*this_id) = frame_id_build (cache->base, cache->pc);
113
}
114
 
115
static struct value *
116
sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
117
                                          void **this_cache, int regnum)
118
{
119
  struct sparc_frame_cache *cache =
120
    sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
121
 
122
  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
123
}
124
 
125
static int
126
sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
127
                                    struct frame_info *this_frame,
128
                                    void **this_cache)
129
{
130
  CORE_ADDR pc = get_frame_pc (this_frame);
131
  char *name;
132
 
133
  find_pc_partial_function (pc, &name, NULL, NULL);
134
  if (sparc32obsd_pc_in_sigtramp (pc, name))
135
    return 1;
136
 
137
  return 0;
138
}
139
static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
140
{
141
  SIGTRAMP_FRAME,
142
  sparc32obsd_sigtramp_frame_this_id,
143
  sparc32obsd_sigtramp_frame_prev_register,
144
  NULL,
145
  sparc32obsd_sigtramp_frame_sniffer
146
};
147
 
148
 
149
 
150
/* Offset wthin the thread structure where we can find %fp and %i7.  */
151
#define SPARC32OBSD_UTHREAD_FP_OFFSET   128
152
#define SPARC32OBSD_UTHREAD_PC_OFFSET   132
153
 
154
static void
155
sparc32obsd_supply_uthread (struct regcache *regcache,
156
                            int regnum, CORE_ADDR addr)
157
{
158
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
159
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
160
  CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
161
  gdb_byte buf[4];
162
 
163
  gdb_assert (regnum >= -1);
164
 
165
  fp = read_memory_unsigned_integer (fp_addr, 4, byte_order);
166
  if (regnum == SPARC_SP_REGNUM || regnum == -1)
167
    {
168
      store_unsigned_integer (buf, 4, byte_order, fp);
169
      regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
170
 
171
      if (regnum == SPARC_SP_REGNUM)
172
        return;
173
    }
174
 
175
  if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM
176
      || regnum == -1)
177
    {
178
      CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
179
 
180
      i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order);
181
      if (regnum == SPARC32_PC_REGNUM || regnum == -1)
182
        {
183
          store_unsigned_integer (buf, 4, byte_order, i7 + 8);
184
          regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf);
185
        }
186
      if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
187
        {
188
          store_unsigned_integer (buf, 4, byte_order, i7 + 12);
189
          regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf);
190
        }
191
 
192
      if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
193
        return;
194
    }
195
 
196
  sparc_supply_rwindow (regcache, fp, regnum);
197
}
198
 
199
static void
200
sparc32obsd_collect_uthread(const struct regcache *regcache,
201
                            int regnum, CORE_ADDR addr)
202
{
203
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
204
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
205
  CORE_ADDR sp;
206
  gdb_byte buf[4];
207
 
208
  gdb_assert (regnum >= -1);
209
 
210
  if (regnum == SPARC_SP_REGNUM || regnum == -1)
211
    {
212
      CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
213
 
214
      regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
215
      write_memory (fp_addr,buf, 4);
216
    }
217
 
218
  if (regnum == SPARC32_PC_REGNUM || regnum == -1)
219
    {
220
      CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
221
 
222
      regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf);
223
      i7 = extract_unsigned_integer (buf, 4, byte_order) - 8;
224
      write_memory_unsigned_integer (i7_addr, 4, byte_order, i7);
225
 
226
      if (regnum == SPARC32_PC_REGNUM)
227
        return;
228
    }
229
 
230
  regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
231
  sp = extract_unsigned_integer (buf, 4, byte_order);
232
  sparc_collect_rwindow (regcache, sp, regnum);
233
}
234
 
235
 
236
static void
237
sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
238
{
239
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
240
 
241
  /* OpenBSD/sparc is very similar to NetBSD/sparc ELF.  */
242
  sparc32nbsd_elf_init_abi (info, gdbarch);
243
 
244
  set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
245
 
246
  frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind);
247
 
248
  /* OpenBSD provides a user-level threads implementation.  */
249
  bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread);
250
  bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
251
}
252
 
253
 
254
/* Provide a prototype to silence -Wmissing-prototypes.  */
255
void _initialize_sparc32obsd_tdep (void);
256
 
257
void
258
_initialize_sparc32obsd_tdep (void)
259
{
260
  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
261
                          sparc32obsd_init_abi);
262
}

powered by: WebSVN 2.1.0

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