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