X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Flinux-x86-low.c;h=cb0169c4bd5649b82b87497738dbba26d4a6e36b;hb=268a13a5a3f7c6b9b6ffc5ac2d1b24eb41f3fbdc;hp=1ba98ba4e07a51ab1d57d13d542c51c24d7a6071;hpb=c8ef42eed100c2439e600e846caa7437da93ac17;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 1ba98ba4e0..cb0169c4bd 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-2016 Free Software Foundation, Inc. + Copyright (C) 2002-2019 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])) @@ -186,7 +191,7 @@ is_64bit_tdesc (void) /* Called by libthread_db. */ ps_err_e -ps_get_thread_area (const struct ps_prochandle *ph, +ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx, void **base) { #ifdef __x86_64__ @@ -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; } @@ -1024,7 +1012,7 @@ append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf) } static int -push_opcode (unsigned char *buf, char *op) +push_opcode (unsigned char *buf, const char *op) { unsigned char *buf_org = buf; @@ -1493,7 +1481,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; @@ -1842,6 +1830,8 @@ amd64_emit_call (CORE_ADDR fn) else { int offset32 = offset64; /* we know we can't overflow here. */ + + buf[i++] = 0xe8; /* call */ memcpy (buf + i, &offset32, 4); i += 4; } @@ -2852,33 +2842,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. @@ -2911,7 +2881,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, @@ -2932,29 +2904,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);