Home | History | Annotate | Line # | Download | only in gdb
i386-netbsd-tdep.c revision 1.1
      1  1.1  christos /* Target-dependent code for NetBSD/i386.
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 1988-2023 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GDB.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19  1.1  christos 
     20  1.1  christos #include "defs.h"
     21  1.1  christos #include "arch-utils.h"
     22  1.1  christos #include "frame.h"
     23  1.1  christos #include "gdbcore.h"
     24  1.1  christos #include "regcache.h"
     25  1.1  christos #include "regset.h"
     26  1.1  christos #include "osabi.h"
     27  1.1  christos #include "symtab.h"
     28  1.1  christos #include "trad-frame.h"
     29  1.1  christos #include "tramp-frame.h"
     30  1.1  christos #include "frame-unwind.h"
     31  1.1  christos 
     32  1.1  christos #include "i386-tdep.h"
     33  1.1  christos #include "i387-tdep.h"
     34  1.1  christos #include "netbsd-tdep.h"
     35  1.1  christos #include "solib-svr4.h"
     36  1.1  christos 
     37  1.1  christos /* From <machine/reg.h>.  */
     38  1.1  christos static int i386nbsd_r_reg_offset[] =
     39  1.1  christos {
     40  1.1  christos   0 * 4,			/* %eax */
     41  1.1  christos   1 * 4,			/* %ecx */
     42  1.1  christos   2 * 4,			/* %edx */
     43  1.1  christos   3 * 4,			/* %ebx */
     44  1.1  christos   4 * 4,			/* %esp */
     45  1.1  christos   5 * 4,			/* %ebp */
     46  1.1  christos   6 * 4,			/* %esi */
     47  1.1  christos   7 * 4,			/* %edi */
     48  1.1  christos   8 * 4,			/* %eip */
     49  1.1  christos   9 * 4,			/* %eflags */
     50  1.1  christos   10 * 4,			/* %cs */
     51  1.1  christos   11 * 4,			/* %ss */
     52  1.1  christos   12 * 4,			/* %ds */
     53  1.1  christos   13 * 4,			/* %es */
     54  1.1  christos   14 * 4,			/* %fs */
     55  1.1  christos   15 * 4			/* %gs */
     56  1.1  christos };
     57  1.1  christos 
     58  1.1  christos /* From <machine/signal.h>.  */
     59  1.1  christos static int i386nbsd_sc_reg_offset[] =
     60  1.1  christos {
     61  1.1  christos   10 * 4,			/* %eax */
     62  1.1  christos   9 * 4,			/* %ecx */
     63  1.1  christos   8 * 4,			/* %edx */
     64  1.1  christos   7 * 4,			/* %ebx */
     65  1.1  christos   14 * 4,			/* %esp */
     66  1.1  christos   6 * 4,			/* %ebp */
     67  1.1  christos   5 * 4,			/* %esi */
     68  1.1  christos   4 * 4,			/* %edi */
     69  1.1  christos   11 * 4,			/* %eip */
     70  1.1  christos   13 * 4,			/* %eflags */
     71  1.1  christos   12 * 4,			/* %cs */
     72  1.1  christos   15 * 4,			/* %ss */
     73  1.1  christos   3 * 4,			/* %ds */
     74  1.1  christos   2 * 4,			/* %es */
     75  1.1  christos   1 * 4,			/* %fs */
     76  1.1  christos   0 * 4				/* %gs */
     77  1.1  christos };
     78  1.1  christos 
     79  1.1  christos /* From <machine/mcontext.h>.  */
     80  1.1  christos static int i386nbsd_mc_reg_offset[] =
     81  1.1  christos {
     82  1.1  christos   11 * 4,			/* %eax */
     83  1.1  christos   10 * 4,			/* %ecx */
     84  1.1  christos   9 * 4,			/* %edx */
     85  1.1  christos   8 * 4,			/* %ebx */
     86  1.1  christos   7 * 4,			/* %esp */
     87  1.1  christos   6 * 4,			/* %ebp */
     88  1.1  christos   5 * 4,			/* %esi */
     89  1.1  christos   4 * 4,			/* %edi */
     90  1.1  christos   14 * 4,			/* %eip */
     91  1.1  christos   16 * 4,			/* %eflags */
     92  1.1  christos   15 * 4,			/* %cs */
     93  1.1  christos   18 * 4,			/* %ss */
     94  1.1  christos   3 * 4,			/* %ds */
     95  1.1  christos   2 * 4,			/* %es */
     96  1.1  christos   1 * 4,			/* %fs */
     97  1.1  christos   0 * 4				/* %gs */
     98  1.1  christos };
     99  1.1  christos 
    100  1.1  christos static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
    101  1.1  christos 					  frame_info_ptr,
    102  1.1  christos 					  struct trad_frame_cache *,
    103  1.1  christos 					  CORE_ADDR);
    104  1.1  christos 
    105  1.1  christos static const struct tramp_frame i386nbsd_sigtramp_sc16 =
    106  1.1  christos {
    107  1.1  christos   SIGTRAMP_FRAME,
    108  1.1  christos   1,
    109  1.1  christos   {
    110  1.1  christos    /* leal  0x10(%esp), %eax */
    111  1.1  christos    { 0x8d, ULONGEST_MAX },
    112  1.1  christos    { 0x44, ULONGEST_MAX },
    113  1.1  christos    { 0x24, ULONGEST_MAX },
    114  1.1  christos    { 0x10, ULONGEST_MAX },
    115  1.1  christos 
    116  1.1  christos    /* pushl %eax */
    117  1.1  christos    { 0x50, ULONGEST_MAX },
    118  1.1  christos 
    119  1.1  christos    /* pushl %eax */
    120  1.1  christos    { 0x50, ULONGEST_MAX },
    121  1.1  christos 
    122  1.1  christos    /* movl  $0x127, %eax		# __sigreturn14 */
    123  1.1  christos    { 0xb8, ULONGEST_MAX },
    124  1.1  christos    { 0x27, ULONGEST_MAX },
    125  1.1  christos    {0x01, ULONGEST_MAX },
    126  1.1  christos    {0x00, ULONGEST_MAX },
    127  1.1  christos    {0x00, ULONGEST_MAX },
    128  1.1  christos 
    129  1.1  christos    /* int   $0x80 */
    130  1.1  christos    { 0xcd, ULONGEST_MAX },
    131  1.1  christos    { 0x80, ULONGEST_MAX},
    132  1.1  christos 
    133  1.1  christos    /* movl  $0x1, %eax		# exit */
    134  1.1  christos    { 0xb8, ULONGEST_MAX },
    135  1.1  christos    { 0x01, ULONGEST_MAX },
    136  1.1  christos    {0x00, ULONGEST_MAX },
    137  1.1  christos    {0x00, ULONGEST_MAX },
    138  1.1  christos    {0x00, ULONGEST_MAX },
    139  1.1  christos 
    140  1.1  christos    /* int   $0x80 */
    141  1.1  christos    { 0xcd, ULONGEST_MAX },
    142  1.1  christos    { 0x80, ULONGEST_MAX},
    143  1.1  christos 
    144  1.1  christos    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    145  1.1  christos   },
    146  1.1  christos   i386nbsd_sigtramp_cache_init
    147  1.1  christos };
    148  1.1  christos 
    149  1.1  christos static const struct tramp_frame i386nbsd_sigtramp_sc2 =
    150  1.1  christos {
    151  1.1  christos   SIGTRAMP_FRAME,
    152  1.1  christos   1,
    153  1.1  christos   {
    154  1.1  christos    /* leal  0x0c(%esp), %eax */
    155  1.1  christos    { 0x8d, ULONGEST_MAX },
    156  1.1  christos    { 0x44, ULONGEST_MAX },
    157  1.1  christos    { 0x24, ULONGEST_MAX },
    158  1.1  christos    { 0x0c, ULONGEST_MAX },
    159  1.1  christos    /* movl  %eax, 0x4(%esp) */
    160  1.1  christos    { 0x89, ULONGEST_MAX },
    161  1.1  christos    { 0x44, ULONGEST_MAX },
    162  1.1  christos    { 0x24, ULONGEST_MAX },
    163  1.1  christos    { 0x04, ULONGEST_MAX },
    164  1.1  christos    /* movl  $0x127, %eax		# __sigreturn14 */
    165  1.1  christos    { 0xb8, ULONGEST_MAX },
    166  1.1  christos    { 0x27, ULONGEST_MAX },
    167  1.1  christos    {0x01, ULONGEST_MAX },
    168  1.1  christos    {0x00, ULONGEST_MAX },
    169  1.1  christos    {0x00, ULONGEST_MAX },
    170  1.1  christos    /* int   $0x80 */
    171  1.1  christos    { 0xcd, ULONGEST_MAX },
    172  1.1  christos    { 0x80, ULONGEST_MAX},
    173  1.1  christos    /* movl  %eax, 0x4(%esp) */
    174  1.1  christos    { 0x89, ULONGEST_MAX },
    175  1.1  christos    { 0x44, ULONGEST_MAX },
    176  1.1  christos    { 0x24, ULONGEST_MAX },
    177  1.1  christos    { 0x04, ULONGEST_MAX },
    178  1.1  christos    /* movl  $0x1, %eax */
    179  1.1  christos    { 0xb8, ULONGEST_MAX },
    180  1.1  christos    { 0x01, ULONGEST_MAX },
    181  1.1  christos    {0x00, ULONGEST_MAX },
    182  1.1  christos    {0x00, ULONGEST_MAX },
    183  1.1  christos    {0x00, ULONGEST_MAX },
    184  1.1  christos    /* int   $0x80 */
    185  1.1  christos    { 0xcd, ULONGEST_MAX },
    186  1.1  christos    { 0x80, ULONGEST_MAX},
    187  1.1  christos    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    188  1.1  christos   },
    189  1.1  christos   i386nbsd_sigtramp_cache_init
    190  1.1  christos };
    191  1.1  christos 
    192  1.1  christos static const struct tramp_frame i386nbsd_sigtramp_si2 =
    193  1.1  christos {
    194  1.1  christos   SIGTRAMP_FRAME,
    195  1.1  christos   1,
    196  1.1  christos   {
    197  1.1  christos    /* movl  8(%esp),%eax */
    198  1.1  christos    { 0x8b, ULONGEST_MAX },
    199  1.1  christos    { 0x44, ULONGEST_MAX },
    200  1.1  christos    { 0x24, ULONGEST_MAX },
    201  1.1  christos    { 0x08, ULONGEST_MAX },
    202  1.1  christos    /* movl  %eax, 0x4(%esp) */
    203  1.1  christos    { 0x89, ULONGEST_MAX },
    204  1.1  christos    { 0x44, ULONGEST_MAX },
    205  1.1  christos    { 0x24, ULONGEST_MAX },
    206  1.1  christos    { 0x04, ULONGEST_MAX },
    207  1.1  christos    /* movl  $0x134, %eax            # setcontext */
    208  1.1  christos    { 0xb8, ULONGEST_MAX },
    209  1.1  christos    { 0x34, ULONGEST_MAX },
    210  1.1  christos    { 0x01, ULONGEST_MAX },
    211  1.1  christos    { 0x00, ULONGEST_MAX },
    212  1.1  christos    { 0x00, ULONGEST_MAX },
    213  1.1  christos    /* int   $0x80 */
    214  1.1  christos    { 0xcd, ULONGEST_MAX },
    215  1.1  christos    { 0x80, ULONGEST_MAX },
    216  1.1  christos    /* movl  %eax, 0x4(%esp) */
    217  1.1  christos    { 0x89, ULONGEST_MAX },
    218  1.1  christos    { 0x44, ULONGEST_MAX },
    219  1.1  christos    { 0x24, ULONGEST_MAX },
    220  1.1  christos    { 0x04, ULONGEST_MAX },
    221  1.1  christos    /* movl  $0x1, %eax */
    222  1.1  christos    { 0xb8, ULONGEST_MAX },
    223  1.1  christos    { 0x01, ULONGEST_MAX },
    224  1.1  christos    { 0x00, ULONGEST_MAX },
    225  1.1  christos    { 0x00, ULONGEST_MAX },
    226  1.1  christos    { 0x00, ULONGEST_MAX },
    227  1.1  christos    /* int   $0x80 */
    228  1.1  christos    { 0xcd, ULONGEST_MAX },
    229  1.1  christos    { 0x80, ULONGEST_MAX },
    230  1.1  christos    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    231  1.1  christos   },
    232  1.1  christos   i386nbsd_sigtramp_cache_init
    233  1.1  christos };
    234  1.1  christos 
    235  1.1  christos static const struct tramp_frame i386nbsd_sigtramp_si31 =
    236  1.1  christos {
    237  1.1  christos   SIGTRAMP_FRAME,
    238  1.1  christos   1,
    239  1.1  christos   {
    240  1.1  christos    /* leal  0x8c(%esp), %eax */
    241  1.1  christos    { 0x8d, ULONGEST_MAX },
    242  1.1  christos    { 0x84, ULONGEST_MAX },
    243  1.1  christos    { 0x24, ULONGEST_MAX },
    244  1.1  christos    { 0x8c, ULONGEST_MAX },
    245  1.1  christos    { 0x00, ULONGEST_MAX },
    246  1.1  christos    { 0x00, ULONGEST_MAX },
    247  1.1  christos    { 0x00, ULONGEST_MAX },
    248  1.1  christos    /* movl  %eax, 0x4(%esp) */
    249  1.1  christos    { 0x89, ULONGEST_MAX },
    250  1.1  christos    { 0x44, ULONGEST_MAX },
    251  1.1  christos    { 0x24, ULONGEST_MAX },
    252  1.1  christos    { 0x04, ULONGEST_MAX },
    253  1.1  christos    /* movl  $0x134, %eax            # setcontext */
    254  1.1  christos    { 0xb8, ULONGEST_MAX },
    255  1.1  christos    { 0x34, ULONGEST_MAX },
    256  1.1  christos    { 0x01, ULONGEST_MAX },
    257  1.1  christos    { 0x00, ULONGEST_MAX },
    258  1.1  christos    { 0x00, ULONGEST_MAX },
    259  1.1  christos    /* int   $0x80 */
    260  1.1  christos    { 0xcd, ULONGEST_MAX },
    261  1.1  christos    { 0x80, ULONGEST_MAX},
    262  1.1  christos    /* movl  %eax, 0x4(%esp) */
    263  1.1  christos    { 0x89, ULONGEST_MAX },
    264  1.1  christos    { 0x44, ULONGEST_MAX },
    265  1.1  christos    { 0x24, ULONGEST_MAX },
    266  1.1  christos    { 0x04, ULONGEST_MAX },
    267  1.1  christos    /* movl  $0x1, %eax */
    268  1.1  christos    { 0xb8, ULONGEST_MAX },
    269  1.1  christos    { 0x01, ULONGEST_MAX },
    270  1.1  christos    {0x00, ULONGEST_MAX },
    271  1.1  christos    {0x00, ULONGEST_MAX },
    272  1.1  christos    {0x00, ULONGEST_MAX },
    273  1.1  christos    /* int   $0x80 */
    274  1.1  christos    { 0xcd, ULONGEST_MAX },
    275  1.1  christos    { 0x80, ULONGEST_MAX},
    276  1.1  christos    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    277  1.1  christos   },
    278  1.1  christos   i386nbsd_sigtramp_cache_init
    279  1.1  christos };
    280  1.1  christos 
    281  1.1  christos static const struct tramp_frame i386nbsd_sigtramp_si4 =
    282  1.1  christos {
    283  1.1  christos   SIGTRAMP_FRAME,
    284  1.1  christos   1,
    285  1.1  christos   {
    286  1.1  christos    /* leal  0x8c(%esp), %eax */
    287  1.1  christos    { 0x8d, ULONGEST_MAX },
    288  1.1  christos    { 0x84, ULONGEST_MAX },
    289  1.1  christos    { 0x24, ULONGEST_MAX },
    290  1.1  christos    { 0x8c, ULONGEST_MAX },
    291  1.1  christos    { 0x00, ULONGEST_MAX },
    292  1.1  christos    { 0x00, ULONGEST_MAX },
    293  1.1  christos    { 0x00, ULONGEST_MAX },
    294  1.1  christos    /* movl  %eax, 0x4(%esp) */
    295  1.1  christos    { 0x89, ULONGEST_MAX },
    296  1.1  christos    { 0x44, ULONGEST_MAX },
    297  1.1  christos    { 0x24, ULONGEST_MAX },
    298  1.1  christos    { 0x04, ULONGEST_MAX },
    299  1.1  christos    /* movl  $0x134, %eax            # setcontext */
    300  1.1  christos    { 0xb8, ULONGEST_MAX },
    301  1.1  christos    { 0x34, ULONGEST_MAX },
    302  1.1  christos    { 0x01, ULONGEST_MAX },
    303  1.1  christos    { 0x00, ULONGEST_MAX },
    304  1.1  christos    { 0x00, ULONGEST_MAX },
    305  1.1  christos    /* int   $0x80 */
    306  1.1  christos    { 0xcd, ULONGEST_MAX },
    307  1.1  christos    { 0x80, ULONGEST_MAX},
    308  1.1  christos    /* movl   $0xffffffff,0x4(%esp) */
    309  1.1  christos    { 0xc7, ULONGEST_MAX },
    310  1.1  christos    { 0x44, ULONGEST_MAX },
    311  1.1  christos    { 0x24, ULONGEST_MAX },
    312  1.1  christos    { 0x04, ULONGEST_MAX },
    313  1.1  christos    { 0xff, ULONGEST_MAX },
    314  1.1  christos    { 0xff, ULONGEST_MAX },
    315  1.1  christos    { 0xff, ULONGEST_MAX },
    316  1.1  christos    { 0xff, ULONGEST_MAX },
    317  1.1  christos    /* movl  $0x1, %eax */
    318  1.1  christos    { 0xb8, ULONGEST_MAX },
    319  1.1  christos    { 0x01, ULONGEST_MAX },
    320  1.1  christos    {0x00, ULONGEST_MAX },
    321  1.1  christos    {0x00, ULONGEST_MAX },
    322  1.1  christos    {0x00, ULONGEST_MAX },
    323  1.1  christos    /* int   $0x80 */
    324  1.1  christos    { 0xcd, ULONGEST_MAX },
    325  1.1  christos    { 0x80, ULONGEST_MAX},
    326  1.1  christos    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
    327  1.1  christos   },
    328  1.1  christos   i386nbsd_sigtramp_cache_init
    329  1.1  christos };
    330  1.1  christos 
    331  1.1  christos static void
    332  1.1  christos i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
    333  1.1  christos 			      frame_info_ptr this_frame,
    334  1.1  christos 			      struct trad_frame_cache *this_cache,
    335  1.1  christos 			      CORE_ADDR func)
    336  1.1  christos {
    337  1.1  christos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    338  1.1  christos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    339  1.1  christos   CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
    340  1.1  christos   CORE_ADDR base;
    341  1.1  christos   int *reg_offset;
    342  1.1  christos   int num_regs;
    343  1.1  christos   int i;
    344  1.1  christos 
    345  1.1  christos   if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
    346  1.1  christos     {
    347  1.1  christos       reg_offset = i386nbsd_sc_reg_offset;
    348  1.1  christos       num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
    349  1.1  christos 
    350  1.1  christos       /* Read in the sigcontext address.  */
    351  1.1  christos       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
    352  1.1  christos     }
    353  1.1  christos   else
    354  1.1  christos     {
    355  1.1  christos       reg_offset = i386nbsd_mc_reg_offset;
    356  1.1  christos       num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
    357  1.1  christos 
    358  1.1  christos       /* Read in the ucontext address.  */
    359  1.1  christos       base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
    360  1.1  christos       /* offsetof(ucontext_t, uc_mcontext) == 36 */
    361  1.1  christos       base += 36;
    362  1.1  christos     }
    363  1.1  christos 
    364  1.1  christos   for (i = 0; i < num_regs; i++)
    365  1.1  christos     if (reg_offset[i] != -1)
    366  1.1  christos       trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
    367  1.1  christos 
    368  1.1  christos   /* Construct the frame ID using the function start.  */
    369  1.1  christos   trad_frame_set_id (this_cache, frame_id_build (sp, func));
    370  1.1  christos }
    371  1.1  christos 
    372  1.1  christos 
    374  1.1  christos /* From <machine/frame.h>.  Note that %esp and %ess are only saved in
    375  1.1  christos    a trap frame when entering the kernel from user space.  */
    376  1.1  christos static int i386nbsd_tf_reg_offset[] =
    377  1.1  christos {
    378  1.1  christos   10 * 4,			/* %eax */
    379  1.1  christos    9 * 4,			/* %ecx */
    380  1.1  christos    8 * 4,			/* %edx */
    381  1.1  christos    7 * 4,			/* %ebx */
    382  1.1  christos   -1,				/* %esp */
    383  1.1  christos    6 * 4,			/* %ebp */
    384  1.1  christos    5 * 4,			/* %esi */
    385  1.1  christos    4 * 4,			/* %edi */
    386  1.1  christos   13 * 4,			/* %eip */
    387  1.1  christos   15 * 4,			/* %eflags */
    388  1.1  christos   14 * 4,			/* %cs */
    389  1.1  christos   -1,				/* %ss */
    390  1.1  christos    3 * 4,			/* %ds */
    391  1.1  christos    2 * 4,			/* %es */
    392  1.1  christos    1 * 4,			/* %fs */
    393  1.1  christos    0 * 4			/* %gs */
    394  1.1  christos };
    395  1.1  christos 
    396  1.1  christos static struct trad_frame_cache *
    397  1.1  christos i386nbsd_trapframe_cache(frame_info_ptr this_frame, void **this_cache)
    398  1.1  christos {
    399  1.1  christos   struct trad_frame_cache *cache;
    400  1.1  christos   CORE_ADDR func, sp, addr, tmp;
    401  1.1  christos   ULONGEST cs;
    402  1.1  christos   const char *name;
    403  1.1  christos   int i;
    404  1.1  christos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    405  1.1  christos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    406  1.1  christos 
    407  1.1  christos   if (*this_cache)
    408  1.1  christos     return (struct trad_frame_cache *)*this_cache;
    409  1.1  christos 
    410  1.1  christos   cache = trad_frame_cache_zalloc (this_frame);
    411  1.1  christos   *this_cache = cache;
    412  1.1  christos 
    413  1.1  christos   func = get_frame_func (this_frame);
    414  1.1  christos   sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
    415  1.1  christos 
    416  1.1  christos   find_pc_partial_function (func, &name, NULL, NULL);
    417  1.1  christos   if (name && (strncmp (name, "Xintr", 5) == 0 ||
    418  1.1  christos                strncmp (name, "Xhandle", 7) == 0))
    419  1.1  christos     {
    420  1.1  christos       /* It's an interrupt frame. */
    421  1.1  christos       tmp = read_memory_unsigned_integer (sp + 4, 4, byte_order);
    422  1.1  christos       if (tmp < 15)
    423  1.1  christos         {
    424  1.1  christos           /* Reasonable value for 'ppl': already on interrupt stack. */
    425  1.1  christos           addr = sp + 8;
    426  1.1  christos         }
    427  1.1  christos       else
    428  1.1  christos         {
    429  1.1  christos           /* Switch to previous stack. */
    430  1.1  christos           addr = tmp + 4;
    431  1.1  christos         }
    432  1.1  christos     }
    433  1.1  christos   else
    434  1.1  christos     {
    435  1.1  christos       /* It's a trap frame. */
    436  1.1  christos       addr = sp + 4;
    437  1.1  christos     }
    438  1.1  christos 
    439  1.1  christos   for (i = 0; i < ARRAY_SIZE (i386nbsd_tf_reg_offset); i++)
    440  1.1  christos     if (i386nbsd_tf_reg_offset[i] != -1)
    441  1.1  christos       trad_frame_set_reg_addr (cache, i, addr + i386nbsd_tf_reg_offset[i]);
    442  1.1  christos 
    443  1.1  christos   /* Read %cs from trap frame.  */
    444  1.1  christos   addr += i386nbsd_tf_reg_offset[I386_CS_REGNUM];
    445  1.1  christos   cs = read_memory_unsigned_integer (addr, 4, byte_order);
    446  1.1  christos   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
    447  1.1  christos     {
    448  1.1  christos       /* Trap from user space; terminate backtrace.  */
    449  1.1  christos       trad_frame_set_id (cache, outer_frame_id);
    450  1.1  christos     }
    451  1.1  christos   else
    452  1.1  christos     {
    453  1.1  christos       /* Construct the frame ID using the function start.  */
    454  1.1  christos       trad_frame_set_id (cache, frame_id_build (sp + 8, func));
    455  1.1  christos     }
    456  1.1  christos 
    457  1.1  christos   return cache;
    458  1.1  christos }
    459  1.1  christos 
    460  1.1  christos static void
    461  1.1  christos i386nbsd_trapframe_this_id (frame_info_ptr this_frame,
    462  1.1  christos 			    void **this_cache, struct frame_id *this_id)
    463  1.1  christos {
    464  1.1  christos   struct trad_frame_cache *cache =
    465  1.1  christos     i386nbsd_trapframe_cache (this_frame, this_cache);
    466  1.1  christos 
    467  1.1  christos   trad_frame_get_id (cache, this_id);
    468  1.1  christos }
    469  1.1  christos 
    470  1.1  christos static struct value *
    471  1.1  christos i386nbsd_trapframe_prev_register (frame_info_ptr this_frame,
    472  1.1  christos 				  void **this_cache, int regnum)
    473  1.1  christos {
    474  1.1  christos   struct trad_frame_cache *cache =
    475  1.1  christos     i386nbsd_trapframe_cache (this_frame, this_cache);
    476  1.1  christos 
    477  1.1  christos   return trad_frame_get_register (cache, this_frame, regnum);
    478  1.1  christos }
    479  1.1  christos 
    480  1.1  christos static int
    481  1.1  christos i386nbsd_trapframe_sniffer (const struct frame_unwind *self,
    482  1.1  christos 			    frame_info_ptr this_frame,
    483  1.1  christos 			    void **this_prologue_cache)
    484  1.1  christos {
    485  1.1  christos   ULONGEST cs;
    486  1.1  christos   const char *name;
    487  1.1  christos 
    488  1.1  christos   /* Check Current Privilege Level and bail out if we're not executing
    489  1.1  christos      in kernel space.  */
    490  1.1  christos   cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM);
    491  1.1  christos   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
    492  1.1  christos     return 0;
    493  1.1  christos 
    494  1.1  christos 
    495  1.1  christos   find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
    496  1.1  christos   return (name && ((strcmp (name, "alltraps") == 0)
    497  1.1  christos 	        || (strcmp (name, "calltrap") == 0)
    498  1.1  christos 		|| (strcmp (name, "syscall1") == 0)
    499  1.1  christos 		|| (strcmp (name, "Xdoreti") == 0)
    500  1.1  christos 		|| (strncmp (name, "Xintr", 5) == 0)
    501  1.1  christos 		|| (strncmp (name, "Xhandle", 7) == 0)
    502  1.1  christos 		|| (strncmp (name, "Xpreempt", 8) == 0)
    503  1.1  christos 		|| (strncmp (name, "Xrecurse", 8) == 0)
    504  1.1  christos 		|| (strncmp (name, "Xresume", 7) == 0)
    505  1.1  christos 		|| (strncmp (name, "Xsoft", 5) == 0)
    506  1.1  christos 		|| (strncmp (name, "Xstray", 6) == 0)
    507  1.1  christos 		|| (strncmp (name, "Xsyscall", 8) == 0)
    508  1.1  christos 		|| (strncmp (name, "Xtrap", 5) == 0)
    509  1.1  christos 	    ));
    510  1.1  christos }
    511  1.1  christos 
    512  1.1  christos const struct frame_unwind i386nbsd_trapframe_unwind = {
    513  1.1  christos   /* FIXME: kettenis/20051219: This really is more like an interrupt
    514  1.1  christos      frame, but SIGTRAMP_FRAME would print <signal handler called>,
    515  1.1  christos      which really is not what we want here.  */
    516  1.1  christos   "i386 trapframe",
    517  1.1  christos   NORMAL_FRAME,
    518  1.1  christos   default_frame_unwind_stop_reason,
    519  1.1  christos   i386nbsd_trapframe_this_id,
    520  1.1  christos   i386nbsd_trapframe_prev_register,
    521  1.1  christos   NULL,
    522  1.1  christos   i386nbsd_trapframe_sniffer
    523  1.1  christos };
    524  1.1  christos 
    525  1.1  christos static void
    526  1.1  christos i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    527  1.1  christos {
    528  1.1  christos   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
    529  1.1  christos 
    530  1.1  christos   /* Obviously NetBSD is BSD-based.  */
    531  1.1  christos   i386bsd_init_abi (info, gdbarch);
    532  1.1  christos 
    533  1.1  christos   nbsd_init_abi (info, gdbarch);
    534  1.1  christos 
    535  1.1  christos   /* NetBSD has a different `struct reg'.  */
    536  1.1  christos   tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
    537  1.1  christos   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
    538  1.1  christos   tdep->sizeof_gregset = 16 * 4;
    539  1.1  christos 
    540  1.1  christos   /* NetBSD uses -freg-struct-return by default.  */
    541  1.1  christos   tdep->struct_return = reg_struct_return;
    542  1.1  christos 
    543  1.1  christos   /* NetBSD uses tramp_frame sniffers for signal trampolines.  */
    544  1.1  christos   tdep->sigcontext_addr= 0;
    545  1.1  christos   tdep->sigtramp_start = 0;
    546  1.1  christos   tdep->sigtramp_end = 0;
    547  1.1  christos   tdep->sigtramp_p = 0;
    548  1.1  christos   tdep->sc_reg_offset = 0;
    549  1.1  christos   tdep->sc_num_regs = 0;
    550  1.1  christos 
    551  1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
    552  1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
    553  1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
    554  1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
    555  1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
    556  1.1  christos 
    557  1.1  christos   /* Unwind kernel trap frames correctly.  */
    558  1.1  christos   frame_unwind_prepend_unwinder (gdbarch, &i386nbsd_trapframe_unwind);
    559  1.1  christos }
    560  1.1  christos 
    561  1.1  christos /* NetBSD ELF.  */
    562  1.1  christos 
    563  1.1  christos static void
    564  1.1  christos i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    565  1.1  christos {
    566  1.1  christos   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
    567  1.1  christos 
    568  1.1  christos   /* It's still NetBSD.  */
    569  1.1  christos   i386nbsd_init_abi (info, gdbarch);
    570  1.1  christos 
    571  1.1  christos   /* But ELF-based.  */
    572  1.1  christos   i386_elf_init_abi (info, gdbarch);
    573  1.1  christos 
    574  1.1  christos   /* NetBSD ELF uses SVR4-style shared libraries.  */
    575  1.1  christos   set_solib_svr4_fetch_link_map_offsets
    576  1.1  christos     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
    577  1.1  christos 
    578  1.1  christos   /* NetBSD ELF uses -fpcc-struct-return by default.  */
    579  1.1  christos   tdep->struct_return = pcc_struct_return;
    580  1.1  christos }
    581  1.1  christos 
    582  1.1  christos void _initialize_i386nbsd_tdep ();
    583  1.1  christos void
    584  1.1  christos _initialize_i386nbsd_tdep ()
    585  1.1  christos {
    586  1.1  christos   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
    587  1.1  christos 			  i386nbsdelf_init_abi);
    588                }
    589