X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Flinux-x86-low.c;h=047eb1376abc74e1984a9e068ecde92e05ae127d;hb=7697afb662b2ffd67d044209d6d807a8e21dfed9;hp=dd9538ad66eba9bedbb7699431f12ceabed7522a;hpb=61baf725eca99af2569262d10aca03dcde2698f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index dd9538ad66..047eb1376a 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -1,6 +1,6 @@ /* GNU/Linux/x86-64 specific low level interface, for the remote server for GDB. - Copyright (C) 2002-2017 Free Software Foundation, Inc. + Copyright (C) 2002-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -24,7 +24,7 @@ #include "linux-low.h" #include "i387-fp.h" #include "x86-low.h" -#include "x86-xstate.h" +#include "gdbsupport/x86-xstate.h" #include "nat/gdb_ptrace.h" #ifdef __x86_64__ @@ -38,7 +38,7 @@ #include "elf/common.h" #endif -#include "agent.h" +#include "gdbsupport/agent.h" #include "tdesc.h" #include "tracepoint.h" #include "ax.h" @@ -72,7 +72,6 @@ static const char *xmltarget_amd64_linux_no_xml = "@\ #include #include -#include "nat/gdb_ptrace.h" #include #ifndef PTRACE_GET_THREAD_AREA @@ -133,6 +132,11 @@ static const int x86_64_regmap[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, ORIG_RAX * 8, +#ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE + 21 * 8, 22 * 8, +#else + -1, -1, +#endif -1, -1, -1, -1, /* MPX registers BND0 ... BND3. */ -1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */ -1, -1, -1, -1, -1, -1, -1, -1, /* xmm16 ... xmm31 (AVX512) */ @@ -143,7 +147,8 @@ static const int x86_64_regmap[] = -1, -1, -1, -1, -1, -1, -1, -1, /* zmm0 ... zmm31 (AVX512) */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 + -1, -1, -1, -1, -1, -1, -1, -1, + -1 /* pkru */ }; #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0])) @@ -249,7 +254,7 @@ x86_get_thread_area (int lwpid, CORE_ADDR *addr) #endif { - struct lwp_info *lwp = find_lwp_pid (pid_to_ptid (lwpid)); + struct lwp_info *lwp = find_lwp_pid (ptid_t (lwpid)); struct thread_info *thr = get_lwp_thread (lwp); struct regcache *regcache = get_thread_regcache (thr, 1); unsigned int desc[4]; @@ -306,6 +311,20 @@ x86_fill_gregset (struct regcache *regcache, void *buf) for (i = 0; i < X86_64_NUM_REGS; i++) if (x86_64_regmap[i] != -1) collect_register (regcache, i, ((char *) buf) + x86_64_regmap[i]); + +#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE + { + unsigned long base; + int lwpid = lwpid_of (current_thread); + + collect_register_by_name (regcache, "fs_base", &base); + ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_SET_FS); + + collect_register_by_name (regcache, "gs_base", &base); + ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_SET_GS); + } +#endif + return; } @@ -319,6 +338,21 @@ x86_fill_gregset (struct regcache *regcache, void *buf) collect_register_by_name (regcache, "orig_eax", ((char *) buf) + ORIG_EAX * REGSIZE); + +#ifdef __x86_64__ + /* Sign extend EAX value to avoid potential syscall restart + problems. + + See amd64_linux_collect_native_gregset() in gdb/amd64-linux-nat.c + for a detailed explanation. */ + if (register_size (regcache->tdesc, 0) == 4) + { + void *ptr = ((gdb_byte *) buf + + i386_regmap[find_regno (regcache->tdesc, "eax")]); + + *(int64_t *) ptr = *(int32_t *) ptr; + } +#endif } static void @@ -332,6 +366,19 @@ x86_store_gregset (struct regcache *regcache, const void *buf) for (i = 0; i < X86_64_NUM_REGS; i++) if (x86_64_regmap[i] != -1) supply_register (regcache, i, ((char *) buf) + x86_64_regmap[i]); + +#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE + { + unsigned long base; + int lwpid = lwpid_of (current_thread); + + if (ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_GET_FS) == 0) + supply_register_by_name (regcache, "fs_base", &base); + + if (ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_GET_GS) == 0) + supply_register_by_name (regcache, "gs_base", &base); + } +#endif return; } #endif @@ -584,6 +631,14 @@ x86_linux_new_process (void) return info; } +/* Called when a process is being deleted. */ + +static void +x86_linux_delete_process (struct arch_process_info *info) +{ + xfree (info); +} + /* Target routine for linux_new_fork. */ static void @@ -724,7 +779,7 @@ x86_linux_read_description (void) { have_ptrace_getfpxregs = 0; have_ptrace_getregset = 0; - return tdesc_i386_mmx_linux; + return i386_linux_read_description (X86_XSTATE_X87); } else have_ptrace_getfpxregs = 1; @@ -776,7 +831,7 @@ x86_linux_read_description (void) /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ xcr0_features = (have_ptrace_getregset - && (xcr0 & X86_XSTATE_ALL_MASK)); + && (xcr0 & X86_XSTATE_ALL_MASK)); if (xcr0_features) x86_xcr0 = xcr0; @@ -784,109 +839,35 @@ x86_linux_read_description (void) if (machine == EM_X86_64) { #ifdef __x86_64__ - if (is_elf64) - { - if (xcr0_features) - { - switch (xcr0 & X86_XSTATE_ALL_MASK) - { - case X86_XSTATE_AVX512_MASK: - return tdesc_amd64_avx512_linux; - - case X86_XSTATE_AVX_MPX_MASK: - return tdesc_amd64_avx_mpx_linux; + const target_desc *tdesc = NULL; - case X86_XSTATE_MPX_MASK: - return tdesc_amd64_mpx_linux; - - case X86_XSTATE_AVX_MASK: - return tdesc_amd64_avx_linux; - - default: - return tdesc_amd64_linux; - } - } - else - return tdesc_amd64_linux; - } - else + if (xcr0_features) { - if (xcr0_features) - { - switch (xcr0 & X86_XSTATE_ALL_MASK) - { - case X86_XSTATE_AVX512_MASK: - return tdesc_x32_avx512_linux; - - case X86_XSTATE_MPX_MASK: /* No MPX on x32. */ - case X86_XSTATE_AVX_MASK: - return tdesc_x32_avx_linux; - - default: - return tdesc_x32_linux; - } - } - else - return tdesc_x32_linux; + tdesc = amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK, + !is_elf64); } + + if (tdesc == NULL) + tdesc = amd64_linux_read_description (X86_XSTATE_SSE_MASK, !is_elf64); + return tdesc; #endif } else { - if (xcr0_features) - { - switch (xcr0 & X86_XSTATE_ALL_MASK) - { - case (X86_XSTATE_AVX512_MASK): - return tdesc_i386_avx512_linux; + const target_desc *tdesc = NULL; - case (X86_XSTATE_MPX_MASK): - return tdesc_i386_mpx_linux; - - case (X86_XSTATE_AVX_MPX_MASK): - return tdesc_i386_avx_mpx_linux; + if (xcr0_features) + tdesc = i386_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK); - case (X86_XSTATE_AVX_MASK): - return tdesc_i386_avx_linux; + if (tdesc == NULL) + tdesc = i386_linux_read_description (X86_XSTATE_SSE); - default: - return tdesc_i386_linux; - } - } - else - return tdesc_i386_linux; + return tdesc; } gdb_assert_not_reached ("failed to return tdesc"); } -/* Callback for find_inferior. Stops iteration when a thread with a - given PID is found. */ - -static int -same_process_callback (struct inferior_list_entry *entry, void *data) -{ - int pid = *(int *) data; - - return (ptid_get_pid (entry->id) == pid); -} - -/* Callback for for_each_inferior. Calls the arch_setup routine for - each process. */ - -static void -x86_arch_setup_process_callback (struct inferior_list_entry *entry) -{ - int pid = ptid_get_pid (entry->id); - - /* Look up any thread of this processes. */ - current_thread - = (struct thread_info *) find_inferior (&all_threads, - same_process_callback, &pid); - - the_low_target.arch_setup (); -} - /* Update all the target description of all processes; a new GDB connected, and it may or not support xml target descriptions. */ @@ -900,7 +881,14 @@ x86_linux_update_xmltarget (void) release the current regcache objects. */ regcache_release (); - for_each_inferior (&all_processes, x86_arch_setup_process_callback); + for_each_process ([] (process_info *proc) { + int pid = proc->pid; + + /* Look up any thread of this process. */ + current_thread = find_any_thread_of_pid (pid); + + the_low_target.arch_setup (); + }); current_thread = saved_thread; } @@ -924,9 +912,11 @@ x86_linux_process_qsupported (char **features, int count) if (startswith (feature, "xmlRegisters=")) { char *copy = xstrdup (feature + 13); - char *p; - for (p = strtok (copy, ","); p != NULL; p = strtok (NULL, ",")) + char *saveptr; + for (char *p = strtok_r (copy, ",", &saveptr); + p != NULL; + p = strtok_r (NULL, ",", &saveptr)) { if (strcmp (p, "i386") == 0) { @@ -1019,12 +1009,12 @@ x86_supports_tracepoints (void) static void append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf) { - write_inferior_memory (*to, buf, len); + target_write_memory (*to, buf, len); *to += len; } static int -push_opcode (unsigned char *buf, char *op) +push_opcode (unsigned char *buf, const char *op) { unsigned char *buf_org = buf; @@ -1397,7 +1387,7 @@ i386_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr, offset = *jump_entry - (*trampoline + sizeof (jump_insn)); memcpy (buf, jump_insn, sizeof (jump_insn)); memcpy (buf + 1, &offset, 4); - write_inferior_memory (*trampoline, buf, sizeof (jump_insn)); + target_write_memory (*trampoline, buf, sizeof (jump_insn)); /* Use a 16-bit relative jump instruction to jump to the trampoline. */ offset = (*trampoline - (tpaddr + sizeof (small_jump_insn))) & 0xffff; @@ -1493,7 +1483,7 @@ x86_get_min_fast_tracepoint_insn_len (void) mention that something has gone awry. */ if (!warned_about_fast_tracepoints) { - warning ("4-byte fast tracepoints not available; %s\n", errbuf); + warning ("4-byte fast tracepoints not available; %s", errbuf); warned_about_fast_tracepoints = 1; } return 5; @@ -1792,7 +1782,7 @@ amd64_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size) } memcpy (buf, &diff, sizeof (int)); - write_inferior_memory (from, buf, sizeof (int)); + target_write_memory (from, buf, sizeof (int)); } static void @@ -2410,7 +2400,7 @@ i386_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size) } memcpy (buf, &diff, sizeof (int)); - write_inferior_memory (from, buf, sizeof (int)); + target_write_memory (from, buf, sizeof (int)); } static void @@ -2854,33 +2844,13 @@ x86_get_ipa_tdesc_idx (void) const struct target_desc *tdesc = regcache->tdesc; #ifdef __x86_64__ - if (tdesc == tdesc_amd64_linux || tdesc == tdesc_amd64_linux_no_xml - || tdesc == tdesc_x32_linux) - return X86_TDESC_SSE; - if (tdesc == tdesc_amd64_avx_linux || tdesc == tdesc_x32_avx_linux) - return X86_TDESC_AVX; - if (tdesc == tdesc_amd64_mpx_linux) - return X86_TDESC_MPX; - if (tdesc == tdesc_amd64_avx_mpx_linux) - return X86_TDESC_AVX_MPX; - if (tdesc == tdesc_amd64_avx512_linux || tdesc == tdesc_x32_avx512_linux) - return X86_TDESC_AVX512; + return amd64_get_ipa_tdesc_idx (tdesc); #endif - if (tdesc == tdesc_i386_mmx_linux) - return X86_TDESC_MMX; - if (tdesc == tdesc_i386_linux || tdesc == tdesc_i386_linux_no_xml) + if (tdesc == tdesc_i386_linux_no_xml) return X86_TDESC_SSE; - if (tdesc == tdesc_i386_avx_linux) - return X86_TDESC_AVX; - if (tdesc == tdesc_i386_mpx_linux) - return X86_TDESC_MPX; - if (tdesc == tdesc_i386_avx_mpx_linux) - return X86_TDESC_AVX_MPX; - if (tdesc == tdesc_i386_avx512_linux) - return X86_TDESC_AVX512; - return 0; + return i386_get_ipa_tdesc_idx (tdesc); } /* This is initialized assuming an amd64 target. @@ -2913,7 +2883,9 @@ struct linux_target_ops the_low_target = /* need to fix up i386 siginfo if host is amd64 */ x86_siginfo_fixup, x86_linux_new_process, + x86_linux_delete_process, x86_linux_new_thread, + x86_linux_delete_thread, x86_linux_new_fork, x86_linux_prepare_to_resume, x86_linux_process_qsupported, @@ -2934,29 +2906,16 @@ initialize_low_arch (void) { /* Initialize the Linux target descriptions. */ #ifdef __x86_64__ - init_registers_amd64_linux (); - init_registers_amd64_avx_linux (); - init_registers_amd64_avx512_linux (); - init_registers_amd64_mpx_linux (); - init_registers_amd64_avx_mpx_linux (); - - init_registers_x32_linux (); - init_registers_x32_avx_linux (); - init_registers_x32_avx512_linux (); - - tdesc_amd64_linux_no_xml = XNEW (struct target_desc); - copy_target_description (tdesc_amd64_linux_no_xml, tdesc_amd64_linux); + tdesc_amd64_linux_no_xml = allocate_target_description (); + copy_target_description (tdesc_amd64_linux_no_xml, + amd64_linux_read_description (X86_XSTATE_SSE_MASK, + false)); tdesc_amd64_linux_no_xml->xmltarget = xmltarget_amd64_linux_no_xml; #endif - init_registers_i386_linux (); - init_registers_i386_mmx_linux (); - init_registers_i386_avx_linux (); - init_registers_i386_avx512_linux (); - init_registers_i386_mpx_linux (); - init_registers_i386_avx_mpx_linux (); - - tdesc_i386_linux_no_xml = XNEW (struct target_desc); - copy_target_description (tdesc_i386_linux_no_xml, tdesc_i386_linux); + + tdesc_i386_linux_no_xml = allocate_target_description (); + copy_target_description (tdesc_i386_linux_no_xml, + i386_linux_read_description (X86_XSTATE_SSE_MASK)); tdesc_i386_linux_no_xml->xmltarget = xmltarget_i386_linux_no_xml; initialize_regsets_info (&x86_regsets_info);