GDB (API)
|
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 }