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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [frv-linux-tdep.c] - Blame information for rev 157

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Target-dependent code for GNU/Linux running on the Fujitsu FR-V,
2
   for GDB.
3
 
4
   Copyright (C) 2004, 2006, 2007, 2008 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 "gdbcore.h"
23
#include "target.h"
24
#include "frame.h"
25
#include "osabi.h"
26
#include "regcache.h"
27
#include "elf-bfd.h"
28
#include "elf/frv.h"
29
#include "frv-tdep.h"
30
#include "trad-frame.h"
31
#include "frame-unwind.h"
32
#include "regset.h"
33
#include "gdb_string.h"
34
 
35
/* Define the size (in bytes) of an FR-V instruction.  */
36
static const int frv_instr_size = 4;
37
 
38
enum {
39
  NORMAL_SIGTRAMP = 1,
40
  RT_SIGTRAMP = 2
41
};
42
 
43
static int
44
frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
45
{
46
  char buf[frv_instr_size];
47
  LONGEST instr;
48
  int retval = 0;
49
 
50
  if (target_read_memory (pc, buf, sizeof buf) != 0)
51
    return 0;
52
 
53
  instr = extract_unsigned_integer (buf, sizeof buf);
54
 
55
  if (instr == 0x8efc0077)      /* setlos #__NR_sigreturn, gr7 */
56
    retval = NORMAL_SIGTRAMP;
57
  else if (instr -= 0x8efc00ad) /* setlos #__NR_rt_sigreturn, gr7 */
58
    retval = RT_SIGTRAMP;
59
  else
60
    return 0;
61
 
62
  if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0)
63
    return 0;
64
  instr = extract_unsigned_integer (buf, sizeof buf);
65
  if (instr != 0xc0700000)      /* tira gr0, 0 */
66
    return 0;
67
 
68
  /* If we get this far, we'll return a non-zero value, either
69
     NORMAL_SIGTRAMP (1) or RT_SIGTRAMP (2).  */
70
  return retval;
71
}
72
 
73
/* Given NEXT_FRAME, the "callee" frame of the sigtramp frame that we
74
   wish to decode, and REGNO, one of the frv register numbers defined
75
   in frv-tdep.h, return the address of the saved register (corresponding
76
   to REGNO) in the sigtramp frame.  Return -1 if the register is not
77
   found in the sigtramp frame.  The magic numbers in the code below
78
   were computed by examining the following kernel structs:
79
 
80
   From arch/frv/kernel/signal.c:
81
 
82
      struct sigframe
83
      {
84
              void (*pretcode)(void);
85
              int sig;
86
              struct sigcontext sc;
87
              unsigned long extramask[_NSIG_WORDS-1];
88
              uint32_t retcode[2];
89
      };
90
 
91
      struct rt_sigframe
92
      {
93
              void (*pretcode)(void);
94
              int sig;
95
              struct siginfo *pinfo;
96
              void *puc;
97
              struct siginfo info;
98
              struct ucontext uc;
99
              uint32_t retcode[2];
100
      };
101
 
102
   From include/asm-frv/ucontext.h:
103
 
104
      struct ucontext {
105
              unsigned long             uc_flags;
106
              struct ucontext           *uc_link;
107
              stack_t                   uc_stack;
108
              struct sigcontext uc_mcontext;
109
              sigset_t          uc_sigmask;
110
      };
111
 
112
   From include/asm-frv/signal.h:
113
 
114
      typedef struct sigaltstack {
115
              void *ss_sp;
116
              int ss_flags;
117
              size_t ss_size;
118
      } stack_t;
119
 
120
   From include/asm-frv/sigcontext.h:
121
 
122
      struct sigcontext {
123
              struct user_context       sc_context;
124
              unsigned long             sc_oldmask;
125
      } __attribute__((aligned(8)));
126
 
127
   From include/asm-frv/registers.h:
128
      struct user_int_regs
129
      {
130
              unsigned long             psr;
131
              unsigned long             isr;
132
              unsigned long             ccr;
133
              unsigned long             cccr;
134
              unsigned long             lr;
135
              unsigned long             lcr;
136
              unsigned long             pc;
137
              unsigned long             __status;
138
              unsigned long             syscallno;
139
              unsigned long             orig_gr8;
140
              unsigned long             gner[2];
141
              unsigned long long        iacc[1];
142
 
143
              union {
144
                      unsigned long     tbr;
145
                      unsigned long     gr[64];
146
              };
147
      };
148
 
149
      struct user_fpmedia_regs
150
      {
151
              unsigned long     fr[64];
152
              unsigned long     fner[2];
153
              unsigned long     msr[2];
154
              unsigned long     acc[8];
155
              unsigned char     accg[8];
156
              unsigned long     fsr[1];
157
      };
158
 
159
      struct user_context
160
      {
161
              struct user_int_regs              i;
162
              struct user_fpmedia_regs  f;
163
 
164
              void *extension;
165
      } __attribute__((aligned(8)));  */
166
 
167
static LONGEST
168
frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno,
169
                               CORE_ADDR *sc_addr_cache_ptr)
170
{
171
  CORE_ADDR sc_addr;
172
 
173
  if (sc_addr_cache_ptr && *sc_addr_cache_ptr)
174
    {
175
      sc_addr = *sc_addr_cache_ptr;
176
    }
177
  else
178
    {
179
      CORE_ADDR pc, sp;
180
      char buf[4];
181
      int tramp_type;
182
 
183
      pc = frame_pc_unwind (next_frame);
184
      tramp_type = frv_linux_pc_in_sigtramp (pc, 0);
185
 
186
      frame_unwind_register (next_frame, sp_regnum, buf);
187
      sp = extract_unsigned_integer (buf, sizeof buf);
188
 
189
      if (tramp_type == NORMAL_SIGTRAMP)
190
        {
191
          /* For a normal sigtramp frame, the sigcontext struct starts
192
             at SP + 8.  */
193
          sc_addr = sp + 8;
194
        }
195
      else if (tramp_type == RT_SIGTRAMP)
196
        {
197
          /* For a realtime sigtramp frame, SP + 12 contains a pointer
198
             to a ucontext struct.  The ucontext struct contains a
199
             sigcontext struct starting 24 bytes in.  (The offset of
200
             uc_mcontext within struct ucontext is derived as follows:
201
             stack_t is a 12-byte struct and struct sigcontext is
202
             8-byte aligned.  This gives an offset of 8 + 12 + 4 (for
203
             padding) = 24.) */
204
          if (target_read_memory (sp + 12, buf, sizeof buf) != 0)
205
            {
206
              warning (_("Can't read realtime sigtramp frame."));
207
              return 0;
208
            }
209
          sc_addr = extract_unsigned_integer (buf, sizeof buf);
210
          sc_addr += 24;
211
        }
212
      else
213
        internal_error (__FILE__, __LINE__, _("not a signal trampoline"));
214
 
215
      if (sc_addr_cache_ptr)
216
        *sc_addr_cache_ptr = sc_addr;
217
    }
218
 
219
  switch (regno)
220
    {
221
    case psr_regnum :
222
      return sc_addr + 0;
223
    /* sc_addr + 4 has "isr", the Integer Status Register.  */
224
    case ccr_regnum :
225
      return sc_addr + 8;
226
    case cccr_regnum :
227
      return sc_addr + 12;
228
    case lr_regnum :
229
      return sc_addr + 16;
230
    case lcr_regnum :
231
      return sc_addr + 20;
232
    case pc_regnum :
233
      return sc_addr + 24;
234
    /* sc_addr + 28 is __status, the exception status.
235
       sc_addr + 32 is syscallno, the syscall number or -1.
236
       sc_addr + 36 is orig_gr8, the original syscall arg #1.
237
       sc_addr + 40 is gner[0].
238
       sc_addr + 44 is gner[1]. */
239
    case iacc0h_regnum :
240
      return sc_addr + 48;
241
    case iacc0l_regnum :
242
      return sc_addr + 52;
243
    default :
244
      if (first_gpr_regnum <= regno && regno <= last_gpr_regnum)
245
        return sc_addr + 56 + 4 * (regno - first_gpr_regnum);
246
      else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum)
247
        return sc_addr + 312 + 4 * (regno - first_fpr_regnum);
248
      else
249
        return -1;  /* not saved. */
250
    }
251
}
252
 
253
/* Signal trampolines.  */
254
 
255
static struct trad_frame_cache *
256
frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
257
{
258
  struct trad_frame_cache *cache;
259
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
260
  CORE_ADDR addr;
261
  char buf[4];
262
  int regnum;
263
  CORE_ADDR sc_addr_cache_val = 0;
264
  struct frame_id this_id;
265
 
266
  if (*this_cache)
267
    return *this_cache;
268
 
269
  cache = trad_frame_cache_zalloc (next_frame);
270
 
271
  /* FIXME: cagney/2004-05-01: This is is long standing broken code.
272
     The frame ID's code address should be the start-address of the
273
     signal trampoline and not the current PC within that
274
     trampoline.  */
275
  frame_unwind_register (next_frame, sp_regnum, buf);
276
  this_id = frame_id_build (extract_unsigned_integer (buf, sizeof buf),
277
                            frame_pc_unwind (next_frame));
278
  trad_frame_set_id (cache, this_id);
279
 
280
  for (regnum = 0; regnum < frv_num_regs; regnum++)
281
    {
282
      LONGEST reg_addr = frv_linux_sigcontext_reg_addr (next_frame, regnum,
283
                                                        &sc_addr_cache_val);
284
      if (reg_addr != -1)
285
        trad_frame_set_reg_addr (cache, regnum, reg_addr);
286
    }
287
 
288
  *this_cache = cache;
289
  return cache;
290
}
291
 
292
static void
293
frv_linux_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
294
                             struct frame_id *this_id)
295
{
296
  struct trad_frame_cache *cache =
297
    frv_linux_sigtramp_frame_cache (next_frame, this_cache);
298
  trad_frame_get_id (cache, this_id);
299
}
300
 
301
static void
302
frv_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
303
                                   void **this_cache,
304
                                   int regnum, int *optimizedp,
305
                                   enum lval_type *lvalp, CORE_ADDR *addrp,
306
                                   int *realnump, gdb_byte *valuep)
307
{
308
  /* Make sure we've initialized the cache.  */
309
  struct trad_frame_cache *cache =
310
    frv_linux_sigtramp_frame_cache (next_frame, this_cache);
311
  trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp,
312
                           addrp, realnump, valuep);
313
}
314
 
315
static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
316
{
317
  SIGTRAMP_FRAME,
318
  frv_linux_sigtramp_frame_this_id,
319
  frv_linux_sigtramp_frame_prev_register
320
};
321
 
322
static const struct frame_unwind *
323
frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
324
{
325
  CORE_ADDR pc = frame_pc_unwind (next_frame);
326
  char *name;
327
 
328
  find_pc_partial_function (pc, &name, NULL, NULL);
329
  if (frv_linux_pc_in_sigtramp (pc, name))
330
    return &frv_linux_sigtramp_frame_unwind;
331
 
332
  return NULL;
333
}
334
 
335
 
336
/* The FRV kernel defines ELF_NGREG as 46.  We add 2 in order to include
337
   the loadmap addresses in the register set.  (See below for more info.)  */
338
#define FRV_ELF_NGREG (46 + 2)
339
typedef unsigned char frv_elf_greg_t[4];
340
typedef struct { frv_elf_greg_t reg[FRV_ELF_NGREG]; } frv_elf_gregset_t;
341
 
342
typedef unsigned char frv_elf_fpreg_t[4];
343
typedef struct
344
{
345
  frv_elf_fpreg_t fr[64];
346
  frv_elf_fpreg_t fner[2];
347
  frv_elf_fpreg_t msr[2];
348
  frv_elf_fpreg_t acc[8];
349
  unsigned char accg[8];
350
  frv_elf_fpreg_t fsr[1];
351
} frv_elf_fpregset_t;
352
 
353
/* Constants for accessing elements of frv_elf_gregset_t.  */
354
 
355
#define FRV_PT_PSR 0
356
#define FRV_PT_ISR 1
357
#define FRV_PT_CCR 2
358
#define FRV_PT_CCCR 3
359
#define FRV_PT_LR 4
360
#define FRV_PT_LCR 5
361
#define FRV_PT_PC 6
362
#define FRV_PT_GNER0 10
363
#define FRV_PT_GNER1 11
364
#define FRV_PT_IACC0H 12
365
#define FRV_PT_IACC0L 13
366
 
367
/* Note: Only 32 of the GRs will be found in the corefile.  */
368
#define FRV_PT_GR(j)    ( 14 + (j))     /* GRj for 0<=j<=63. */
369
 
370
#define FRV_PT_TBR FRV_PT_GR(0)         /* gr0 is always 0, so TBR is stuffed
371
                                           there.  */
372
 
373
/* Technically, the loadmap addresses are not part of `pr_reg' as
374
   found in the elf_prstatus struct.  The fields which communicate the
375
   loadmap address appear (by design) immediately after `pr_reg'
376
   though, and the BFD function elf32_frv_grok_prstatus() has been
377
   implemented to include these fields in the register section that it
378
   extracts from the core file.  So, for our purposes, they may be
379
   viewed as registers.  */
380
 
381
#define FRV_PT_EXEC_FDPIC_LOADMAP 46
382
#define FRV_PT_INTERP_FDPIC_LOADMAP 47
383
 
384
 
385
/* Unpack an frv_elf_gregset_t into GDB's register cache.  */
386
 
387
static void
388
frv_linux_supply_gregset (const struct regset *regset,
389
                          struct regcache *regcache,
390
                          int regnum, const void *gregs, size_t len)
391
{
392
  int regi;
393
  char zerobuf[MAX_REGISTER_SIZE];
394
  const frv_elf_gregset_t *gregsetp = gregs;
395
 
396
  memset (zerobuf, 0, MAX_REGISTER_SIZE);
397
 
398
  /* gr0 always contains 0.  Also, the kernel passes the TBR value in
399
     this slot.  */
400
  regcache_raw_supply (regcache, first_gpr_regnum, zerobuf);
401
 
402
  for (regi = first_gpr_regnum + 1; regi <= last_gpr_regnum; regi++)
403
    {
404
      if (regi >= first_gpr_regnum + 32)
405
        regcache_raw_supply (regcache, regi, zerobuf);
406
      else
407
        regcache_raw_supply (regcache, regi,
408
                             gregsetp->reg[FRV_PT_GR (regi - first_gpr_regnum)]);
409
    }
410
 
411
  regcache_raw_supply (regcache, pc_regnum, gregsetp->reg[FRV_PT_PC]);
412
  regcache_raw_supply (regcache, psr_regnum, gregsetp->reg[FRV_PT_PSR]);
413
  regcache_raw_supply (regcache, ccr_regnum, gregsetp->reg[FRV_PT_CCR]);
414
  regcache_raw_supply (regcache, cccr_regnum, gregsetp->reg[FRV_PT_CCCR]);
415
  regcache_raw_supply (regcache, lr_regnum, gregsetp->reg[FRV_PT_LR]);
416
  regcache_raw_supply (regcache, lcr_regnum, gregsetp->reg[FRV_PT_LCR]);
417
  regcache_raw_supply (regcache, gner0_regnum, gregsetp->reg[FRV_PT_GNER0]);
418
  regcache_raw_supply (regcache, gner1_regnum, gregsetp->reg[FRV_PT_GNER1]);
419
  regcache_raw_supply (regcache, tbr_regnum, gregsetp->reg[FRV_PT_TBR]);
420
  regcache_raw_supply (regcache, fdpic_loadmap_exec_regnum,
421
                       gregsetp->reg[FRV_PT_EXEC_FDPIC_LOADMAP]);
422
  regcache_raw_supply (regcache, fdpic_loadmap_interp_regnum,
423
                       gregsetp->reg[FRV_PT_INTERP_FDPIC_LOADMAP]);
424
}
425
 
426
/* Unpack an frv_elf_fpregset_t into GDB's register cache.  */
427
 
428
static void
429
frv_linux_supply_fpregset (const struct regset *regset,
430
                           struct regcache *regcache,
431
                           int regnum, const void *gregs, size_t len)
432
{
433
  int regi;
434
  const frv_elf_fpregset_t *fpregsetp = gregs;
435
 
436
  for (regi = first_fpr_regnum; regi <= last_fpr_regnum; regi++)
437
    regcache_raw_supply (regcache, regi, fpregsetp->fr[regi - first_fpr_regnum]);
438
 
439
  regcache_raw_supply (regcache, fner0_regnum, fpregsetp->fner[0]);
440
  regcache_raw_supply (regcache, fner1_regnum, fpregsetp->fner[1]);
441
 
442
  regcache_raw_supply (regcache, msr0_regnum, fpregsetp->msr[0]);
443
  regcache_raw_supply (regcache, msr1_regnum, fpregsetp->msr[1]);
444
 
445
  for (regi = acc0_regnum; regi <= acc7_regnum; regi++)
446
    regcache_raw_supply (regcache, regi, fpregsetp->acc[regi - acc0_regnum]);
447
 
448
  regcache_raw_supply (regcache, accg0123_regnum, fpregsetp->accg);
449
  regcache_raw_supply (regcache, accg4567_regnum, fpregsetp->accg + 4);
450
 
451
  regcache_raw_supply (regcache, fsr0_regnum, fpregsetp->fsr[0]);
452
}
453
 
454
/* FRV Linux kernel register sets.  */
455
 
456
static struct regset frv_linux_gregset =
457
{
458
  NULL,
459
  frv_linux_supply_gregset
460
};
461
 
462
static struct regset frv_linux_fpregset =
463
{
464
  NULL,
465
  frv_linux_supply_fpregset
466
};
467
 
468
static const struct regset *
469
frv_linux_regset_from_core_section (struct gdbarch *gdbarch,
470
                                    const char *sect_name, size_t sect_size)
471
{
472
  if (strcmp (sect_name, ".reg") == 0
473
      && sect_size >= sizeof (frv_elf_gregset_t))
474
    return &frv_linux_gregset;
475
 
476
  if (strcmp (sect_name, ".reg2") == 0
477
      && sect_size >= sizeof (frv_elf_fpregset_t))
478
    return &frv_linux_fpregset;
479
 
480
  return NULL;
481
}
482
 
483
 
484
static void
485
frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
486
{
487
  /* Set the sigtramp frame sniffer.  */
488
  frame_unwind_append_sniffer (gdbarch, frv_linux_sigtramp_frame_sniffer);
489
  set_gdbarch_regset_from_core_section (gdbarch,
490
                                        frv_linux_regset_from_core_section);
491
}
492
 
493
static enum gdb_osabi
494
frv_linux_elf_osabi_sniffer (bfd *abfd)
495
{
496
  int elf_flags;
497
 
498
  elf_flags = elf_elfheader (abfd)->e_flags;
499
 
500
  /* Assume GNU/Linux if using the FDPIC ABI.  If/when another OS shows
501
     up that uses this ABI, we'll need to start using .note sections
502
     or some such.  */
503
  if (elf_flags & EF_FRV_FDPIC)
504
    return GDB_OSABI_LINUX;
505
  else
506
    return GDB_OSABI_UNKNOWN;
507
}
508
 
509
/* Provide a prototype to silence -Wmissing-prototypes.  */
510
void _initialize_frv_linux_tdep (void);
511
 
512
void
513
_initialize_frv_linux_tdep (void)
514
{
515
  gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, frv_linux_init_abi);
516
  gdbarch_register_osabi_sniffer (bfd_arch_frv,
517
                                  bfd_target_elf_flavour,
518
                                  frv_linux_elf_osabi_sniffer);
519
}

powered by: WebSVN 2.1.0

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