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