123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /* Target-dependent code for the GNU Hurd.
- Copyright (C) 2002-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "gdbcore.h"
- #include "osabi.h"
- #include "solib-svr4.h"
- #include "i386-tdep.h"
- /* Recognizing signal handler frames. */
- /* When the GNU/Hurd libc calls a signal handler, the return address points
- inside the trampoline assembly snippet.
- If the trampoline function name can not be identified, we resort to reading
- memory from the process in order to identify it. */
- static const gdb_byte gnu_sigtramp_code[] =
- {
- /* rpc_wait_trampoline: */
- 0xb8, 0xe7, 0xff, 0xff, 0xff, /* mov $-25,%eax */
- 0x9a, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, /* lcall $7,$0 */
- 0x89, 0x01, /* movl %eax, (%ecx) */
- 0x89, 0xdc, /* movl %ebx, %esp */
- /* trampoline: */
- 0xff, 0xd2, /* call *%edx */
- /* RA HERE */
- 0x83, 0xc4, 0x0c, /* addl $12, %esp */
- 0xc3, /* ret */
- /* firewall: */
- 0xf4, /* hlt */
- };
- #define GNU_SIGTRAMP_LEN (sizeof gnu_sigtramp_code)
- #define GNU_SIGTRAMP_TAIL 5 /* length of tail after RA */
- /* If THIS_FRAME is a sigtramp routine, return the address of the
- start of the routine. Otherwise, return 0. */
- static CORE_ADDR
- i386_gnu_sigtramp_start (struct frame_info *this_frame)
- {
- CORE_ADDR pc = get_frame_pc (this_frame);
- gdb_byte buf[GNU_SIGTRAMP_LEN];
- if (!safe_frame_unwind_memory (this_frame,
- pc + GNU_SIGTRAMP_TAIL - GNU_SIGTRAMP_LEN,
- buf))
- return 0;
- if (memcmp (buf, gnu_sigtramp_code, GNU_SIGTRAMP_LEN) != 0)
- return 0;
- return pc;
- }
- /* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp
- routine. */
- static int
- i386_gnu_sigtramp_p (struct frame_info *this_frame)
- {
- CORE_ADDR pc = get_frame_pc (this_frame);
- const char *name;
- find_pc_partial_function (pc, &name, NULL, NULL);
- /* If we have a NAME, we can check for the trampoline function */
- if (name != NULL && strcmp (name, "trampoline") == 0)
- return 1;
- return i386_gnu_sigtramp_start (this_frame) != 0;
- }
- /* Offset to sc_i386_thread_state in sigcontext, from <bits/sigcontext.h>. */
- #define I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET 20
- /* Assuming THIS_FRAME is a GNU/Linux sigtramp routine, return the
- address of the associated sigcontext structure. */
- static CORE_ADDR
- i386_gnu_sigcontext_addr (struct frame_info *this_frame)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR pc;
- CORE_ADDR sp;
- gdb_byte buf[4];
- get_frame_register (this_frame, I386_ESP_REGNUM, buf);
- sp = extract_unsigned_integer (buf, 4, byte_order);
- pc = i386_gnu_sigtramp_start (this_frame);
- if (pc)
- {
- CORE_ADDR sigcontext_addr;
- /* The sigcontext structure address is passed as the third argument to
- the signal handler. */
- read_memory (sp + 8, buf, 4);
- sigcontext_addr = extract_unsigned_integer (buf, 4, byte_order);
- return sigcontext_addr + I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET;
- }
- error (_("Couldn't recognize signal trampoline."));
- return 0;
- }
- /* Mapping between the general-purpose registers in `struct
- sigcontext' format (starting at sc_i386_thread_state)
- and GDB's register cache layout. */
- /* From <bits/sigcontext.h>. */
- static int i386_gnu_sc_reg_offset[] =
- {
- 11 * 4, /* %eax */
- 10 * 4, /* %ecx */
- 9 * 4, /* %edx */
- 8 * 4, /* %ebx */
- 7 * 4, /* %esp */
- 6 * 4, /* %ebp */
- 5 * 4, /* %esi */
- 4 * 4, /* %edi */
- 12 * 4, /* %eip */
- 14 * 4, /* %eflags */
- 13 * 4, /* %cs */
- 16 * 4, /* %ss */
- 3 * 4, /* %ds */
- 2 * 4, /* %es */
- 1 * 4, /* %fs */
- 0 * 4 /* %gs */
- };
- /* From <sys/ucontext.h>. */
- static int i386gnu_gregset_reg_offset[] =
- {
- 11 * 4, /* %eax */
- 10 * 4, /* %ecx */
- 9 * 4, /* %edx */
- 8 * 4, /* %ebx */
- 17 * 4, /* %uesp */
- 6 * 4, /* %ebp */
- 5 * 4, /* %esi */
- 4 * 4, /* %edi */
- 14 * 4, /* %eip */
- 16 * 4, /* %efl */
- 15 * 4, /* %cs */
- 18 * 4, /* %ss */
- 3 * 4, /* %ds */
- 2 * 4, /* %es */
- 1 * 4, /* %fs */
- 0 * 4, /* %gs */
- };
- static void
- i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- /* GNU uses ELF. */
- i386_elf_init_abi (info, gdbarch);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
- tdep->gregset_reg_offset = i386gnu_gregset_reg_offset;
- tdep->gregset_num_regs = ARRAY_SIZE (i386gnu_gregset_reg_offset);
- tdep->sizeof_gregset = 19 * 4;
- tdep->jb_pc_offset = 20; /* From <bits/setjmp.h>. */
- tdep->sigtramp_p = i386_gnu_sigtramp_p;
- tdep->sigcontext_addr = i386_gnu_sigcontext_addr;
- tdep->sc_reg_offset = i386_gnu_sc_reg_offset;
- tdep->sc_num_regs = ARRAY_SIZE (i386_gnu_sc_reg_offset);
- }
- void _initialize_i386gnu_tdep ();
- void
- _initialize_i386gnu_tdep ()
- {
- gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HURD, i386gnu_init_abi);
- }
|