X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Flinux-i386-ipa.c;h=6cf4e45b48b09befe7f1cc63cca340c8547d3716;hb=476350ba4800f1144b125f6511a5e25b223cc90b;hp=7af7924f0a4cf57f283d863a26172198a9221cd1;hpb=6a271cae85843023ce9c046c040b643158d85054;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c
index 7af7924f0a..6cf4e45b48 100644
--- a/gdb/gdbserver/linux-i386-ipa.c
+++ b/gdb/gdbserver/linux-i386-ipa.c
@@ -1,7 +1,7 @@
/* GNU/Linux/x86 specific low level interface, for the in-process
agent library for GDB.
- Copyright (C) 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2016 Free Software Foundation, Inc.
This file is part of GDB.
@@ -19,6 +19,9 @@
along with this program. If not, see . */
#include "server.h"
+#include
+#include "tracepoint.h"
+#include "linux-x86-tdesc.h"
/* GDB register numbers. */
@@ -45,9 +48,6 @@ enum i386_gdb_regnum
#define i386_num_regs 16
-/* Defined in auto-generated file i386-linux.c. */
-void init_registers_i386_linux (void);
-
#define FT_CR_EAX 15
#define FT_CR_ECX 14
#define FT_CR_EDX 13
@@ -95,8 +95,8 @@ supply_fast_tracepoint_registers (struct regcache *regcache,
}
}
-ULONGEST __attribute__ ((visibility("default"), used))
-gdb_agent_get_raw_reg (unsigned char *raw_regs, int regnum)
+ULONGEST
+get_raw_reg (const unsigned char *raw_regs, int regnum)
{
/* This should maybe be allowed to return an error code, or perhaps
better, have the emit_reg detect this, and emit a constant zero,
@@ -110,12 +110,189 @@ gdb_agent_get_raw_reg (unsigned char *raw_regs, int regnum)
return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
}
+#ifdef HAVE_UST
+
+#include
+
+/* "struct registers" is the UST object type holding the registers at
+ the time of the static tracepoint marker call. This doesn't
+ contain EIP, but we know what it must have been (the marker
+ address). */
+
+#define ST_REGENTRY(REG) \
+ { \
+ offsetof (struct registers, REG), \
+ sizeof (((struct registers *) NULL)->REG) \
+ }
+
+static struct
+{
+ int offset;
+ int size;
+} i386_st_collect_regmap[] =
+ {
+ ST_REGENTRY(eax),
+ ST_REGENTRY(ecx),
+ ST_REGENTRY(edx),
+ ST_REGENTRY(ebx),
+ ST_REGENTRY(esp),
+ ST_REGENTRY(ebp),
+ ST_REGENTRY(esi),
+ ST_REGENTRY(edi),
+ { -1, 0 }, /* eip */
+ ST_REGENTRY(eflags),
+ ST_REGENTRY(cs),
+ ST_REGENTRY(ss),
+ };
+
+#define i386_NUM_ST_COLLECT_GREGS \
+ (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
+
+void
+supply_static_tracepoint_registers (struct regcache *regcache,
+ const unsigned char *buf,
+ CORE_ADDR pc)
+{
+ int i;
+ unsigned int newpc = pc;
+
+ supply_register (regcache, I386_EIP_REGNUM, &newpc);
+
+ for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
+ if (i386_st_collect_regmap[i].offset != -1)
+ {
+ switch (i386_st_collect_regmap[i].size)
+ {
+ case 4:
+ supply_register (regcache, i,
+ ((char *) buf)
+ + i386_st_collect_regmap[i].offset);
+ break;
+ case 2:
+ {
+ unsigned long reg
+ = * (short *) (((char *) buf)
+ + i386_st_collect_regmap[i].offset);
+ reg &= 0xffff;
+ supply_register (regcache, i, ®);
+ }
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "unhandled register size: %d",
+ i386_st_collect_regmap[i].size);
+ }
+ }
+}
+
+#endif /* HAVE_UST */
+
+
/* This is only needed because reg-i386-linux-lib.o references it. We
may use it proper at some point. */
const char *gdbserver_xmltarget;
+/* Attempt to allocate memory for trampolines in the first 64 KiB of
+ memory to enable smaller jump patches. */
+
+static void
+initialize_fast_tracepoint_trampoline_buffer (void)
+{
+ const CORE_ADDR buffer_end = 64 * 1024;
+ /* Ensure that the buffer will be at least 1 KiB in size, which is
+ enough space for over 200 fast tracepoints. */
+ const int min_buffer_size = 1024;
+ char buf[IPA_BUFSIZ];
+ CORE_ADDR mmap_min_addr = buffer_end + 1;
+ ULONGEST buffer_size;
+ FILE *f = fopen ("/proc/sys/vm/mmap_min_addr", "r");
+
+ if (!f)
+ {
+ snprintf (buf, sizeof (buf), "mmap_min_addr open failed: %s",
+ strerror (errno));
+ set_trampoline_buffer_space (0, 0, buf);
+ return;
+ }
+
+ if (fgets (buf, IPA_BUFSIZ, f))
+ sscanf (buf, "%llu", &mmap_min_addr);
+
+ fclose (f);
+
+ buffer_size = buffer_end - mmap_min_addr;
+
+ if (buffer_size >= min_buffer_size)
+ {
+ if (mmap ((void *) (uintptr_t) mmap_min_addr, buffer_size,
+ PROT_READ | PROT_EXEC | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0)
+ != MAP_FAILED)
+ set_trampoline_buffer_space (mmap_min_addr, buffer_end, NULL);
+ else
+ {
+ snprintf (buf, IPA_BUFSIZ, "low-64K-buffer mmap() failed: %s",
+ strerror (errno));
+ set_trampoline_buffer_space (0, 0, buf);
+ }
+ }
+ else
+ {
+ snprintf (buf, IPA_BUFSIZ, "mmap_min_addr is %d, must be %d or less",
+ (int) mmap_min_addr, (int) buffer_end - min_buffer_size);
+ set_trampoline_buffer_space (0, 0, buf);
+ }
+}
+
+/* Return target_desc to use for IPA, given the tdesc index passed by
+ gdbserver. */
+
+const struct target_desc *
+get_ipa_tdesc (int idx)
+{
+ switch (idx)
+ {
+ case X86_TDESC_MMX:
+ return tdesc_i386_mmx_linux;
+ case X86_TDESC_SSE:
+ return tdesc_i386_linux;
+ case X86_TDESC_AVX:
+ return tdesc_i386_avx_linux;
+ case X86_TDESC_MPX:
+ return tdesc_i386_mpx_linux;
+ case X86_TDESC_AVX_MPX:
+ return tdesc_i386_avx_mpx_linux;
+ case X86_TDESC_AVX512:
+ return tdesc_i386_avx512_linux;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "unknown ipa tdesc index: %d", idx);
+ return tdesc_i386_linux;
+ }
+}
+
+/* Allocate buffer for the jump pads. On i386, we can reach an arbitrary
+ address with a jump instruction, so just allocate normally. */
+
+void *
+alloc_jump_pad_buffer (size_t size)
+{
+ void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ if (res == MAP_FAILED)
+ return NULL;
+
+ return res;
+}
+
void
initialize_low_tracepoint (void)
{
+ init_registers_i386_mmx_linux ();
init_registers_i386_linux ();
+ init_registers_i386_avx_linux ();
+ init_registers_i386_mpx_linux ();
+ init_registers_i386_avx512_linux ();
+ initialize_fast_tracepoint_trampoline_buffer ();
}