GDB (API)
/home/stan/gdb/src/gdb/amd64fbsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for FreeBSD/amd64.
00002 
00003    Copyright (C) 2003-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "arch-utils.h"
00022 #include "frame.h"
00023 #include "gdbcore.h"
00024 #include "regcache.h"
00025 #include "osabi.h"
00026 
00027 #include "gdb_assert.h"
00028 #include "gdb_string.h"
00029 
00030 #include "amd64-tdep.h"
00031 #include "bsd-uthread.h"
00032 #include "solib-svr4.h"
00033 
00034 /* Support for signal handlers.  */
00035 
00036 /* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
00037    address of the associated sigcontext structure.  */
00038 
00039 static CORE_ADDR
00040 amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
00041 {
00042   CORE_ADDR sp;
00043 
00044   /* The `struct sigcontext' (which really is an `ucontext_t' on
00045      FreeBSD/amd64) lives at a fixed offset in the signal frame.  See
00046      <machine/sigframe.h>.  */
00047   sp = frame_unwind_register_unsigned (this_frame, AMD64_RSP_REGNUM);
00048   return sp + 16;
00049 }
00050 
00051 /* FreeBSD 5.1-RELEASE or later.  */
00052 
00053 /* Mapping between the general-purpose registers in `struct reg'
00054    format and GDB's register cache layout.
00055 
00056    Note that some registers are 32-bit, but since we're little-endian
00057    we get away with that.  */
00058 
00059 /* From <machine/reg.h>.  */
00060 static int amd64fbsd_r_reg_offset[] =
00061 {
00062   14 * 8,                       /* %rax */
00063   11 * 8,                       /* %rbx */
00064   13 * 8,                       /* %rcx */
00065   12 * 8,                       /* %rdx */
00066   9 * 8,                        /* %rsi */
00067   8 * 8,                        /* %rdi */
00068   10 * 8,                       /* %rbp */
00069   20 * 8,                       /* %rsp */
00070   7 * 8,                        /* %r8 ...  */
00071   6 * 8,
00072   5 * 8,
00073   4 * 8,
00074   3 * 8,
00075   2 * 8,
00076   1 * 8,
00077   0 * 8,                        /* ... %r15 */
00078   17 * 8,                       /* %rip */
00079   19 * 8,                       /* %eflags */
00080   18 * 8,                       /* %cs */
00081   21 * 8,                       /* %ss */
00082   -1,                           /* %ds */
00083   -1,                           /* %es */
00084   -1,                           /* %fs */
00085   -1                            /* %gs */
00086 };
00087 
00088 /* Location of the signal trampoline.  */
00089 CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0ULL;
00090 CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0ULL;
00091 
00092 /* From <machine/signal.h>.  */
00093 int amd64fbsd_sc_reg_offset[] =
00094 {
00095   24 + 6 * 8,                   /* %rax */
00096   24 + 7 * 8,                   /* %rbx */
00097   24 + 3 * 8,                   /* %rcx */
00098   24 + 2 * 8,                   /* %rdx */
00099   24 + 1 * 8,                   /* %rsi */
00100   24 + 0 * 8,                   /* %rdi */
00101   24 + 8 * 8,                   /* %rbp */
00102   24 + 22 * 8,                  /* %rsp */
00103   24 + 4 * 8,                   /* %r8 ...  */
00104   24 + 5 * 8,
00105   24 + 9 * 8,
00106   24 + 10 * 8,
00107   24 + 11 * 8,
00108   24 + 12 * 8,
00109   24 + 13 * 8,
00110   24 + 14 * 8,                  /* ... %r15 */
00111   24 + 19 * 8,                  /* %rip */
00112   24 + 21 * 8,                  /* %eflags */
00113   24 + 20 * 8,                  /* %cs */
00114   24 + 23 * 8,                  /* %ss */
00115   -1,                           /* %ds */
00116   -1,                           /* %es */
00117   -1,                           /* %fs */
00118   -1                            /* %gs */
00119 };
00120 
00121 /* From /usr/src/lib/libc/amd64/gen/_setjmp.S.  */
00122 static int amd64fbsd_jmp_buf_reg_offset[] =
00123 {
00124   -1,                           /* %rax */
00125   1 * 8,                        /* %rbx */
00126   -1,                           /* %rcx */
00127   -1,                           /* %rdx */
00128   -1,                           /* %rsi */
00129   -1,                           /* %rdi */
00130   3 * 8,                        /* %rbp */
00131   2 * 8,                        /* %rsp */
00132   -1,                           /* %r8 ...  */
00133   -1,
00134   -1,
00135   -1,                           /* ... %r11 */
00136   4 * 8,                        /* %r12 ...  */
00137   5 * 8,
00138   6 * 8,
00139   7 * 8,                        /* ... %r15 */
00140   0 * 8                         /* %rip */
00141 };
00142 
00143 static void
00144 amd64fbsd_supply_uthread (struct regcache *regcache,
00145                           int regnum, CORE_ADDR addr)
00146 {
00147   gdb_byte buf[8];
00148   int i;
00149 
00150   gdb_assert (regnum >= -1);
00151 
00152   for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
00153     {
00154       if (amd64fbsd_jmp_buf_reg_offset[i] != -1
00155           && (regnum == -1 || regnum == i))
00156         {
00157           read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
00158           regcache_raw_supply (regcache, i, buf);
00159         }
00160     }
00161 }
00162 
00163 static void
00164 amd64fbsd_collect_uthread (const struct regcache *regcache,
00165                            int regnum, CORE_ADDR addr)
00166 {
00167   gdb_byte buf[8];
00168   int i;
00169 
00170   gdb_assert (regnum >= -1);
00171 
00172   for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
00173     {
00174       if (amd64fbsd_jmp_buf_reg_offset[i] != -1
00175           && (regnum == -1 || regnum == i))
00176         {
00177           regcache_raw_collect (regcache, i, buf);
00178           write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
00179         }
00180     }
00181 }
00182 
00183 static void
00184 amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00185 {
00186   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00187 
00188   /* Obviously FreeBSD is BSD-based.  */
00189   i386bsd_init_abi (info, gdbarch);
00190 
00191   tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
00192   tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
00193   tdep->sizeof_gregset = 22 * 8;
00194 
00195   amd64_init_abi (info, gdbarch);
00196 
00197   tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
00198   tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
00199   tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
00200   tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
00201   tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
00202 
00203   /* FreeBSD provides a user-level threads implementation.  */
00204   bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread);
00205   bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread);
00206 
00207   /* FreeBSD uses SVR4-style shared libraries.  */
00208   set_solib_svr4_fetch_link_map_offsets
00209     (gdbarch, svr4_lp64_fetch_link_map_offsets);
00210 }
00211 
00212 
00213 /* Provide a prototype to silence -Wmissing-prototypes.  */
00214 void _initialize_amd64fbsd_tdep (void);
00215 
00216 void
00217 _initialize_amd64fbsd_tdep (void)
00218 {
00219   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
00220                           GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi);
00221 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines