gdb/i386fbsd-tdep.c - gdb

Global variables defined

Functions defined

Source code

  1. /* Target-dependent code for FreeBSD/i386.

  2.    Copyright (C) 2003-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "arch-utils.h"
  16. #include "gdbcore.h"
  17. #include "osabi.h"
  18. #include "regcache.h"

  19. #include "i386-tdep.h"
  20. #include "i387-tdep.h"
  21. #include "bsd-uthread.h"
  22. #include "fbsd-tdep.h"
  23. #include "solib-svr4.h"

  24. /* FreeBSD 3.0-RELEASE or later.  */

  25. /* From <machine/reg.h>.  */
  26. static int i386fbsd_r_reg_offset[] =
  27. {
  28.   9 * 4, 8 * 4, 7 * 4, 6 * 4,        /* %eax, %ecx, %edx, %ebx */
  29.   15 * 4, 4 * 4,                /* %esp, %ebp */
  30.   3 * 4, 2 * 4,                        /* %esi, %edi */
  31.   12 * 4, 14 * 4,                /* %eip, %eflags */
  32.   13 * 4, 16 * 4,                /* %cs, %ss */
  33.   1 * 4, 0 * 4, -1, -1                /* %ds, %es, %fs, %gs */
  34. };

  35. /* Sigtramp routine location.  */
  36. CORE_ADDR i386fbsd_sigtramp_start_addr = 0xbfbfdf20;
  37. CORE_ADDR i386fbsd_sigtramp_end_addr = 0xbfbfdff0;

  38. /* From <machine/signal.h>.  */
  39. int i386fbsd_sc_reg_offset[] =
  40. {
  41.   8 + 14 * 4,                        /* %eax */
  42.   8 + 13 * 4,                        /* %ecx */
  43.   8 + 12 * 4,                        /* %edx */
  44.   8 + 11 * 4,                        /* %ebx */
  45.   8 + 0 * 4,                    /* %esp */
  46.   8 + 1 * 4,                    /* %ebp */
  47.   8 + 10 * 4,                   /* %esi */
  48.   8 + 9 * 4,                    /* %edi */
  49.   8 + 3 * 4,                    /* %eip */
  50.   8 + 4 * 4,                    /* %eflags */
  51.   8 + 7 * 4,                    /* %cs */
  52.   8 + 8 * 4,                    /* %ss */
  53.   8 + 6 * 4,                    /* %ds */
  54.   8 + 5 * 4,                    /* %es */
  55.   8 + 15 * 4,                        /* %fs */
  56.   8 + 16 * 4                        /* %gs */
  57. };

  58. /* From /usr/src/lib/libc/i386/gen/_setjmp.S.  */
  59. static int i386fbsd_jmp_buf_reg_offset[] =
  60. {
  61.   -1,                                /* %eax */
  62.   -1,                                /* %ecx */
  63.   -1,                                /* %edx */
  64.   1 * 4,                        /* %ebx */
  65.   2 * 4,                        /* %esp */
  66.   3 * 4,                        /* %ebp */
  67.   4 * 4,                        /* %esi */
  68.   5 * 4,                        /* %edi */
  69.   0 * 4                                /* %eip */
  70. };

  71. static void
  72. i386fbsd_supply_uthread (struct regcache *regcache,
  73.                          int regnum, CORE_ADDR addr)
  74. {
  75.   gdb_byte buf[4];
  76.   int i;

  77.   gdb_assert (regnum >= -1);

  78.   for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
  79.     {
  80.       if (i386fbsd_jmp_buf_reg_offset[i] != -1
  81.           && (regnum == -1 || regnum == i))
  82.         {
  83.           read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
  84.           regcache_raw_supply (regcache, i, buf);
  85.         }
  86.     }
  87. }

  88. static void
  89. i386fbsd_collect_uthread (const struct regcache *regcache,
  90.                           int regnum, CORE_ADDR addr)
  91. {
  92.   gdb_byte buf[4];
  93.   int i;

  94.   gdb_assert (regnum >= -1);

  95.   for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
  96.     {
  97.       if (i386fbsd_jmp_buf_reg_offset[i] != -1
  98.           && (regnum == -1 || regnum == i))
  99.         {
  100.           regcache_raw_collect (regcache, i, buf);
  101.           write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
  102.         }
  103.     }
  104. }

  105. static void
  106. i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  107. {
  108.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  109.   /* Obviously FreeBSD is BSD-based.  */
  110.   i386bsd_init_abi (info, gdbarch);

  111.   /* FreeBSD has a different `struct reg', and reserves some space for
  112.      its FPU emulator in `struct fpreg'.  */
  113.   tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
  114.   tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
  115.   tdep->sizeof_gregset = 18 * 4;
  116.   tdep->sizeof_fpregset = 176;

  117.   /* FreeBSD uses -freg-struct-return by default.  */
  118.   tdep->struct_return = reg_struct_return;

  119.   /* FreeBSD uses a different memory layout.  */
  120.   tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
  121.   tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;

  122.   /* FreeBSD has a more complete `struct sigcontext'.  */
  123.   tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
  124.   tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);

  125.   /* FreeBSD provides a user-level threads implementation.  */
  126.   bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread);
  127.   bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread);
  128. }

  129. static void
  130. i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  131. {
  132.   /* It's almost identical to FreeBSD a.out.  */
  133.   i386fbsdaout_init_abi (info, gdbarch);

  134.   /* Except that it uses ELF.  */
  135.   i386_elf_init_abi (info, gdbarch);

  136.   /* FreeBSD ELF uses SVR4-style shared libraries.  */
  137.   set_solib_svr4_fetch_link_map_offsets
  138.     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
  139. }

  140. /* FreeBSD 4.0-RELEASE or later.  */

  141. /* From <machine/reg.h>.  */
  142. static int i386fbsd4_r_reg_offset[] =
  143. {
  144.   10 * 4, 9 * 4, 8 * 4, 7 * 4,        /* %eax, %ecx, %edx, %ebx */
  145.   16 * 4, 5 * 4,                /* %esp, %ebp */
  146.   4 * 4, 3 * 4,                        /* %esi, %edi */
  147.   13 * 4, 15 * 4,                /* %eip, %eflags */
  148.   14 * 4, 17 * 4,                /* %cs, %ss */
  149.   2 * 4, 1 * 4, 0 * 4, 18 * 4        /* %ds, %es, %fs, %gs */
  150. };

  151. /* From <machine/signal.h>.  */
  152. int i386fbsd4_sc_reg_offset[] =
  153. {
  154.   20 + 11 * 4,                        /* %eax */
  155.   20 + 10 * 4,                        /* %ecx */
  156.   20 + 9 * 4,                        /* %edx */
  157.   20 + 8 * 4,                        /* %ebx */
  158.   20 + 17 * 4,                        /* %esp */
  159.   20 + 6 * 4,                        /* %ebp */
  160.   20 + 5 * 4,                        /* %esi */
  161.   20 + 4 * 4,                        /* %edi */
  162.   20 + 14 * 4,                        /* %eip */
  163.   20 + 16 * 4,                        /* %eflags */
  164.   20 + 15 * 4,                        /* %cs */
  165.   20 + 18 * 4,                        /* %ss */
  166.   20 + 3 * 4,                        /* %ds */
  167.   20 + 2 * 4,                        /* %es */
  168.   20 + 1 * 4,                        /* %fs */
  169.   20 + 0 * 4                        /* %gs */
  170. };

  171. static void
  172. i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  173. {
  174.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  175.   /* Generic FreeBSD support. */
  176.   fbsd_init_abi (info, gdbarch);

  177.   /* Inherit stuff from older releases.  We assume that FreeBSD
  178.      4.0-RELEASE always uses ELF.  */
  179.   i386fbsd_init_abi (info, gdbarch);

  180.   /* FreeBSD 4.0 introduced a new `struct reg'.  */
  181.   tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
  182.   tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
  183.   tdep->sizeof_gregset = 19 * 4;

  184.   /* FreeBSD 4.0 introduced a new `struct sigcontext'.  */
  185.   tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
  186.   tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
  187. }


  188. /* Provide a prototype to silence -Wmissing-prototypes.  */
  189. void _initialize_i386fbsd_tdep (void);

  190. void
  191. _initialize_i386fbsd_tdep (void)
  192. {
  193.   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT,
  194.                           i386fbsdaout_init_abi);
  195.   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF,
  196.                           i386fbsd4_init_abi);
  197. }