GDB (API)
|
00001 /* Target-dependent code for NetBSD/i386. 00002 00003 Copyright (C) 1988-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 "regset.h" 00026 #include "osabi.h" 00027 #include "symtab.h" 00028 #include "trad-frame.h" 00029 #include "tramp-frame.h" 00030 00031 #include "gdb_assert.h" 00032 #include "gdb_string.h" 00033 00034 #include "i386-tdep.h" 00035 #include "i387-tdep.h" 00036 #include "nbsd-tdep.h" 00037 #include "solib-svr4.h" 00038 00039 /* From <machine/reg.h>. */ 00040 static int i386nbsd_r_reg_offset[] = 00041 { 00042 0 * 4, /* %eax */ 00043 1 * 4, /* %ecx */ 00044 2 * 4, /* %edx */ 00045 3 * 4, /* %ebx */ 00046 4 * 4, /* %esp */ 00047 5 * 4, /* %ebp */ 00048 6 * 4, /* %esi */ 00049 7 * 4, /* %edi */ 00050 8 * 4, /* %eip */ 00051 9 * 4, /* %eflags */ 00052 10 * 4, /* %cs */ 00053 11 * 4, /* %ss */ 00054 12 * 4, /* %ds */ 00055 13 * 4, /* %es */ 00056 14 * 4, /* %fs */ 00057 15 * 4 /* %gs */ 00058 }; 00059 00060 /* From <machine/signal.h>. */ 00061 int i386nbsd_sc_reg_offset[] = 00062 { 00063 10 * 4, /* %eax */ 00064 9 * 4, /* %ecx */ 00065 8 * 4, /* %edx */ 00066 7 * 4, /* %ebx */ 00067 14 * 4, /* %esp */ 00068 6 * 4, /* %ebp */ 00069 5 * 4, /* %esi */ 00070 4 * 4, /* %edi */ 00071 11 * 4, /* %eip */ 00072 13 * 4, /* %eflags */ 00073 12 * 4, /* %cs */ 00074 15 * 4, /* %ss */ 00075 3 * 4, /* %ds */ 00076 2 * 4, /* %es */ 00077 1 * 4, /* %fs */ 00078 0 * 4 /* %gs */ 00079 }; 00080 00081 /* From <machine/mcontext.h>. */ 00082 int i386nbsd_mc_reg_offset[] = 00083 { 00084 11 * 4, /* %eax */ 00085 10 * 4, /* %ecx */ 00086 9 * 4, /* %edx */ 00087 8 * 4, /* %ebx */ 00088 7 * 4, /* %esp */ 00089 6 * 4, /* %ebp */ 00090 5 * 4, /* %esi */ 00091 4 * 4, /* %edi */ 00092 14 * 4, /* %eip */ 00093 16 * 4, /* %eflags */ 00094 15 * 4, /* %cs */ 00095 18 * 4, /* %ss */ 00096 3 * 4, /* %ds */ 00097 2 * 4, /* %es */ 00098 1 * 4, /* %fs */ 00099 0 * 4 /* %gs */ 00100 }; 00101 00102 static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *, 00103 struct frame_info *, 00104 struct trad_frame_cache *, 00105 CORE_ADDR); 00106 00107 static const struct tramp_frame i386nbsd_sigtramp_sc16 = 00108 { 00109 SIGTRAMP_FRAME, 00110 1, 00111 { 00112 { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 }, 00113 /* leal 0x10(%esp), %eax */ 00114 { 0x50, -1 }, /* pushl %eax */ 00115 { 0x50, -1 }, /* pushl %eax */ 00116 { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, 00117 /* movl $0x127, %eax # __sigreturn14 */ 00118 { 0xcd, -1 }, { 0x80, -1}, 00119 /* int $0x80 */ 00120 { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, 00121 /* movl $0x1, %eax # exit */ 00122 { 0xcd, -1 }, { 0x80, -1}, 00123 /* int $0x80 */ 00124 { TRAMP_SENTINEL_INSN, -1 } 00125 }, 00126 i386nbsd_sigtramp_cache_init 00127 }; 00128 00129 static const struct tramp_frame i386nbsd_sigtramp_sc2 = 00130 { 00131 SIGTRAMP_FRAME, 00132 1, 00133 { 00134 { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 }, 00135 /* leal 0x0c(%esp), %eax */ 00136 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00137 /* movl %eax, 0x4(%esp) */ 00138 { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, 00139 /* movl $0x127, %eax # __sigreturn14 */ 00140 { 0xcd, -1 }, { 0x80, -1}, 00141 /* int $0x80 */ 00142 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00143 /* movl %eax, 0x4(%esp) */ 00144 { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, 00145 /* movl $0x1, %eax */ 00146 { 0xcd, -1 }, { 0x80, -1}, 00147 /* int $0x80 */ 00148 { TRAMP_SENTINEL_INSN, -1 } 00149 }, 00150 i386nbsd_sigtramp_cache_init 00151 }; 00152 00153 static const struct tramp_frame i386nbsd_sigtramp_si2 = 00154 { 00155 SIGTRAMP_FRAME, 00156 1, 00157 { 00158 { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 }, 00159 /* movl 8(%esp),%eax */ 00160 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00161 /* movl %eax, 0x4(%esp) */ 00162 { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00163 /* movl $0x134, %eax # setcontext */ 00164 { 0xcd, -1 }, { 0x80, -1 }, 00165 /* int $0x80 */ 00166 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00167 /* movl %eax, 0x4(%esp) */ 00168 { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00169 /* movl $0x1, %eax */ 00170 { 0xcd, -1 }, { 0x80, -1 }, 00171 /* int $0x80 */ 00172 { TRAMP_SENTINEL_INSN, -1 } 00173 }, 00174 i386nbsd_sigtramp_cache_init 00175 }; 00176 00177 static const struct tramp_frame i386nbsd_sigtramp_si31 = 00178 { 00179 SIGTRAMP_FRAME, 00180 1, 00181 { 00182 { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, 00183 { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00184 /* leal 0x8c(%esp), %eax */ 00185 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00186 /* movl %eax, 0x4(%esp) */ 00187 { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00188 /* movl $0x134, %eax # setcontext */ 00189 { 0xcd, -1 }, { 0x80, -1}, 00190 /* int $0x80 */ 00191 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00192 /* movl %eax, 0x4(%esp) */ 00193 { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, 00194 /* movl $0x1, %eax */ 00195 { 0xcd, -1 }, { 0x80, -1}, 00196 /* int $0x80 */ 00197 { TRAMP_SENTINEL_INSN, -1 } 00198 }, 00199 i386nbsd_sigtramp_cache_init 00200 }; 00201 00202 static const struct tramp_frame i386nbsd_sigtramp_si4 = 00203 { 00204 SIGTRAMP_FRAME, 00205 1, 00206 { 00207 { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, 00208 { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00209 /* leal 0x8c(%esp), %eax */ 00210 { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00211 /* movl %eax, 0x4(%esp) */ 00212 { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, 00213 /* movl $0x134, %eax # setcontext */ 00214 { 0xcd, -1 }, { 0x80, -1}, 00215 /* int $0x80 */ 00216 { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, 00217 { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, 00218 /* movl $0xffffffff,0x4(%esp) */ 00219 { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, 00220 /* movl $0x1, %eax */ 00221 { 0xcd, -1 }, { 0x80, -1}, 00222 /* int $0x80 */ 00223 { TRAMP_SENTINEL_INSN, -1 } 00224 }, 00225 i386nbsd_sigtramp_cache_init 00226 }; 00227 00228 static void 00229 i386nbsd_sigtramp_cache_init (const struct tramp_frame *self, 00230 struct frame_info *this_frame, 00231 struct trad_frame_cache *this_cache, 00232 CORE_ADDR func) 00233 { 00234 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00235 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00236 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00237 CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); 00238 CORE_ADDR base; 00239 int *reg_offset; 00240 int num_regs; 00241 int i; 00242 00243 if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2) 00244 { 00245 reg_offset = i386nbsd_sc_reg_offset; 00246 num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset); 00247 00248 /* Read in the sigcontext address. */ 00249 base = read_memory_unsigned_integer (sp + 8, 4, byte_order); 00250 } 00251 else 00252 { 00253 reg_offset = i386nbsd_mc_reg_offset; 00254 num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset); 00255 00256 /* Read in the ucontext address. */ 00257 base = read_memory_unsigned_integer (sp + 8, 4, byte_order); 00258 /* offsetof(ucontext_t, uc_mcontext) == 36 */ 00259 base += 36; 00260 } 00261 00262 for (i = 0; i < num_regs; i++) 00263 if (reg_offset[i] != -1) 00264 trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); 00265 00266 /* Construct the frame ID using the function start. */ 00267 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 00268 } 00269 00270 00271 static void 00272 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00273 { 00274 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00275 00276 /* Obviously NetBSD is BSD-based. */ 00277 i386bsd_init_abi (info, gdbarch); 00278 00279 /* NetBSD has a different `struct reg'. */ 00280 tdep->gregset_reg_offset = i386nbsd_r_reg_offset; 00281 tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset); 00282 tdep->sizeof_gregset = 16 * 4; 00283 00284 /* NetBSD uses -freg-struct-return by default. */ 00285 tdep->struct_return = reg_struct_return; 00286 00287 /* NetBSD uses tramp_frame sniffers for signal trampolines. */ 00288 tdep->sigcontext_addr= 0; 00289 tdep->sigtramp_start = 0; 00290 tdep->sigtramp_end = 0; 00291 tdep->sigtramp_p = 0; 00292 tdep->sc_reg_offset = 0; 00293 tdep->sc_num_regs = 0; 00294 00295 tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16); 00296 tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2); 00297 tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2); 00298 tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31); 00299 tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4); 00300 } 00301 00302 /* NetBSD ELF. */ 00303 00304 static void 00305 i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00306 { 00307 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00308 00309 /* It's still NetBSD. */ 00310 i386nbsd_init_abi (info, gdbarch); 00311 00312 /* But ELF-based. */ 00313 i386_elf_init_abi (info, gdbarch); 00314 00315 /* NetBSD ELF uses SVR4-style shared libraries. */ 00316 set_solib_svr4_fetch_link_map_offsets 00317 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 00318 00319 /* NetBSD ELF uses -fpcc-struct-return by default. */ 00320 tdep->struct_return = pcc_struct_return; 00321 } 00322 00323 /* Provide a prototype to silence -Wmissing-prototypes. */ 00324 extern initialize_file_ftype _initialize_i386nbsd_tdep; 00325 00326 void 00327 _initialize_i386nbsd_tdep (void) 00328 { 00329 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF, 00330 i386nbsdelf_init_abi); 00331 }