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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [sparc64obsd-tdep.c] - Blame information for rev 866

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

Line No. Rev Author Line
1 24 jeremybenn
/* Target-dependent code for OpenBSD/sparc64.
2
 
3
   Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "frame-unwind.h"
23
#include "gdbcore.h"
24
#include "osabi.h"
25
#include "regcache.h"
26
#include "regset.h"
27
#include "symtab.h"
28
#include "objfiles.h"
29
#include "trad-frame.h"
30
 
31
#include "gdb_assert.h"
32
 
33
#include "obsd-tdep.h"
34
#include "sparc64-tdep.h"
35
#include "solib-svr4.h"
36
#include "bsd-uthread.h"
37
 
38
/* OpenBSD uses the traditional NetBSD core file format, even for
39
   ports that use ELF.  The core files don't use multiple register
40
   sets.  Instead, the general-purpose and floating-point registers
41
   are lumped together in a single section.  Unlike on NetBSD, OpenBSD
42
   uses a different layout for its general-purpose registers than the
43
   layout used for ptrace(2).  */
44
 
45
/* From <machine/reg.h>.  */
46
const struct sparc_gregset sparc64obsd_core_gregset =
47
{
48
 
49
  1 * 8,                        /* %pc */
50
  2 * 8,                        /* %npc */
51
  3 * 8,                        /* %y */
52
  -1,                           /* %fprs */
53
  -1,
54
  7 * 8,                        /* %g1 */
55
  22 * 8,                       /* %l0 */
56
  4                             /* sizeof (%y) */
57
};
58
 
59
static void
60
sparc64obsd_supply_gregset (const struct regset *regset,
61
                            struct regcache *regcache,
62
                            int regnum, const void *gregs, size_t len)
63
{
64
  const char *regs = gregs;
65
 
66
  sparc64_supply_gregset (&sparc64obsd_core_gregset, regcache, regnum, regs);
67
  sparc64_supply_fpregset (regcache, regnum, regs + 288);
68
}
69
 
70
 
71
/* Signal trampolines.  */
72
 
73
/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
74
   in virtual memory.  The randomness makes it somewhat tricky to
75
   detect it, but fortunately we can rely on the fact that the start
76
   of the sigtramp routine is page-aligned.  We recognize the
77
   trampoline by looking for the code that invokes the sigreturn
78
   system call.  The offset where we can find that code varies from
79
   release to release.
80
 
81
   By the way, the mapping mentioned above is read-only, so you cannot
82
   place a breakpoint in the signal trampoline.  */
83
 
84
/* Default page size.  */
85
static const int sparc64obsd_page_size = 8192;
86
 
87
/* Offset for sigreturn(2).  */
88
static const int sparc64obsd_sigreturn_offset[] = {
89
  0xf0,                         /* OpenBSD 3.8 */
90
  0xec,                         /* OpenBSD 3.6 */
91
  0xe8,                         /* OpenBSD 3.2 */
92
  -1
93
};
94
 
95
static int
96
sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
97
{
98
  CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
99
  unsigned long insn;
100
  const int *offset;
101
 
102
  if (name)
103
    return 0;
104
 
105
  for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++)
106
    {
107
      /* Check for "restore %g0, SYS_sigreturn, %g1".  */
108
      insn = sparc_fetch_instruction (start_pc + *offset);
109
      if (insn != 0x83e82067)
110
        continue;
111
 
112
      /* Check for "t ST_SYSCALL".  */
113
      insn = sparc_fetch_instruction (start_pc + *offset + 8);
114
      if (insn != 0x91d02000)
115
        continue;
116
 
117
      return 1;
118
    }
119
 
120
  return 0;
121
}
122
 
123
static struct sparc_frame_cache *
124
sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
125
{
126
  struct sparc_frame_cache *cache;
127
  CORE_ADDR addr;
128
 
129
  if (*this_cache)
130
    return *this_cache;
131
 
132
  cache = sparc_frame_cache (next_frame, this_cache);
133
  gdb_assert (cache == *this_cache);
134
 
135
  /* If we couldn't find the frame's function, we're probably dealing
136
     with an on-stack signal trampoline.  */
137
  if (cache->pc == 0)
138
    {
139
      cache->pc = frame_pc_unwind (next_frame);
140
      cache->pc &= ~(sparc64obsd_page_size - 1);
141
 
142
      /* Since we couldn't find the frame's function, the cache was
143
         initialized under the assumption that we're frameless.  */
144
      cache->frameless_p = 0;
145
      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
146
      if (addr & 1)
147
        addr += BIAS;
148
      cache->base = addr;
149
    }
150
 
151
  /* We find the appropriate instance of `struct sigcontext' at a
152
     fixed offset in the signal frame.  */
153
  addr = cache->base + 128 + 16;
154
  cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame);
155
 
156
  return cache;
157
}
158
 
159
static void
160
sparc64obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
161
                           struct frame_id *this_id)
162
{
163
  struct sparc_frame_cache *cache =
164
    sparc64obsd_frame_cache (next_frame, this_cache);
165
 
166
  (*this_id) = frame_id_build (cache->base, cache->pc);
167
}
168
 
169
static void
170
sparc64obsd_frame_prev_register (struct frame_info *next_frame,
171
                                 void **this_cache,
172
                                 int regnum, int *optimizedp,
173
                                 enum lval_type *lvalp, CORE_ADDR *addrp,
174
                                 int *realnump, gdb_byte *valuep)
175
{
176
  struct sparc_frame_cache *cache =
177
    sparc64obsd_frame_cache (next_frame, this_cache);
178
 
179
  trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
180
                                optimizedp, lvalp, addrp, realnump, valuep);
181
}
182
 
183
static const struct frame_unwind sparc64obsd_frame_unwind =
184
{
185
  SIGTRAMP_FRAME,
186
  sparc64obsd_frame_this_id,
187
  sparc64obsd_frame_prev_register
188
};
189
 
190
static const struct frame_unwind *
191
sparc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
192
{
193
  CORE_ADDR pc = frame_pc_unwind (next_frame);
194
  char *name;
195
 
196
  find_pc_partial_function (pc, &name, NULL, NULL);
197
  if (sparc64obsd_pc_in_sigtramp (pc, name))
198
    return &sparc64obsd_frame_unwind;
199
 
200
  return NULL;
201
}
202
 
203
/* Kernel debugging support.  */
204
 
205
static struct sparc_frame_cache *
206
sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache)
207
{
208
  struct sparc_frame_cache *cache;
209
  CORE_ADDR sp, trapframe_addr;
210
  int regnum;
211
 
212
  if (*this_cache)
213
    return *this_cache;
214
 
215
  cache = sparc_frame_cache (next_frame, this_cache);
216
  gdb_assert (cache == *this_cache);
217
 
218
  sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
219
  trapframe_addr = sp + BIAS + 176;
220
 
221
  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
222
 
223
  cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr;
224
  cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8;
225
  cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16;
226
 
227
  for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
228
    cache->saved_regs[regnum].addr =
229
      trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8;
230
 
231
  return cache;
232
}
233
 
234
static void
235
sparc64obsd_trapframe_this_id (struct frame_info *next_frame,
236
                               void **this_cache, struct frame_id *this_id)
237
{
238
  struct sparc_frame_cache *cache =
239
    sparc64obsd_trapframe_cache (next_frame, this_cache);
240
 
241
  (*this_id) = frame_id_build (cache->base, cache->pc);
242
}
243
 
244
static void
245
sparc64obsd_trapframe_prev_register (struct frame_info *next_frame,
246
                                     void **this_cache,
247
                                     int regnum, int *optimizedp,
248
                                     enum lval_type *lvalp, CORE_ADDR *addrp,
249
                                     int *realnump, gdb_byte *valuep)
250
{
251
  struct sparc_frame_cache *cache =
252
    sparc64obsd_trapframe_cache (next_frame, this_cache);
253
 
254
  trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
255
                                optimizedp, lvalp, addrp, realnump, valuep);
256
}
257
 
258
static const struct frame_unwind sparc64obsd_trapframe_unwind =
259
{
260
  NORMAL_FRAME,
261
  sparc64obsd_trapframe_this_id,
262
  sparc64obsd_trapframe_prev_register
263
};
264
 
265
static const struct frame_unwind *
266
sparc64obsd_trapframe_sniffer (struct frame_info *next_frame)
267
{
268
  CORE_ADDR pc;
269
  ULONGEST pstate;
270
  char *name;
271
 
272
  /* Check whether we are in privileged mode, and bail out if we're not.  */
273
  pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM);
274
  if ((pstate & SPARC64_PSTATE_PRIV) == 0)
275
    return NULL;
276
 
277
  pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
278
  find_pc_partial_function (pc, &name, NULL, NULL);
279
  if (name && strcmp (name, "Lslowtrap_reenter") == 0)
280
    return &sparc64obsd_trapframe_unwind;
281
 
282
  return NULL;
283
}
284
 
285
 
286
/* Threads support.  */
287
 
288
/* Offset wthin the thread structure where we can find %fp and %i7.  */
289
#define SPARC64OBSD_UTHREAD_FP_OFFSET   232
290
#define SPARC64OBSD_UTHREAD_PC_OFFSET   240
291
 
292
static void
293
sparc64obsd_supply_uthread (struct regcache *regcache,
294
                            int regnum, CORE_ADDR addr)
295
{
296
  CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
297
  gdb_byte buf[8];
298
 
299
  gdb_assert (regnum >= -1);
300
 
301
  fp = read_memory_unsigned_integer (fp_addr, 8);
302
  if (regnum == SPARC_SP_REGNUM || regnum == -1)
303
    {
304
      store_unsigned_integer (buf, 8, fp);
305
      regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
306
 
307
      if (regnum == SPARC_SP_REGNUM)
308
        return;
309
    }
310
 
311
  if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM
312
      || regnum == -1)
313
    {
314
      CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
315
 
316
      i7 = read_memory_unsigned_integer (i7_addr, 8);
317
      if (regnum == SPARC64_PC_REGNUM || regnum == -1)
318
        {
319
          store_unsigned_integer (buf, 8, i7 + 8);
320
          regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf);
321
        }
322
      if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
323
        {
324
          store_unsigned_integer (buf, 8, i7 + 12);
325
          regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf);
326
        }
327
 
328
      if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
329
        return;
330
    }
331
 
332
  sparc_supply_rwindow (regcache, fp, regnum);
333
}
334
 
335
static void
336
sparc64obsd_collect_uthread(const struct regcache *regcache,
337
                            int regnum, CORE_ADDR addr)
338
{
339
  CORE_ADDR sp;
340
  gdb_byte buf[8];
341
 
342
  gdb_assert (regnum >= -1);
343
 
344
  if (regnum == SPARC_SP_REGNUM || regnum == -1)
345
    {
346
      CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
347
 
348
      regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
349
      write_memory (fp_addr,buf, 8);
350
    }
351
 
352
  if (regnum == SPARC64_PC_REGNUM || regnum == -1)
353
    {
354
      CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
355
 
356
      regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf);
357
      i7 = extract_unsigned_integer (buf, 8) - 8;
358
      write_memory_unsigned_integer (i7_addr, 8, i7);
359
 
360
      if (regnum == SPARC64_PC_REGNUM)
361
        return;
362
    }
363
 
364
  regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
365
  sp = extract_unsigned_integer (buf, 8);
366
  sparc_collect_rwindow (regcache, sp, regnum);
367
}
368
 
369
 
370
static void
371
sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
372
{
373
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
374
 
375
  tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL);
376
  tdep->sizeof_gregset = 832;
377
 
378
  /* Make sure we can single-step "new" syscalls.  */
379
  tdep->step_trap = sparcnbsd_step_trap;
380
 
381
  frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
382
  frame_unwind_append_sniffer (gdbarch, sparc64obsd_trapframe_sniffer);
383
 
384
  sparc64_init_abi (info, gdbarch);
385
 
386
  /* OpenBSD/sparc64 has SVR4-style shared libraries.  */
387
  set_solib_svr4_fetch_link_map_offsets
388
    (gdbarch, svr4_lp64_fetch_link_map_offsets);
389
  set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
390
 
391
  /* OpenBSD provides a user-level threads implementation.  */
392
  bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread);
393
  bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread);
394
}
395
 
396
 
397
/* Provide a prototype to silence -Wmissing-prototypes.  */
398
void _initialize_sparc64obsd_tdep (void);
399
 
400
void
401
_initialize_sparc64obsd_tdep (void)
402
{
403
  gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
404
                          GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi);
405
}

powered by: WebSVN 2.1.0

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