Index: gdb/gdbserver/linux-x86-low.c |
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c |
index 4ea284eebafd16fea56c1ea5165dbe203ece2e30..e8505bf0e83b65aad4f4fab7e6ae6d46646a5477 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, 2004-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2002-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -30,21 +30,54 @@ |
#include "gdb_proc_service.h" |
#include "agent.h" |
+#include "tdesc.h" |
+#include "tracepoint.h" |
+#include "ax.h" |
-/* Defined in auto-generated file i386-linux.c. */ |
-void init_registers_i386_linux (void); |
+#ifdef __x86_64__ |
/* Defined in auto-generated file amd64-linux.c. */ |
void init_registers_amd64_linux (void); |
-/* Defined in auto-generated file i386-avx-linux.c. */ |
-void init_registers_i386_avx_linux (void); |
+extern const struct target_desc *tdesc_amd64_linux; |
+ |
/* Defined in auto-generated file amd64-avx-linux.c. */ |
void init_registers_amd64_avx_linux (void); |
-/* Defined in auto-generated file i386-mmx-linux.c. */ |
-void init_registers_i386_mmx_linux (void); |
+extern const struct target_desc *tdesc_amd64_avx_linux; |
+ |
+/* Defined in auto-generated file amd64-mpx-linux.c. */ |
+void init_registers_amd64_mpx_linux (void); |
+extern const struct target_desc *tdesc_amd64_mpx_linux; |
+ |
/* Defined in auto-generated file x32-linux.c. */ |
void init_registers_x32_linux (void); |
+extern const struct target_desc *tdesc_x32_linux; |
+ |
/* Defined in auto-generated file x32-avx-linux.c. */ |
void init_registers_x32_avx_linux (void); |
+extern const struct target_desc *tdesc_x32_avx_linux; |
+ |
+#endif |
+ |
+/* Defined in auto-generated file i386-linux.c. */ |
+void init_registers_i386_linux (void); |
+extern const struct target_desc *tdesc_i386_linux; |
+ |
+/* Defined in auto-generated file i386-mmx-linux.c. */ |
+void init_registers_i386_mmx_linux (void); |
+extern const struct target_desc *tdesc_i386_mmx_linux; |
+ |
+/* Defined in auto-generated file i386-avx-linux.c. */ |
+void init_registers_i386_avx_linux (void); |
+extern const struct target_desc *tdesc_i386_avx_linux; |
+ |
+/* Defined in auto-generated file i386-mpx-linux.c. */ |
+void init_registers_i386_mpx_linux (void); |
+extern const struct target_desc *tdesc_i386_mpx_linux; |
+ |
+#ifdef __x86_64__ |
+static struct target_desc *tdesc_amd64_linux_no_xml; |
+#endif |
+static struct target_desc *tdesc_i386_linux_no_xml; |
+ |
static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 }; |
static unsigned char small_jump_insn[] = { 0x66, 0xe9, 0, 0 }; |
@@ -139,8 +172,11 @@ static const int x86_64_regmap[] = |
-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, |
- ORIG_RAX * 8 |
+ -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, |
+ ORIG_RAX * 8, |
+ -1, -1, -1, -1, /* MPX registers BND0 ... BND3. */ |
+ -1, -1 /* MPX registers BNDCFGU, BNDSTATUS. */ |
}; |
#define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0])) |
@@ -160,6 +196,22 @@ static /*const*/ int i386_regmap[] = |
#define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0])) |
#endif |
+ |
+#ifdef __x86_64__ |
+ |
+/* Returns true if the current inferior belongs to a x86-64 process, |
+ per the tdesc. */ |
+ |
+static int |
+is_64bit_tdesc (void) |
+{ |
+ struct regcache *regcache = get_thread_regcache (current_inferior, 0); |
+ |
+ return register_size (regcache->tdesc, 0) == 8; |
+} |
+ |
+#endif |
+ |
/* Called by libthread_db. */ |
@@ -168,7 +220,7 @@ ps_get_thread_area (const struct ps_prochandle *ph, |
lwpid_t lwpid, int idx, void **base) |
{ |
#ifdef __x86_64__ |
- int use_64bit = register_size (0) == 8; |
+ int use_64bit = is_64bit_tdesc (); |
if (use_64bit) |
{ |
@@ -196,7 +248,8 @@ ps_get_thread_area (const struct ps_prochandle *ph, |
(void *) (intptr_t) idx, (unsigned long) &desc) < 0) |
return PS_ERR; |
- *(int *)base = desc[1]; |
+ /* Ensure we properly extend the value to 64-bits for x86_64. */ |
+ *base = (void *) (uintptr_t) desc[1]; |
return PS_OK; |
} |
} |
@@ -210,7 +263,7 @@ static int |
x86_get_thread_area (int lwpid, CORE_ADDR *addr) |
{ |
#ifdef __x86_64__ |
- int use_64bit = register_size (0) == 8; |
+ int use_64bit = is_64bit_tdesc (); |
if (use_64bit) |
{ |
@@ -250,14 +303,24 @@ x86_get_thread_area (int lwpid, CORE_ADDR *addr) |
static int |
-i386_cannot_store_register (int regno) |
+x86_cannot_store_register (int regno) |
{ |
+#ifdef __x86_64__ |
+ if (is_64bit_tdesc ()) |
+ return 0; |
+#endif |
+ |
return regno >= I386_NUM_REGS; |
} |
static int |
-i386_cannot_fetch_register (int regno) |
+x86_cannot_fetch_register (int regno) |
{ |
+#ifdef __x86_64__ |
+ if (is_64bit_tdesc ()) |
+ return 0; |
+#endif |
+ |
return regno >= I386_NUM_REGS; |
} |
@@ -267,7 +330,7 @@ x86_fill_gregset (struct regcache *regcache, void *buf) |
int i; |
#ifdef __x86_64__ |
- if (register_size (0) == 8) |
+ if (register_size (regcache->tdesc, 0) == 8) |
{ |
for (i = 0; i < X86_64_NUM_REGS; i++) |
if (x86_64_regmap[i] != -1) |
@@ -289,7 +352,7 @@ x86_store_gregset (struct regcache *regcache, const void *buf) |
int i; |
#ifdef __x86_64__ |
- if (register_size (0) == 8) |
+ if (register_size (regcache->tdesc, 0) == 8) |
{ |
for (i = 0; i < X86_64_NUM_REGS; i++) |
if (x86_64_regmap[i] != -1) |
@@ -358,11 +421,9 @@ x86_store_xstateregset (struct regcache *regcache, const void *buf) |
This is, presumably, to handle the case where PTRACE_[GS]ETFPXREGS |
doesn't work. IWBN to avoid the duplication in the case where it |
does work. Maybe the arch_setup routine could check whether it works |
- and update target_regsets accordingly, maybe by moving target_regsets |
- to linux_target_ops and set the right one there, rather than having to |
- modify the target_regsets global. */ |
+ and update the supported regsets accordingly. */ |
-struct regset_info target_regsets[] = |
+static struct regset_info x86_regsets[] = |
{ |
#ifdef HAVE_PTRACE_GETREGS |
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t), |
@@ -387,7 +448,7 @@ struct regset_info target_regsets[] = |
static CORE_ADDR |
x86_get_pc (struct regcache *regcache) |
{ |
- int use_64bit = register_size (0) == 8; |
+ int use_64bit = register_size (regcache->tdesc, 0) == 8; |
if (use_64bit) |
{ |
@@ -406,7 +467,7 @@ x86_get_pc (struct regcache *regcache) |
static void |
x86_set_pc (struct regcache *regcache, CORE_ADDR pc) |
{ |
- int use_64bit = register_size (0) == 8; |
+ int use_64bit = register_size (regcache->tdesc, 0) == 8; |
if (use_64bit) |
{ |
@@ -561,7 +622,7 @@ x86_insert_point (char type, CORE_ADDR addr, int len) |
struct process_info *proc = current_process (); |
switch (type) |
{ |
- case '0': |
+ case '0': /* software-breakpoint */ |
{ |
int ret; |
@@ -572,11 +633,13 @@ x86_insert_point (char type, CORE_ADDR addr, int len) |
done_accessing_memory (); |
return ret; |
} |
- case '2': |
- case '3': |
- case '4': |
+ case '1': /* hardware-breakpoint */ |
+ case '2': /* write watchpoint */ |
+ case '3': /* read watchpoint */ |
+ case '4': /* access watchpoint */ |
return i386_low_insert_watchpoint (&proc->private->arch_private->debug_reg_state, |
type, addr, len); |
+ |
default: |
/* Unsupported. */ |
return 1; |
@@ -589,7 +652,7 @@ x86_remove_point (char type, CORE_ADDR addr, int len) |
struct process_info *proc = current_process (); |
switch (type) |
{ |
- case '0': |
+ case '0': /* software-breakpoint */ |
{ |
int ret; |
@@ -600,9 +663,10 @@ x86_remove_point (char type, CORE_ADDR addr, int len) |
done_accessing_memory (); |
return ret; |
} |
- case '2': |
- case '3': |
- case '4': |
+ case '1': /* hardware-breakpoint */ |
+ case '2': /* write watchpoint */ |
+ case '3': /* read watchpoint */ |
+ case '4': /* access watchpoint */ |
return i386_low_remove_watchpoint (&proc->private->arch_private->debug_reg_state, |
type, addr, len); |
default: |
@@ -1088,8 +1152,6 @@ siginfo_from_compat_x32_siginfo (siginfo_t *to, |
} |
} |
-/* Is this process 64-bit? */ |
-static int linux_is_elf64; |
#endif /* __x86_64__ */ |
/* Convert a native/host siginfo object, into/from the siginfo in the |
@@ -1102,8 +1164,12 @@ static int |
x86_siginfo_fixup (siginfo_t *native, void *inf, int direction) |
{ |
#ifdef __x86_64__ |
+ unsigned int machine; |
+ int tid = lwpid_of (get_thread_lwp (current_inferior)); |
+ int is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine); |
+ |
/* Is the inferior 32-bit? If so, then fixup the siginfo object. */ |
- if (register_size (0) == 4) |
+ if (!is_64bit_tdesc ()) |
{ |
if (sizeof (siginfo_t) != sizeof (compat_siginfo_t)) |
fatal ("unexpected difference in siginfo"); |
@@ -1116,7 +1182,7 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction) |
return 1; |
} |
/* No fixup for native x32 GDB. */ |
- else if (!linux_is_elf64 && sizeof (void *) == 8) |
+ else if (!is_elf64 && sizeof (void *) == 8) |
{ |
if (sizeof (siginfo_t) != sizeof (compat_x32_siginfo_t)) |
fatal ("unexpected difference in siginfo"); |
@@ -1137,138 +1203,240 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction) |
static int use_xml; |
-/* Update gdbserver_xmltarget. */ |
+/* Format of XSAVE extended state is: |
+ struct |
+ { |
+ fxsave_bytes[0..463] |
+ sw_usable_bytes[464..511] |
+ xstate_hdr_bytes[512..575] |
+ avx_bytes[576..831] |
+ future_state etc |
+ }; |
+ |
+ Same memory layout will be used for the coredump NT_X86_XSTATE |
+ representing the XSAVE extended state registers. |
+ |
+ The first 8 bytes of the sw_usable_bytes[464..467] is the OS enabled |
+ extended state mask, which is the same as the extended control register |
+ 0 (the XFEATURE_ENABLED_MASK register), XCR0. We can use this mask |
+ together with the mask saved in the xstate_hdr_bytes to determine what |
+ states the processor/OS supports and what state, used or initialized, |
+ the process/thread is in. */ |
+#define I386_LINUX_XSAVE_XCR0_OFFSET 464 |
+ |
+/* Does the current host support the GETFPXREGS request? The header |
+ file may or may not define it, and even if it is defined, the |
+ kernel will return EIO if it's running on a pre-SSE processor. */ |
+int have_ptrace_getfpxregs = |
+#ifdef HAVE_PTRACE_GETFPXREGS |
+ -1 |
+#else |
+ 0 |
+#endif |
+; |
-static void |
-x86_linux_update_xmltarget (void) |
+/* Does the current host support PTRACE_GETREGSET? */ |
+static int have_ptrace_getregset = -1; |
+ |
+/* Get Linux/x86 target description from running target. */ |
+ |
+static const struct target_desc * |
+x86_linux_read_description (void) |
{ |
- int pid; |
+ unsigned int machine; |
+ int is_elf64; |
+ int xcr0_features; |
+ int tid; |
+ static uint64_t xcr0; |
struct regset_info *regset; |
- static unsigned long long xcr0; |
- static int have_ptrace_getregset = -1; |
-#if !defined(__x86_64__) && defined(HAVE_PTRACE_GETFPXREGS) |
- static int have_ptrace_getfpxregs = -1; |
-#endif |
- if (!current_inferior) |
- return; |
+ tid = lwpid_of (get_thread_lwp (current_inferior)); |
- /* Before changing the register cache internal layout or the target |
- regsets, flush the contents of the current valid caches back to |
- the threads. */ |
- regcache_invalidate (); |
+ is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine); |
- pid = pid_of (get_thread_lwp (current_inferior)); |
-#ifdef __x86_64__ |
- if (num_xmm_registers == 8) |
- init_registers_i386_linux (); |
- else if (linux_is_elf64) |
- init_registers_amd64_linux (); |
- else |
- init_registers_x32_linux (); |
-#else |
+ if (sizeof (void *) == 4) |
{ |
-# ifdef HAVE_PTRACE_GETFPXREGS |
- if (have_ptrace_getfpxregs == -1) |
- { |
- elf_fpxregset_t fpxregs; |
+ if (is_elf64 > 0) |
+ error (_("Can't debug 64-bit process with 32-bit GDBserver")); |
+#ifndef __x86_64__ |
+ else if (machine == EM_X86_64) |
+ error (_("Can't debug x86-64 process with 32-bit GDBserver")); |
+#endif |
+ } |
- if (ptrace (PTRACE_GETFPXREGS, pid, 0, (int) &fpxregs) < 0) |
- { |
- have_ptrace_getfpxregs = 0; |
- x86_xcr0 = I386_XSTATE_X87_MASK; |
- |
- /* Disable PTRACE_GETFPXREGS. */ |
- for (regset = target_regsets; |
- regset->fill_function != NULL; regset++) |
- if (regset->get_request == PTRACE_GETFPXREGS) |
- { |
- regset->size = 0; |
- break; |
- } |
- } |
- else |
- have_ptrace_getfpxregs = 1; |
- } |
+#if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS |
+ if (machine == EM_386 && have_ptrace_getfpxregs == -1) |
+ { |
+ elf_fpxregset_t fpxregs; |
- if (!have_ptrace_getfpxregs) |
+ if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0) |
{ |
- init_registers_i386_mmx_linux (); |
- return; |
+ have_ptrace_getfpxregs = 0; |
+ have_ptrace_getregset = 0; |
+ return tdesc_i386_mmx_linux; |
} |
-# endif |
- init_registers_i386_linux (); |
+ else |
+ have_ptrace_getfpxregs = 1; |
} |
#endif |
if (!use_xml) |
{ |
+ x86_xcr0 = I386_XSTATE_SSE_MASK; |
+ |
/* Don't use XML. */ |
#ifdef __x86_64__ |
- if (num_xmm_registers == 8) |
- gdbserver_xmltarget = xmltarget_i386_linux_no_xml; |
+ if (machine == EM_X86_64) |
+ return tdesc_amd64_linux_no_xml; |
else |
- gdbserver_xmltarget = xmltarget_amd64_linux_no_xml; |
-#else |
- gdbserver_xmltarget = xmltarget_i386_linux_no_xml; |
#endif |
- |
- x86_xcr0 = I386_XSTATE_SSE_MASK; |
- |
- return; |
+ return tdesc_i386_linux_no_xml; |
} |
- /* Check if XSAVE extended state is supported. */ |
if (have_ptrace_getregset == -1) |
{ |
- unsigned long long xstateregs[I386_XSTATE_SSE_SIZE / sizeof (long long)]; |
+ uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; |
struct iovec iov; |
iov.iov_base = xstateregs; |
iov.iov_len = sizeof (xstateregs); |
/* Check if PTRACE_GETREGSET works. */ |
- if (ptrace (PTRACE_GETREGSET, pid, (unsigned int) NT_X86_XSTATE, |
- &iov) < 0) |
+ if (ptrace (PTRACE_GETREGSET, tid, |
+ (unsigned int) NT_X86_XSTATE, (long) &iov) < 0) |
+ have_ptrace_getregset = 0; |
+ else |
{ |
- have_ptrace_getregset = 0; |
- return; |
+ have_ptrace_getregset = 1; |
+ |
+ /* Get XCR0 from XSAVE extended state. */ |
+ xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET |
+ / sizeof (uint64_t))]; |
+ |
+ /* Use PTRACE_GETREGSET if it is available. */ |
+ for (regset = x86_regsets; |
+ regset->fill_function != NULL; regset++) |
+ if (regset->get_request == PTRACE_GETREGSET) |
+ regset->size = I386_XSTATE_SIZE (xcr0); |
+ else if (regset->type != GENERAL_REGS) |
+ regset->size = 0; |
} |
- else |
- have_ptrace_getregset = 1; |
- |
- /* Get XCR0 from XSAVE extended state at byte 464. */ |
- xcr0 = xstateregs[464 / sizeof (long long)]; |
- |
- /* Use PTRACE_GETREGSET if it is available. */ |
- for (regset = target_regsets; |
- regset->fill_function != NULL; regset++) |
- if (regset->get_request == PTRACE_GETREGSET) |
- regset->size = I386_XSTATE_SIZE (xcr0); |
- else if (regset->type != GENERAL_REGS) |
- regset->size = 0; |
} |
- if (have_ptrace_getregset) |
+ /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ |
+ xcr0_features = (have_ptrace_getregset |
+ && (xcr0 & I386_XSTATE_ALL_MASK)); |
+ |
+ if (xcr0_features) |
+ x86_xcr0 = xcr0; |
+ |
+ if (machine == EM_X86_64) |
{ |
- /* AVX is the highest feature we support. */ |
- if ((xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) |
+#ifdef __x86_64__ |
+ if (is_elf64) |
{ |
- x86_xcr0 = xcr0; |
+ if (xcr0_features) |
+ { |
+ switch (xcr0 & I386_XSTATE_ALL_MASK) |
+ { |
+ case I386_XSTATE_MPX_MASK: |
+ return tdesc_amd64_mpx_linux; |
-#ifdef __x86_64__ |
- /* I386 has 8 xmm regs. */ |
- if (num_xmm_registers == 8) |
- init_registers_i386_avx_linux (); |
- else if (linux_is_elf64) |
- init_registers_amd64_avx_linux (); |
+ case I386_XSTATE_AVX_MASK: |
+ return tdesc_amd64_avx_linux; |
+ |
+ default: |
+ return tdesc_amd64_linux; |
+ } |
+ } |
else |
- init_registers_x32_avx_linux (); |
-#else |
- init_registers_i386_avx_linux (); |
+ return tdesc_amd64_linux; |
+ } |
+ else |
+ { |
+ if (xcr0_features) |
+ { |
+ switch (xcr0 & I386_XSTATE_ALL_MASK) |
+ { |
+ case I386_XSTATE_MPX_MASK: /* No MPX on x32. */ |
+ case I386_XSTATE_AVX_MASK: |
+ return tdesc_x32_avx_linux; |
+ |
+ default: |
+ return tdesc_x32_linux; |
+ } |
+ } |
+ else |
+ return tdesc_x32_linux; |
+ } |
#endif |
+ } |
+ else |
+ { |
+ if (xcr0_features) |
+ { |
+ switch (xcr0 & I386_XSTATE_ALL_MASK) |
+ { |
+ case (I386_XSTATE_MPX_MASK): |
+ return tdesc_i386_mpx_linux; |
+ |
+ case (I386_XSTATE_AVX_MASK): |
+ return tdesc_i386_avx_linux; |
+ |
+ default: |
+ return tdesc_i386_linux; |
+ } |
} |
+ else |
+ return tdesc_i386_linux; |
} |
+ |
+ 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_inferior |
+ = (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. */ |
+ |
+static void |
+x86_linux_update_xmltarget (void) |
+{ |
+ struct thread_info *save_inferior = current_inferior; |
+ |
+ /* Before changing the register cache's internal layout, flush the |
+ contents of the current valid caches back to the threads, and |
+ release the current regcache objects. */ |
+ regcache_release (); |
+ |
+ for_each_inferior (&all_processes, x86_arch_setup_process_callback); |
+ |
+ current_inferior = save_inferior; |
} |
/* Process qSupported query, "xmlRegisters=". Update the buffer size for |
@@ -1301,62 +1469,54 @@ x86_linux_process_qsupported (const char *query) |
x86_linux_update_xmltarget (); |
} |
-/* Initialize gdbserver for the architecture of the inferior. */ |
- |
-static void |
-x86_arch_setup (void) |
-{ |
- int pid = pid_of (get_thread_lwp (current_inferior)); |
- unsigned int machine; |
- int is_elf64 = linux_pid_exe_is_elf_64_file (pid, &machine); |
+/* Common for x86/x86-64. */ |
- if (sizeof (void *) == 4) |
- { |
- if (is_elf64 > 0) |
- error (_("Can't debug 64-bit process with 32-bit GDBserver")); |
-#ifndef __x86_64__ |
- else if (machine == EM_X86_64) |
- error (_("Can't debug x86-64 process with 32-bit GDBserver")); |
-#endif |
- } |
+static struct regsets_info x86_regsets_info = |
+ { |
+ x86_regsets, /* regsets */ |
+ 0, /* num_regsets */ |
+ NULL, /* disabled_regsets */ |
+ }; |
#ifdef __x86_64__ |
- if (is_elf64 < 0) |
- { |
- /* This can only happen if /proc/<pid>/exe is unreadable, |
- but "that can't happen" if we've gotten this far. |
- Fall through and assume this is a 32-bit program. */ |
- } |
- else if (machine == EM_X86_64) |
- { |
- /* Amd64 doesn't have HAVE_LINUX_USRREGS. */ |
- the_low_target.num_regs = -1; |
- the_low_target.regmap = NULL; |
- the_low_target.cannot_fetch_register = NULL; |
- the_low_target.cannot_store_register = NULL; |
- |
- /* Amd64 has 16 xmm regs. */ |
- num_xmm_registers = 16; |
- |
- linux_is_elf64 = is_elf64; |
- x86_linux_update_xmltarget (); |
- return; |
- } |
- |
- linux_is_elf64 = 0; |
+static struct regs_info amd64_linux_regs_info = |
+ { |
+ NULL, /* regset_bitmap */ |
+ NULL, /* usrregs_info */ |
+ &x86_regsets_info |
+ }; |
#endif |
+static struct usrregs_info i386_linux_usrregs_info = |
+ { |
+ I386_NUM_REGS, |
+ i386_regmap, |
+ }; |
- /* Ok we have a 32-bit inferior. */ |
+static struct regs_info i386_linux_regs_info = |
+ { |
+ NULL, /* regset_bitmap */ |
+ &i386_linux_usrregs_info, |
+ &x86_regsets_info |
+ }; |
- the_low_target.num_regs = I386_NUM_REGS; |
- the_low_target.regmap = i386_regmap; |
- the_low_target.cannot_fetch_register = i386_cannot_fetch_register; |
- the_low_target.cannot_store_register = i386_cannot_store_register; |
+const struct regs_info * |
+x86_linux_regs_info (void) |
+{ |
+#ifdef __x86_64__ |
+ if (is_64bit_tdesc ()) |
+ return &amd64_linux_regs_info; |
+ else |
+#endif |
+ return &i386_linux_regs_info; |
+} |
- /* I386 has 8 xmm regs. */ |
- num_xmm_registers = 8; |
+/* Initialize the target description for the architecture of the |
+ inferior. */ |
- x86_linux_update_xmltarget (); |
+static void |
+x86_arch_setup (void) |
+{ |
+ current_process ()->tdesc = x86_linux_read_description (); |
} |
static int |
@@ -1786,7 +1946,7 @@ x86_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr, |
char *err) |
{ |
#ifdef __x86_64__ |
- if (register_size (0) == 8) |
+ if (is_64bit_tdesc ()) |
return amd64_install_fast_tracepoint_jump_pad (tpoint, tpaddr, |
collector, lockaddr, |
orig_size, jump_entry, |
@@ -1820,7 +1980,7 @@ x86_get_min_fast_tracepoint_insn_len (void) |
#ifdef __x86_64__ |
/* On x86-64, 5-byte jump instructions with a 4-byte offset are always |
used for fast tracepoints. */ |
- if (register_size (0) == 8) |
+ if (is_64bit_tdesc ()) |
return 5; |
#endif |
@@ -3163,26 +3323,28 @@ static struct emit_ops * |
x86_emit_ops (void) |
{ |
#ifdef __x86_64__ |
- int use_64bit = register_size (0) == 8; |
- |
- if (use_64bit) |
+ if (is_64bit_tdesc ()) |
return &amd64_emit_ops; |
else |
#endif |
return &i386_emit_ops; |
} |
+static int |
+x86_supports_range_stepping (void) |
+{ |
+ return 1; |
+} |
+ |
/* This is initialized assuming an amd64 target. |
x86_arch_setup will correct it for i386 or amd64 targets. */ |
struct linux_target_ops the_low_target = |
{ |
x86_arch_setup, |
- -1, |
- NULL, |
- NULL, |
- NULL, |
- NULL, |
+ x86_linux_regs_info, |
+ x86_cannot_fetch_register, |
+ x86_cannot_store_register, |
NULL, /* fetch_register */ |
x86_get_pc, |
x86_set_pc, |
@@ -3211,4 +3373,33 @@ struct linux_target_ops the_low_target = |
x86_install_fast_tracepoint_jump_pad, |
x86_emit_ops, |
x86_get_min_fast_tracepoint_insn_len, |
+ x86_supports_range_stepping, |
}; |
+ |
+void |
+initialize_low_arch (void) |
+{ |
+ /* Initialize the Linux target descriptions. */ |
+#ifdef __x86_64__ |
+ init_registers_amd64_linux (); |
+ init_registers_amd64_avx_linux (); |
+ init_registers_amd64_mpx_linux (); |
+ |
+ init_registers_x32_linux (); |
+ init_registers_x32_avx_linux (); |
+ |
+ tdesc_amd64_linux_no_xml = xmalloc (sizeof (struct target_desc)); |
+ copy_target_description (tdesc_amd64_linux_no_xml, tdesc_amd64_linux); |
+ 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_mpx_linux (); |
+ |
+ tdesc_i386_linux_no_xml = xmalloc (sizeof (struct target_desc)); |
+ copy_target_description (tdesc_i386_linux_no_xml, tdesc_i386_linux); |
+ tdesc_i386_linux_no_xml->xmltarget = xmltarget_i386_linux_no_xml; |
+ |
+ initialize_regsets_info (&x86_regsets_info); |
+} |