1699b0f92Schristos /* Target-dependent code for the GNU Hurd. 2*6881a400Schristos Copyright (C) 2002-2023 Free Software Foundation, Inc. 3699b0f92Schristos 4699b0f92Schristos This file is part of GDB. 5699b0f92Schristos 6699b0f92Schristos This program is free software; you can redistribute it and/or modify 7699b0f92Schristos it under the terms of the GNU General Public License as published by 8699b0f92Schristos the Free Software Foundation; either version 3 of the License, or 9699b0f92Schristos (at your option) any later version. 10699b0f92Schristos 11699b0f92Schristos This program is distributed in the hope that it will be useful, 12699b0f92Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 13699b0f92Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14699b0f92Schristos GNU General Public License for more details. 15699b0f92Schristos 16699b0f92Schristos You should have received a copy of the GNU General Public License 17699b0f92Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18699b0f92Schristos 19699b0f92Schristos #include "defs.h" 207d62b00eSchristos #include "gdbcore.h" 21699b0f92Schristos #include "osabi.h" 22699b0f92Schristos #include "solib-svr4.h" 23699b0f92Schristos 24699b0f92Schristos #include "i386-tdep.h" 25699b0f92Schristos 267d62b00eSchristos /* Recognizing signal handler frames. */ 277d62b00eSchristos 287d62b00eSchristos /* When the GNU/Hurd libc calls a signal handler, the return address points 297d62b00eSchristos inside the trampoline assembly snippet. 307d62b00eSchristos 317d62b00eSchristos If the trampoline function name can not be identified, we resort to reading 327d62b00eSchristos memory from the process in order to identify it. */ 337d62b00eSchristos 347d62b00eSchristos static const gdb_byte gnu_sigtramp_code[] = 357d62b00eSchristos { 367d62b00eSchristos /* rpc_wait_trampoline: */ 377d62b00eSchristos 0xb8, 0xe7, 0xff, 0xff, 0xff, /* mov $-25,%eax */ 387d62b00eSchristos 0x9a, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, /* lcall $7,$0 */ 397d62b00eSchristos 0x89, 0x01, /* movl %eax, (%ecx) */ 407d62b00eSchristos 0x89, 0xdc, /* movl %ebx, %esp */ 417d62b00eSchristos 427d62b00eSchristos /* trampoline: */ 437d62b00eSchristos 0xff, 0xd2, /* call *%edx */ 447d62b00eSchristos /* RA HERE */ 457d62b00eSchristos 0x83, 0xc4, 0x0c, /* addl $12, %esp */ 467d62b00eSchristos 0xc3, /* ret */ 477d62b00eSchristos 487d62b00eSchristos /* firewall: */ 497d62b00eSchristos 0xf4, /* hlt */ 507d62b00eSchristos }; 517d62b00eSchristos 527d62b00eSchristos #define GNU_SIGTRAMP_LEN (sizeof gnu_sigtramp_code) 537d62b00eSchristos #define GNU_SIGTRAMP_TAIL 5 /* length of tail after RA */ 547d62b00eSchristos 557d62b00eSchristos /* If THIS_FRAME is a sigtramp routine, return the address of the 567d62b00eSchristos start of the routine. Otherwise, return 0. */ 577d62b00eSchristos 587d62b00eSchristos static CORE_ADDR 59*6881a400Schristos i386_gnu_sigtramp_start (frame_info_ptr this_frame) 607d62b00eSchristos { 617d62b00eSchristos CORE_ADDR pc = get_frame_pc (this_frame); 627d62b00eSchristos gdb_byte buf[GNU_SIGTRAMP_LEN]; 637d62b00eSchristos 647d62b00eSchristos if (!safe_frame_unwind_memory (this_frame, 657d62b00eSchristos pc + GNU_SIGTRAMP_TAIL - GNU_SIGTRAMP_LEN, 66*6881a400Schristos buf)) 677d62b00eSchristos return 0; 687d62b00eSchristos 697d62b00eSchristos if (memcmp (buf, gnu_sigtramp_code, GNU_SIGTRAMP_LEN) != 0) 707d62b00eSchristos return 0; 717d62b00eSchristos 727d62b00eSchristos return pc; 737d62b00eSchristos } 747d62b00eSchristos 757d62b00eSchristos /* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp 767d62b00eSchristos routine. */ 777d62b00eSchristos 787d62b00eSchristos static int 79*6881a400Schristos i386_gnu_sigtramp_p (frame_info_ptr this_frame) 807d62b00eSchristos { 817d62b00eSchristos CORE_ADDR pc = get_frame_pc (this_frame); 827d62b00eSchristos const char *name; 837d62b00eSchristos 847d62b00eSchristos find_pc_partial_function (pc, &name, NULL, NULL); 857d62b00eSchristos 867d62b00eSchristos /* If we have a NAME, we can check for the trampoline function */ 877d62b00eSchristos if (name != NULL && strcmp (name, "trampoline") == 0) 887d62b00eSchristos return 1; 897d62b00eSchristos 907d62b00eSchristos return i386_gnu_sigtramp_start (this_frame) != 0; 917d62b00eSchristos } 927d62b00eSchristos 937d62b00eSchristos /* Offset to sc_i386_thread_state in sigcontext, from <bits/sigcontext.h>. */ 947d62b00eSchristos #define I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET 20 957d62b00eSchristos 967d62b00eSchristos /* Assuming THIS_FRAME is a GNU/Linux sigtramp routine, return the 977d62b00eSchristos address of the associated sigcontext structure. */ 987d62b00eSchristos 997d62b00eSchristos static CORE_ADDR 100*6881a400Schristos i386_gnu_sigcontext_addr (frame_info_ptr this_frame) 1017d62b00eSchristos { 1027d62b00eSchristos struct gdbarch *gdbarch = get_frame_arch (this_frame); 1037d62b00eSchristos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 1047d62b00eSchristos CORE_ADDR pc; 1057d62b00eSchristos CORE_ADDR sp; 1067d62b00eSchristos gdb_byte buf[4]; 1077d62b00eSchristos 1087d62b00eSchristos get_frame_register (this_frame, I386_ESP_REGNUM, buf); 1097d62b00eSchristos sp = extract_unsigned_integer (buf, 4, byte_order); 1107d62b00eSchristos 1117d62b00eSchristos pc = i386_gnu_sigtramp_start (this_frame); 1127d62b00eSchristos if (pc) 1137d62b00eSchristos { 1147d62b00eSchristos CORE_ADDR sigcontext_addr; 1157d62b00eSchristos 1167d62b00eSchristos /* The sigcontext structure address is passed as the third argument to 1177d62b00eSchristos the signal handler. */ 1187d62b00eSchristos read_memory (sp + 8, buf, 4); 1197d62b00eSchristos sigcontext_addr = extract_unsigned_integer (buf, 4, byte_order); 1207d62b00eSchristos return sigcontext_addr + I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET; 1217d62b00eSchristos } 1227d62b00eSchristos 1237d62b00eSchristos error (_("Couldn't recognize signal trampoline.")); 1247d62b00eSchristos return 0; 1257d62b00eSchristos } 1267d62b00eSchristos 1277d62b00eSchristos /* Mapping between the general-purpose registers in `struct 1287d62b00eSchristos sigcontext' format (starting at sc_i386_thread_state) 1297d62b00eSchristos and GDB's register cache layout. */ 1307d62b00eSchristos 1317d62b00eSchristos /* From <bits/sigcontext.h>. */ 1327d62b00eSchristos static int i386_gnu_sc_reg_offset[] = 1337d62b00eSchristos { 1347d62b00eSchristos 11 * 4, /* %eax */ 1357d62b00eSchristos 10 * 4, /* %ecx */ 1367d62b00eSchristos 9 * 4, /* %edx */ 1377d62b00eSchristos 8 * 4, /* %ebx */ 1387d62b00eSchristos 7 * 4, /* %esp */ 1397d62b00eSchristos 6 * 4, /* %ebp */ 1407d62b00eSchristos 5 * 4, /* %esi */ 1417d62b00eSchristos 4 * 4, /* %edi */ 1427d62b00eSchristos 12 * 4, /* %eip */ 1437d62b00eSchristos 14 * 4, /* %eflags */ 1447d62b00eSchristos 13 * 4, /* %cs */ 1457d62b00eSchristos 16 * 4, /* %ss */ 1467d62b00eSchristos 3 * 4, /* %ds */ 1477d62b00eSchristos 2 * 4, /* %es */ 1487d62b00eSchristos 1 * 4, /* %fs */ 1497d62b00eSchristos 0 * 4 /* %gs */ 1507d62b00eSchristos }; 1517d62b00eSchristos 152699b0f92Schristos /* From <sys/ucontext.h>. */ 153699b0f92Schristos static int i386gnu_gregset_reg_offset[] = 154699b0f92Schristos { 155699b0f92Schristos 11 * 4, /* %eax */ 156699b0f92Schristos 10 * 4, /* %ecx */ 157699b0f92Schristos 9 * 4, /* %edx */ 158699b0f92Schristos 8 * 4, /* %ebx */ 159699b0f92Schristos 17 * 4, /* %uesp */ 160699b0f92Schristos 6 * 4, /* %ebp */ 161699b0f92Schristos 5 * 4, /* %esi */ 162699b0f92Schristos 4 * 4, /* %edi */ 163699b0f92Schristos 14 * 4, /* %eip */ 164699b0f92Schristos 16 * 4, /* %efl */ 165699b0f92Schristos 15 * 4, /* %cs */ 166699b0f92Schristos 18 * 4, /* %ss */ 167699b0f92Schristos 3 * 4, /* %ds */ 168699b0f92Schristos 2 * 4, /* %es */ 169699b0f92Schristos 1 * 4, /* %fs */ 170699b0f92Schristos 0 * 4, /* %gs */ 171699b0f92Schristos }; 172699b0f92Schristos 173699b0f92Schristos static void 174699b0f92Schristos i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 175699b0f92Schristos { 176*6881a400Schristos i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); 177699b0f92Schristos 178699b0f92Schristos /* GNU uses ELF. */ 179699b0f92Schristos i386_elf_init_abi (info, gdbarch); 180699b0f92Schristos 181699b0f92Schristos set_solib_svr4_fetch_link_map_offsets 182699b0f92Schristos (gdbarch, svr4_ilp32_fetch_link_map_offsets); 183699b0f92Schristos 184699b0f92Schristos tdep->gregset_reg_offset = i386gnu_gregset_reg_offset; 185699b0f92Schristos tdep->gregset_num_regs = ARRAY_SIZE (i386gnu_gregset_reg_offset); 186699b0f92Schristos tdep->sizeof_gregset = 19 * 4; 187699b0f92Schristos 188699b0f92Schristos tdep->jb_pc_offset = 20; /* From <bits/setjmp.h>. */ 1897d62b00eSchristos 1907d62b00eSchristos tdep->sigtramp_p = i386_gnu_sigtramp_p; 1917d62b00eSchristos tdep->sigcontext_addr = i386_gnu_sigcontext_addr; 1927d62b00eSchristos tdep->sc_reg_offset = i386_gnu_sc_reg_offset; 1937d62b00eSchristos tdep->sc_num_regs = ARRAY_SIZE (i386_gnu_sc_reg_offset); 194699b0f92Schristos } 195699b0f92Schristos 1967d62b00eSchristos void _initialize_i386gnu_tdep (); 197699b0f92Schristos void 1987d62b00eSchristos _initialize_i386gnu_tdep () 199699b0f92Schristos { 200699b0f92Schristos gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HURD, i386gnu_init_abi); 201699b0f92Schristos } 202